import { Injectable, BadRequestException, Inject } from "@nestjs/common";
import { Logger } from "nestjs-pino";
import { WhmcsConnectionFacade } from "@bff/integrations/whmcs/facades/whmcs.facade.js";
import { extractErrorMessage } from "@bff/core/utils/error.util.js";
import {
  ValidationErrorCode,
  createValidationError,
  validationFailure,
  validationSuccess,
  type ValidationResult,
} from "./base-validator.interface.js";

/**
 * Payment Validator
 *
 * Validates that a user has a payment method on file in WHMCS before ordering.
 * Follows the same validation pattern as other validators (returns ValidationResult).
 */
@Injectable()
export class PaymentValidator {
  constructor(
    @Inject(Logger) private readonly logger: Logger,
    private readonly whmcs: WhmcsConnectionFacade
  ) {}

  /**
   * Validate that a payment method exists for the WHMCS client
   * Returns validation result indicating if payment method is on file
   */
  async validate(userId: string, whmcsClientId: number): Promise<ValidationResult<void>> {
    try {
      const pay = await this.whmcs.getPaymentMethods({ clientid: whmcsClientId });
      const paymentMethods = Array.isArray(pay.paymethods) ? pay.paymethods : [];

      if (paymentMethods.length === 0) {
        this.logger.warn({ userId, whmcsClientId }, "No payment method on file");
        return validationFailure([
          createValidationError(
            ValidationErrorCode.NO_PAYMENT_METHOD,
            "A payment method is required before ordering"
          ),
        ]);
      }

      this.logger.log(
        { userId, whmcsClientId, count: paymentMethods.length },
        "Payment method verified"
      );
      return validationSuccess();
    } catch (e: unknown) {
      const err = extractErrorMessage(e);
      this.logger.error({ err, userId, whmcsClientId }, "Payment method verification failed");
      return validationFailure([
        createValidationError(
          ValidationErrorCode.VALIDATION_ERROR,
          "Unable to verify payment method. Please try again later."
        ),
      ]);
    }
  }

  /**
   * Validate and throw BadRequestException on failure
   * Use this when you need to fail fast with HTTP error
   */
  async validateOrThrow(userId: string, whmcsClientId: number): Promise<void> {
    const result = await this.validate(userId, whmcsClientId);

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