/**
 * Use Case: SelectAvatarUseCase
 *
 * Handles the business logic for selecting a generated avatar from the options.
 */

import type { IAvatarGenerationRepository } from '../../domain/repositories/IAvatarGenerationRepository';
import type { Logger, UseCaseOutputPort } from '@core/shared/application';
import { Result } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';

export interface SelectAvatarInput {
  requestId: string;
  selectedIndex: number;
}

export interface SelectAvatarResult {
  requestId: string;
  selectedAvatarUrl: string;
}

export type SelectAvatarErrorCode =
  | 'REQUEST_NOT_FOUND'
  | 'REQUEST_NOT_COMPLETED'
  | 'REPOSITORY_ERROR';

export type SelectAvatarApplicationError = ApplicationErrorCode<
  SelectAvatarErrorCode,
  { message: string }
>;

export class SelectAvatarUseCase {
  constructor(
    private readonly avatarRepo: IAvatarGenerationRepository,
    private readonly output: UseCaseOutputPort<SelectAvatarResult>,
    private readonly logger: Logger,
  ) {}

  async execute(input: SelectAvatarInput): Promise<Result<void, SelectAvatarApplicationError>> {
    this.logger.info('[SelectAvatarUseCase] Selecting avatar', {
      requestId: input.requestId,
      selectedIndex: input.selectedIndex,
    });

    try {
      const request = await this.avatarRepo.findById(input.requestId);

      if (!request) {
        return Result.err<void, SelectAvatarApplicationError>({
          code: 'REQUEST_NOT_FOUND',
          details: { message: 'Avatar generation request not found' },
        });
      }

      if (request.status !== 'completed') {
        return Result.err<void, SelectAvatarApplicationError>({
          code: 'REQUEST_NOT_COMPLETED',
          details: { message: 'Avatar generation is not completed yet' },
        });
      }

      request.selectAvatar(input.selectedIndex);
      await this.avatarRepo.save(request);

      const selectedAvatarUrl = request.selectedAvatarUrl!;

      this.output.present({
        requestId: input.requestId,
        selectedAvatarUrl,
      });

      this.logger.info('[SelectAvatarUseCase] Avatar selected successfully', {
        requestId: input.requestId,
        selectedAvatarUrl,
      });

      return Result.ok(undefined);
    } catch (error) {
      const err = error instanceof Error ? error : new Error(String(error));

      this.logger.error('[SelectAvatarUseCase] Error selecting avatar', err, {
        requestId: input.requestId,
      });

      return Result.err({
        code: 'REPOSITORY_ERROR',
        details: { message: err.message ?? 'Unexpected repository error' },
      });
    }
  }
}