import { Injectable, Inject, BadRequestException } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { Logger } from "nestjs-pino";
import { WhmcsClientService } from "@bff/integrations/whmcs/services/whmcs-client.service.js";
import { extractErrorMessage } from "@bff/core/utils/error.util.js";
import { serializeWhmcsKeyValueMap } from "@customer-portal/domain/customer/providers";

export interface CreateWhmcsClientParams {
  email: string;
  password: string;
  firstName: string;
  lastName: string;
  phone: string;
  address: {
    address1: string;
    address2?: string;
    city: string;
    state: string;
    postcode: string;
    country: string;
  };
  customerNumber: string | null;
  company?: string;
  dateOfBirth?: string;
  gender?: string;
  nationality?: string;
}

export interface CreateWhmcsClientResult {
  whmcsClientId: number;
}

/**
 * Step: Create a WHMCS billing client.
 *
 * Calls WhmcsClientService directly with custom-field mapping.
 * Rollback marks the created client as inactive for manual cleanup.
 */
@Injectable()
export class CreateWhmcsClientStep {
  private readonly customerNumberFieldId: string | undefined;
  private readonly dobFieldId: string | undefined;
  private readonly genderFieldId: string | undefined;
  private readonly nationalityFieldId: string | undefined;

  constructor(
    private readonly whmcsClientService: WhmcsClientService,
    configService: ConfigService,
    @Inject(Logger) private readonly logger: Logger
  ) {
    this.customerNumberFieldId = configService.get<string>("WHMCS_CUSTOMER_NUMBER_FIELD_ID");
    this.dobFieldId = configService.get<string>("WHMCS_DOB_FIELD_ID");
    this.genderFieldId = configService.get<string>("WHMCS_GENDER_FIELD_ID");
    this.nationalityFieldId = configService.get<string>("WHMCS_NATIONALITY_FIELD_ID");
  }

  async execute(params: CreateWhmcsClientParams): Promise<CreateWhmcsClientResult> {
    const customfieldsMap: Record<string, string> = {};
    if (this.customerNumberFieldId && params.customerNumber) {
      customfieldsMap[this.customerNumberFieldId] = params.customerNumber;
    }
    if (this.dobFieldId && params.dateOfBirth)
      customfieldsMap[this.dobFieldId] = params.dateOfBirth;
    if (this.genderFieldId && params.gender) customfieldsMap[this.genderFieldId] = params.gender;
    if (this.nationalityFieldId && params.nationality)
      customfieldsMap[this.nationalityFieldId] = params.nationality;

    this.logger.log(
      {
        email: params.email,
        firstName: params.firstName,
        lastName: params.lastName,
        sfNumber: params.customerNumber,
      },
      "Creating WHMCS client"
    );

    try {
      const whmcsClient = await this.whmcsClientService.addClient({
        firstname: params.firstName,
        lastname: params.lastName,
        email: params.email,
        companyname: params.company || "",
        phonenumber: params.phone,
        address1: params.address.address1,
        address2: params.address.address2 ?? "",
        city: params.address.city,
        state: params.address.state,
        postcode: params.address.postcode,
        country: params.address.country,
        password2: params.password,
        customfields: serializeWhmcsKeyValueMap(customfieldsMap) || undefined,
      });

      this.logger.log(
        { whmcsClientId: whmcsClient.clientId, email: params.email },
        "WHMCS client created successfully"
      );

      return { whmcsClientId: whmcsClient.clientId };
    } catch (whmcsError) {
      this.logger.error(
        {
          error: extractErrorMessage(whmcsError),
          email: params.email,
          firstName: params.firstName,
          lastName: params.lastName,
        },
        "Failed to create WHMCS client"
      );
      throw new BadRequestException("Failed to create billing account");
    }
  }

  async rollback(whmcsClientId: number, email?: string): Promise<void> {
    this.logger.warn(
      { whmcsClientId, email },
      "Rolling back WHMCS client creation — marking for cleanup"
    );

    try {
      await this.whmcsClientService.updateClient(whmcsClientId, {
        status: "Inactive",
      });

      this.logger.warn(
        { whmcsClientId, email, action: "marked_for_cleanup" },
        "Marked orphaned WHMCS client for manual cleanup"
      );
    } catch (cleanupError) {
      this.logger.error(
        {
          whmcsClientId,
          email,
          cleanupError: extractErrorMessage(cleanupError),
          recommendation: "Manual cleanup required in WHMCS admin",
        },
        "Failed to mark orphaned WHMCS client for cleanup"
      );
    }
  }
}
