import { Injectable, Inject, BadRequestException } from "@nestjs/common";
import { Logger } from "nestjs-pino";
import { ConfigService } from "@nestjs/config";
import { FreebitOrchestratorService } from "@bff/integrations/freebit/services/freebit-orchestrator.service";
import { WhmcsService } from "@bff/integrations/whmcs/whmcs.service";
import { MappingsService } from "@bff/modules/id-mappings/mappings.service";
import { SimValidationService } from "./sim-validation.service";
import { SimNotificationService } from "./sim-notification.service";
import { SimApiNotificationService } from "./sim-api-notification.service";
import { getErrorMessage } from "@bff/core/utils/error.util";
import type { SimReissueRequest } from "@customer-portal/domain/sim";

export interface ReissueSimRequest {
  simType: "physical" | "esim";
  newEid?: string;
}

@Injectable()
export class EsimManagementService {
  constructor(
    private readonly freebitService: FreebitOrchestratorService,
    private readonly whmcsService: WhmcsService,
    private readonly mappingsService: MappingsService,
    private readonly simValidation: SimValidationService,
    private readonly simNotification: SimNotificationService,
    private readonly apiNotification: SimApiNotificationService,
    private readonly configService: ConfigService,
    @Inject(Logger) private readonly logger: Logger
  ) {}

  private get freebitBaseUrl(): string {
    return this.configService.get<string>("FREEBIT_BASE_URL") || "https://i1.mvno.net/emptool/api";
  }

  /**
   * Reissue eSIM profile (legacy method)
   */
  async reissueEsimProfile(
    userId: string,
    subscriptionId: number,
    request: SimReissueRequest
  ): Promise<void> {
    try {
      const { account } = await this.simValidation.validateSimSubscription(userId, subscriptionId);

      // First check if this is actually an eSIM
      const simDetails = await this.freebitService.getSimDetails(account);
      if (simDetails.simType !== "esim") {
        throw new BadRequestException("This operation is only available for eSIM subscriptions");
      }

      const newEid = request.newEid;

      if (newEid) {
        await this.freebitService.reissueEsimProfileEnhanced(account, newEid, {
          oldEid: simDetails.eid,
          planCode: simDetails.planCode,
        });
      } else {
        await this.freebitService.reissueEsimProfile(account);
      }

      this.logger.log(`Successfully reissued eSIM profile for subscription ${subscriptionId}`, {
        userId,
        subscriptionId,
        account,
        oldEid: simDetails.eid,
        newEid: newEid || undefined,
      });

      await this.simNotification.notifySimAction("Reissue eSIM", "SUCCESS", {
        userId,
        subscriptionId,
        account,
        oldEid: simDetails.eid,
        newEid: newEid || undefined,
      });
    } catch (error) {
      const sanitizedError = getErrorMessage(error);
      this.logger.error(`Failed to reissue eSIM profile for subscription ${subscriptionId}`, {
        error: sanitizedError,
        userId,
        subscriptionId,
        newEid: request.newEid || undefined,
      });
      await this.simNotification.notifySimAction("Reissue eSIM", "ERROR", {
        userId,
        subscriptionId,
        newEid: request.newEid || undefined,
        error: sanitizedError,
      });
      throw error;
    }
  }

  /**
   * Reissue SIM with full flow (eSIM via PA05-41, Physical SIM via email)
   */
  async reissueSim(
    userId: string,
    subscriptionId: number,
    request: ReissueSimRequest
  ): Promise<void> {
    const { account } = await this.simValidation.validateSimSubscription(userId, subscriptionId);
    const simDetails = await this.freebitService.getSimDetails(account);

    // Get customer info from WHMCS
    const mapping = await this.mappingsService.findByUserId(userId);
    if (!mapping?.whmcsClientId) {
      throw new BadRequestException("WHMCS client mapping not found");
    }

    const clientDetails = await this.whmcsService.getClientDetails(mapping.whmcsClientId);
    const customerName = `${clientDetails.firstname || ""} ${clientDetails.lastname || ""}`.trim() || "Customer";
    const customerEmail = clientDetails.email || "";

    if (request.simType === "esim") {
      // eSIM reissue via PA05-41
      if (!request.newEid) {
        throw new BadRequestException("New EID is required for eSIM reissue");
      }

      const oldEid = simDetails.eid;

      this.logger.log(`Reissuing eSIM via PA05-41`, {
        userId,
        subscriptionId,
        account,
        oldEid,
        newEid: request.newEid,
      });

      // Call PA05-41 with addKind: "R" for reissue
      await this.freebitService.activateEsimAccountNew({
        account,
        eid: request.newEid,
        addKind: "R",
        planCode: simDetails.planCode,
      });

      // Send API results email to admin
      await this.apiNotification.sendApiResultsEmail(
        "SIM Re-issue Request",
        [
          {
            url: `${this.freebitBaseUrl}/mvno/esim/addAcnt/`,
            json: {
              reissue: { oldEid },
              account,
              addKind: "R",
              eid: request.newEid,
              authKey: "[REDACTED]",
            },
            result: {
              resultCode: "100",
              status: { message: "OK", statusCode: "200" },
            },
          },
        ]
      );

      // Send customer email
      const customerEmailBody = this.apiNotification.buildEsimReissueEmail(
        customerName,
        account,
        request.newEid
      );
      await this.apiNotification.sendCustomerEmail(
        customerEmail,
        "SIM Re-issue Request",
        customerEmailBody
      );

      this.logger.log(`Successfully reissued eSIM for subscription ${subscriptionId}`, {
        userId,
        subscriptionId,
        account,
        oldEid,
        newEid: request.newEid,
      });
    } else {
      // Physical SIM reissue - email only, no API call
      this.logger.log(`Processing physical SIM reissue request`, {
        userId,
        subscriptionId,
        account,
      });

      // Send admin notification email
      await this.apiNotification.sendApiResultsEmail(
        "Physical SIM Re-issue Request",
        [],
        `Physical SIM reissue requested for:\nCustomer: ${customerName}\nSIM #: ${account}\nSerial #: ${simDetails.iccid || "N/A"}\nEmail: ${customerEmail}`
      );

      // Send customer email
      const customerEmailBody = this.apiNotification.buildPhysicalSimReissueEmail(
        customerName,
        account
      );
      await this.apiNotification.sendCustomerEmail(
        customerEmail,
        "Physical SIM Re-issue Request",
        customerEmailBody
      );

      this.logger.log(`Sent physical SIM reissue request emails`, {
        userId,
        subscriptionId,
        account,
        customerEmail,
      });
    }
  }
}
