import type { UseCase } from '@core/shared/application/UseCase';
import type { Logger } from '@core/shared/domain/Logger';
import { Result } from '@core/shared/domain/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import { User } from '../../domain/entities/User';
import { UserRepository } from '../../domain/repositories/UserRepository';

export type GetUserInput = {
  userId: string;
};

export type GetUserResult = {
  user: User;
};

export type GetUserErrorCode = 'USER_NOT_FOUND' | 'REPOSITORY_ERROR';

export type GetUserApplicationError = ApplicationErrorCode<
  GetUserErrorCode,
  { message: string }
>;

export class GetUserUseCase implements UseCase<GetUserInput, GetUserResult, GetUserErrorCode> {
  constructor(
    private readonly userRepo: UserRepository,
    private readonly logger: Logger,
  ) {}

  async execute(input: GetUserInput): Promise<Result<GetUserResult, GetUserApplicationError>> {
    try {
      const stored = await this.userRepo.findById(input.userId);
      if (!stored) {
        return Result.err<GetUserResult, GetUserApplicationError>({
          code: 'USER_NOT_FOUND',
          details: { message: 'User not found' },
        });
      }

      const user = User.fromStored(stored);
      return Result.ok<GetUserResult, GetUserApplicationError>({ user });
    } catch (error) {
      const message =
        error instanceof Error && error.message ? error.message : 'Failed to get user';

      this.logger.error('GetUserUseCase.execute failed', error instanceof Error ? error : undefined, {
        input,
      });

      return Result.err<GetUserResult, GetUserApplicationError>({
        code: 'REPOSITORY_ERROR',
        details: { message },
      });
    }
  }
}