/**
 * Freebit Voice Options Service (PA05-05)
 *
 * Handles MVNO voice option registration via the Freebit PA05-05 API.
 * This is called after PA02-01 account registration to configure
 * voice features like VoiceMail, CallWaiting, WorldCall, etc.
 *
 * @see docs/freebit-apis/PA05-05-mvno-voice-option-registration.md
 */

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";

/**
 * Identity data required for voice option registration
 */
export interface VoiceOptionIdentityData {
  /** Last name in Kanji (UTF-8, max 50 chars) */
  lastnameKanji: string;
  /** First name in Kanji (UTF-8, max 50 chars) */
  firstnameKanji: string;
  /** Last name in Katakana (full-width, max 50 chars) */
  lastnameKana: string;
  /** First name in Katakana (full-width, max 50 chars) */
  firstnameKana: string;
  /** Gender: "M" = Male, "F" = Female */
  gender: "M" | "F";
  /** Birthday in YYYYMMDD format */
  birthday: string;
}

/**
 * PA05-05 Voice Option Registration parameters
 */
export interface VoiceOptionRegistrationParams {
  /** MSISDN (phone number) - must be already registered via PA02-01 */
  account: string;
  /** Enable VoiceMail service */
  voiceMailEnabled: boolean;
  /** Enable CallWaiting (Catch Phone) service */
  callWaitingEnabled: boolean;
  /** Customer identity data (required) */
  identificationData: VoiceOptionIdentityData;
  /** WorldCall credit limit in yen (default: 5000) */
  worldCallCreditLimit?: string;
}

/**
 * PA05-05 Request payload structure
 */
interface FreebitVoiceOptionRequest {
  account: string;
  userConfirmed: "10" | "20";
  aladinOperated: "10" | "20";
  talkOption: {
    voiceMail: "10" | "20";
    callWaiting: "10" | "20";
    callTransfer?: "10" | "20";
    callTransferNoId?: "10" | "20";
    worldCall: "10" | "20";
    worldCallCreditLimit?: string;
    worldWing: "10" | "20";
    worldWingCreditLimit?: string;
  };
  identificationData: {
    lastnameKanji: string;
    firstnameKanji: string;
    lastnameKana: string;
    firstnameKana: string;
    gender: string;
    birthday: string;
  };
}

/**
 * PA05-05 Response structure
 */
interface FreebitVoiceOptionResponse {
  resultCode: string;
  status?: {
    message?: string;
    statusCode?: string | number;
  };
}

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

  /**
   * Register voice options for an MVNO account (PA05-05)
   *
   * This configures voice features for a phone number that was previously
   * registered via PA02-01. Must be called after account registration.
   *
   * Default settings applied:
   * - WorldCall: Always enabled
   * - WorldWing: Always disabled
   *
   * @param params - Voice option registration parameters
   * @throws BadRequestException if registration fails
   */
  async registerVoiceOptions(params: VoiceOptionRegistrationParams): Promise<void> {
    const {
      account,
      voiceMailEnabled,
      callWaitingEnabled,
      identificationData,
      worldCallCreditLimit = "5000",
    } = params;

    // Validate required parameters
    if (!account || account.length < 11) {
      throw new BadRequestException("Invalid phone number (account) for voice option registration");
    }

    if (!identificationData) {
      throw new BadRequestException("Identity data is required for voice option registration");
    }

    // Validate identity data
    if (!identificationData.lastnameKanji || !identificationData.firstnameKanji) {
      throw new BadRequestException("Name (Kanji) is required for voice option registration");
    }

    if (!identificationData.lastnameKana || !identificationData.firstnameKana) {
      throw new BadRequestException("Name (Kana) is required for voice option registration");
    }

    if (!identificationData.gender || !["M", "F"].includes(identificationData.gender)) {
      throw new BadRequestException("Valid gender (M/F) is required for voice option registration");
    }

    if (!identificationData.birthday || !/^\d{8}$/.test(identificationData.birthday)) {
      throw new BadRequestException(
        "Birthday in YYYYMMDD format is required for voice option registration"
      );
    }

    this.logger.log("Starting voice option registration (PA05-05)", {
      account,
      voiceMailEnabled,
      callWaitingEnabled,
      worldCallCreditLimit,
      hasIdentityData: !!identificationData,
    });

    try {
      // Build payload according to PA05-05 documentation
      // Note: authKey is added automatically by makeAuthenticatedRequest
      const payload: FreebitVoiceOptionRequest = {
        account,
        userConfirmed: "10", // Always confirmed
        aladinOperated: "10", // ALADIN operated
        talkOption: {
          voiceMail: voiceMailEnabled ? "10" : "20",
          callWaiting: callWaitingEnabled ? "10" : "20",
          worldCall: "10", // Always enabled per requirements
          worldCallCreditLimit,
          worldWing: "20", // Always disabled per requirements
        },
        identificationData: {
          lastnameKanji: identificationData.lastnameKanji,
          firstnameKanji: identificationData.firstnameKanji,
          lastnameKana: identificationData.lastnameKana,
          firstnameKana: identificationData.firstnameKana,
          gender: identificationData.gender,
          birthday: identificationData.birthday,
        },
      };

      // PA05-05 uses form-urlencoded format with json= parameter
      await this.client.makeAuthenticatedRequest<
        FreebitVoiceOptionResponse,
        FreebitVoiceOptionRequest
      >("/mvno/talkoption/addOrder/", payload);

      this.logger.log("Voice option registration successful (PA05-05)", {
        account,
        voiceMailEnabled,
        callWaitingEnabled,
      });
    } catch (error: unknown) {
      const message = extractErrorMessage(error);
      this.logger.error("Voice option registration failed (PA05-05)", {
        account,
        error: message,
      });
      throw new BadRequestException(`Voice option registration failed: ${message}`);
    }
  }

  /**
   * Format birthday from Date or ISO string to YYYYMMDD
   */
  formatBirthday(date: Date | string | undefined): string {
    if (!date) return "";

    const d = typeof date === "string" ? new Date(date) : date;
    if (Number.isNaN(d.getTime())) return "";

    const year = d.getFullYear();
    const month = String(d.getMonth() + 1).padStart(2, "0");
    const day = String(d.getDate()).padStart(2, "0");

    return `${year}${month}${day}`;
  }
}
