import { Injectable, BadRequestException, Inject } from "@nestjs/common";
import { Logger } from "nestjs-pino";
import { MappingsService } from "@bff/modules/id-mappings/mappings.service.js";
import {
  ValidationErrorCode,
  createValidationError,
  validationFailure,
  validationSuccess,
  type ValidationResult,
} from "./base-validator.interface.js";

export interface UserMappingData {
  userId: string;
  sfAccountId: string;
  whmcsClientId: number;
}

/**
 * User Mapping Validator
 *
 * Validates that a user has the required account mappings
 * (Salesforce Account ID and WHMCS Client ID) before ordering.
 */
@Injectable()
export class UserMappingValidator {
  constructor(
    @Inject(Logger) private readonly logger: Logger,
    private readonly mappings: MappingsService
  ) {}

  /**
   * Validate user mapping exists and has required IDs
   * Returns validation result with mapping data on success
   */
  async validate(userId: string): Promise<ValidationResult<UserMappingData>> {
    const mapping = await this.mappings.findByUserId(userId);

    if (!mapping) {
      this.logger.warn({ userId }, "User mapping not found");
      return validationFailure([
        createValidationError(
          ValidationErrorCode.USER_MAPPING_NOT_FOUND,
          "User account mapping is required before ordering"
        ),
      ]);
    }

    if (!mapping.whmcsClientId) {
      this.logger.warn({ userId, mapping }, "WHMCS client ID missing from mapping");
      return validationFailure([
        createValidationError(
          ValidationErrorCode.WHMCS_CLIENT_NOT_LINKED,
          "WHMCS integration is required before ordering"
        ),
      ]);
    }

    return validationSuccess({
      userId: mapping.userId,
      sfAccountId: mapping.sfAccountId,
      whmcsClientId: mapping.whmcsClientId,
    });
  }

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

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

    return result.data!;
  }
}
