/**
 * Freebit Semi-Black Account Registration Service (PA05-19)
 *
 * Handles MVNO semi-black (半黒) SIM registration via the Freebit PA05-19 API.
 * For MNP transfers, this replaces PA02-01. For non-MNP, PA02-01 is used instead.
 *
 * Semi-black SIMs are pre-provisioned SIMs that need to be registered
 * to associate them with a customer account and plan.
 */

import { Injectable, Inject, BadRequestException } from "@nestjs/common";
import { Logger } from "nestjs-pino";
import { extractErrorMessage } from "@bff/core/utils/error.util.js";
import { FreebitClientService } from "./freebit-client.service.js";

/**
 * PA05-19 Semi-Black Account Registration parameters
 */
export interface SemiBlackRegistrationParams {
  /** MSISDN (phone number) - 11-14 digits */
  account: string;
  /** Manufacturing number (productNumber) - 15 chars, e.g., AXxxxxxxxxxxxxx */
  productNumber: string;
  /** Freebit plan code (e.g., "PASI_5G") */
  planCode: string;
  /** Ship date in YYYYMMDD format (defaults to today) */
  shipDate?: string;
  /** Create type: "new" for new master account, "add" for existing */
  createType?: "new" | "add";
  /** Global IP assignment: "20" = disabled (default) */
  globalIp?: "20";
  /** ALADIN operation flag: "10" = operated, "20" = not operated (default) */
  aladinOperated?: "10" | "20";
  /** Sales channel code (optional) */
  deliveryCode?: string;
}

/**
 * PA05-19 Request payload structure
 */
interface FreebitSemiBlackRequest {
  authKey: string;
  createType: "new" | "add";
  account: string;
  productNumber: string;
  planCode: string;
  shipDate: string;
  mnp: {
    method: "10"; // "10" = Semi-black SIM
  };
  globalIp?: string;
  aladinOperated?: string;
  deliveryCode?: string;
}

/**
 * PA05-19 Response structure
 */
interface FreebitSemiBlackResponse {
  resultCode: number;
  status: {
    message: string;
    statusCode: number;
  };
}

@Injectable()
export class FreebitSemiBlackService {
  constructor(
    private readonly client: FreebitClientService,
    @Inject(Logger) private readonly logger: Logger
  ) {}

  /**
   * Register a semi-black SIM account (PA05-19)
   *
   * This registers a pre-provisioned (semi-black) physical SIM in Freebit's
   * system. For MNP transfers, this replaces PA02-01.
   *
   * @param params - Semi-black registration parameters
   * @throws BadRequestException if registration fails
   */
  async registerSemiBlackAccount(params: SemiBlackRegistrationParams): Promise<void> {
    const {
      account,
      productNumber,
      planCode,
      shipDate,
      createType = "new",
      globalIp = "20",
      aladinOperated = "20",
      deliveryCode,
    } = params;

    // Validate phone number
    if (!account || account.length < 11 || account.length > 14) {
      throw new BadRequestException(
        "Invalid phone number (account) for semi-black registration - must be 11-14 digits"
      );
    }

    // Validate product number (manufacturing number)
    if (!productNumber || productNumber.length !== 15) {
      throw new BadRequestException(
        "Invalid product number for semi-black registration - must be 15 characters (e.g., AXxxxxxxxxxxxxx)"
      );
    }

    if (!planCode) {
      throw new BadRequestException("Plan code is required for semi-black registration");
    }

    // Default to today's date if not provided
    const effectiveShipDate = shipDate ?? this.formatTodayAsYYYYMMDD();

    this.logger.log("Starting semi-black SIM registration (PA05-19)", {
      account,
      productNumber,
      planCode,
      shipDate: effectiveShipDate,
      createType,
    });

    try {
      const payload: Omit<FreebitSemiBlackRequest, "authKey"> = {
        createType,
        account,
        productNumber,
        planCode,
        shipDate: effectiveShipDate,
        mnp: {
          method: "10", // Semi-black SIM method
        },
        globalIp,
        aladinOperated,
        ...(deliveryCode && { deliveryCode }),
      };

      // FreebitClientService validates resultCode === "100" before returning
      await this.client.makeAuthenticatedRequest<
        FreebitSemiBlackResponse,
        Omit<FreebitSemiBlackRequest, "authKey">
      >("/mvno/semiblack/addAcnt/", payload);

      this.logger.log("Semi-black SIM registration successful (PA05-19)", {
        account,
        productNumber,
        planCode,
      });
    } catch (error: unknown) {
      // Re-throw BadRequestException as-is
      if (error instanceof BadRequestException) {
        throw error;
      }

      const message = extractErrorMessage(error);
      this.logger.error("Semi-black registration failed (PA05-19)", {
        account,
        productNumber,
        planCode,
        error: message,
      });
      throw new BadRequestException(`Semi-black registration failed: ${message}`);
    }
  }

  /**
   * Format today's date as YYYYMMDD
   */
  private formatTodayAsYYYYMMDD(): string {
    const now = new Date();
    const year = now.getFullYear();
    const month = String(now.getMonth() + 1).padStart(2, "0");
    const day = String(now.getDate()).padStart(2, "0");
    return `${year}${month}${day}`;
  }
}
