import { Injectable, BadRequestException, Inject } from "@nestjs/common";
import { Logger } from "nestjs-pino";
import { ResidenceCardService } from "@bff/modules/verification/residence-card.service.js";
import { SimServicesService } from "@bff/modules/services/application/sim-services.service.js";
import {
  ValidationErrorCode,
  createValidationError,
  validationFailure,
  validationSuccess,
  type ValidationResult,
} from "./base-validator.interface.js";

/**
 * SIM Order Validator
 *
 * Validates SIM-specific order requirements:
 * - Residence card verification status
 * - Activation fee SKU presence
 */
@Injectable()
export class SimOrderValidator {
  constructor(
    @Inject(Logger) private readonly logger: Logger,
    private readonly residenceCards: ResidenceCardService,
    private readonly simCatalogService: SimServicesService
  ) {}

  /**
   * Validate SIM order requirements
   */
  async validate(userId: string, skus: string[]): Promise<ValidationResult> {
    // Check residence card verification status
    const verification = await this.residenceCards.getStatusForUser(userId);

    if (verification.status === "not_submitted") {
      return validationFailure([
        createValidationError(
          ValidationErrorCode.RESIDENCE_CARD_NOT_SUBMITTED,
          "Residence card submission required for SIM orders. Please upload your residence card and try again."
        ),
      ]);
    }

    if (verification.status === "rejected") {
      return validationFailure([
        createValidationError(
          ValidationErrorCode.RESIDENCE_CARD_REJECTED,
          "Your residence card submission was rejected. Please resubmit your residence card and try again."
        ),
      ]);
    }

    // Check for activation fee SKU
    const activationFees = await this.simCatalogService.getActivationFees();
    const activationSkus = new Set(
      activationFees
        .map(fee => fee.sku?.trim())
        .filter((sku): sku is string => Boolean(sku))
        .map(sku => sku.toUpperCase())
    );

    const hasActivationSku = skus.some(sku => {
      const normalized = sku?.trim().toUpperCase();
      if (!normalized) {
        return false;
      }
      return activationSkus.has(normalized);
    });

    if (!hasActivationSku) {
      this.logger.warn({ skus }, "SIM order missing activation SKU based on catalog metadata");
      return validationFailure([
        createValidationError(
          ValidationErrorCode.SIM_ACTIVATION_FEE_REQUIRED,
          "SIM orders require an activation fee",
          "skus"
        ),
      ]);
    }

    return validationSuccess();
  }

  /**
   * Validate and throw BadRequestException on failure
   */
  async validateOrThrow(userId: string, skus: string[]): Promise<void> {
    const result = await this.validate(userId, skus);

    if (!result.success) {
      const error = result.errors?.[0];
      throw new BadRequestException(error?.message ?? "SIM order validation failed");
    }
  }
}
