import { Inject } from '@nestjs/common';
import { CommandHandler, type ICommandHandler } from '@nestjs/cqrs';
import {
  NotFoundException,
  ValidationException,
  LoggerService,
} from '@modules/shared';
import {
  MEDIA_STORAGE_SERVICE,
  type IMediaStorageService,
} from '../../../../listings/infrastructure/services/media-storage.service';
import { USER_REPOSITORY, type IUserRepository } from '../../../domain/repositories/user.repository';
import { GenerateKycUploadUrlsCommand } from './generate-kyc-upload-urls.command';

const KYC_FOLDER = 'kyc';
const ALLOWED_SUBMIT_STATUSES = new Set(['NONE', 'REJECTED']);
const ALLOWED_MIME_TYPES = new Set(['image/jpeg', 'image/png', 'image/webp']);
const PRESIGNED_URL_EXPIRY_SECONDS = 300; // 5 minutes

export interface KycUploadUrlResult {
  field: string;
  uploadUrl: string;
  publicUrl: string;
  objectKey: string;
}

@CommandHandler(GenerateKycUploadUrlsCommand)
export class GenerateKycUploadUrlsHandler
  implements ICommandHandler<GenerateKycUploadUrlsCommand>
{
  constructor(
    @Inject(USER_REPOSITORY) private readonly userRepo: IUserRepository,
    @Inject(MEDIA_STORAGE_SERVICE) private readonly mediaStorage: IMediaStorageService,
    private readonly logger: LoggerService,
  ) {}

  async execute(command: GenerateKycUploadUrlsCommand): Promise<KycUploadUrlResult[]> {
    const user = await this.userRepo.findById(command.userId);
    if (!user) {
      throw new NotFoundException('Nguoi dung', command.userId);
    }

    if (!ALLOWED_SUBMIT_STATUSES.has(user.kycStatus)) {
      throw new ValidationException(
        'Ban da gui ho so KYC. Vui long cho ket qua xem xet.',
      );
    }

    if (!command.files.length || command.files.length > 3) {
      throw new ValidationException(
        'Vui long cung cap 1-3 file de tai len',
      );
    }

    // Validate MIME types
    for (const file of command.files) {
      if (!ALLOWED_MIME_TYPES.has(file.mimeType)) {
        throw new ValidationException(
          `Dinh dang file khong duoc ho tro: ${file.mimeType}. Chi chap nhan JPEG, PNG, WebP.`,
        );
      }
    }

    const folder = `${KYC_FOLDER}/${command.userId}`;

    const results: KycUploadUrlResult[] = [];
    for (const file of command.files) {
      try {
        const presigned = await this.mediaStorage.generatePresignedUpload(
          folder,
          file.fileName,
          file.mimeType,
          PRESIGNED_URL_EXPIRY_SECONDS,
        );

        results.push({
          field: file.field,
          uploadUrl: presigned.uploadUrl,
          publicUrl: presigned.publicUrl,
          objectKey: presigned.objectKey,
        });
      } catch (error) {
        this.logger.error(
          `Failed to generate presigned URL for KYC ${file.field}: ${error instanceof Error ? error.message : error}`,
          error instanceof Error ? error.stack : undefined,
          'GenerateKycUploadUrlsHandler',
        );
        throw new ValidationException(
          `Khong the tao URL tai len cho ${file.field}`,
        );
      }
    }

    return results;
  }
}
