import { Injectable } from "@nestjs/common";
import { FreebitAccountService } from "../services/freebit-account.service.js";
import { FreebitUsageService } from "../services/freebit-usage.service.js";
import { FreebitPlanService } from "../services/freebit-plan.service.js";
import { FreebitVoiceService } from "../services/freebit-voice.service.js";
import { FreebitCancellationService } from "../services/freebit-cancellation.service.js";
import { FreebitEsimService, type EsimActivationParams } from "../services/freebit-esim.service.js";
import { FreebitMapperService } from "../services/freebit-mapper.service.js";
import type { SimDetails, SimUsage, SimTopUpHistory } from "../interfaces/freebit.types.js";

/**
 * Freebit Facade
 *
 * Unified entry point for all Freebit SIM operations.
 * Delegates to specialized services for each operation type.
 *
 * This facade handles account normalization automatically, so consumers
 * don't need to worry about formatting phone numbers correctly.
 *
 * @remarks
 * Specialized services:
 * - FreebitAccountService: SIM details, health checks
 * - FreebitUsageService: Usage queries, top-ups, quota history
 * - FreebitPlanService: Plan changes (PA05-21)
 * - FreebitVoiceService: Voice options (PA05-06), network type (PA05-38)
 * - FreebitCancellationService: Plan (PA05-04) and account (PA02-04) cancellation
 * - FreebitEsimService: eSIM profile management
 */
@Injectable()
export class FreebitFacade {
  constructor(
    private readonly accountService: FreebitAccountService,
    private readonly usageService: FreebitUsageService,
    private readonly planService: FreebitPlanService,
    private readonly voiceService: FreebitVoiceService,
    private readonly cancellationService: FreebitCancellationService,
    private readonly esimService: FreebitEsimService,
    private readonly mapper: FreebitMapperService
  ) {}

  /**
   * Normalize account identifier (remove formatting like dashes, spaces)
   */
  private normalizeAccount(account: string): string {
    return this.mapper.normalizeAccount(account);
  }

  // ============================================================================
  // Account Operations (delegated to FreebitAccountService)
  // ============================================================================

  /**
   * Get SIM account details with endpoint fallback
   */
  async getSimDetails(account: string): Promise<SimDetails> {
    const normalizedAccount = this.normalizeAccount(account);
    return this.accountService.getSimDetails(normalizedAccount);
  }

  /**
   * Health check - test API connectivity
   */
  async healthCheck(): Promise<boolean> {
    return this.accountService.healthCheck();
  }

  // ============================================================================
  // Usage Operations (delegated to FreebitUsageService)
  // ============================================================================

  /**
   * Get SIM usage/traffic information
   */
  async getSimUsage(account: string): Promise<SimUsage> {
    const normalizedAccount = this.normalizeAccount(account);
    return this.usageService.getSimUsage(normalizedAccount);
  }

  /**
   * Top up SIM data quota
   */
  async topUpSim(
    account: string,
    quotaMb: number,
    options: { campaignCode?: string; expiryDate?: string; scheduledAt?: string } = {}
  ): Promise<void> {
    const normalizedAccount = this.normalizeAccount(account);
    return this.usageService.topUpSim(normalizedAccount, quotaMb, options);
  }

  /**
   * Get SIM top-up history
   */
  async getSimTopUpHistory(
    account: string,
    fromDate: string,
    toDate: string
  ): Promise<SimTopUpHistory> {
    const normalizedAccount = this.normalizeAccount(account);
    return this.usageService.getSimTopUpHistory(normalizedAccount, fromDate, toDate);
  }

  // ============================================================================
  // Plan Operations (delegated to FreebitPlanService)
  // ============================================================================

  /**
   * Change SIM plan
   * Uses PA05-21 changePlan endpoint
   */
  async changeSimPlan(
    account: string,
    newPlanCode: string,
    options: { assignGlobalIp?: boolean; scheduledAt?: string } = {}
  ): Promise<{ ipv4?: string | undefined; ipv6?: string | undefined }> {
    const normalizedAccount = this.normalizeAccount(account);
    return this.planService.changeSimPlan(normalizedAccount, newPlanCode, options);
  }

  // ============================================================================
  // Voice/Network Operations (delegated to FreebitVoiceService)
  // ============================================================================

  /**
   * Update SIM features (voice options and network type)
   */
  async updateSimFeatures(
    account: string,
    features: {
      voiceMailEnabled?: boolean;
      callWaitingEnabled?: boolean;
      internationalRoamingEnabled?: boolean;
      networkType?: "4G" | "5G";
    }
  ): Promise<void> {
    const normalizedAccount = this.normalizeAccount(account);
    return this.voiceService.updateSimFeatures(normalizedAccount, features);
  }

  // ============================================================================
  // Cancellation Operations (delegated to FreebitCancellationService)
  // ============================================================================

  /**
   * Cancel SIM plan (PA05-04 - plan cancellation only)
   */
  async cancelSim(account: string, scheduledAt?: string): Promise<void> {
    const normalizedAccount = this.normalizeAccount(account);
    return this.cancellationService.cancelSim(normalizedAccount, scheduledAt);
  }

  /**
   * Cancel SIM account (PA02-04 - full account cancellation)
   */
  async cancelAccount(account: string, runDate?: string): Promise<void> {
    const normalizedAccount = this.normalizeAccount(account);
    return this.cancellationService.cancelAccount(normalizedAccount, runDate);
  }

  // ============================================================================
  // eSIM Operations (delegated to FreebitEsimService)
  // ============================================================================

  /**
   * Reissue eSIM profile (simple version)
   */
  async reissueEsimProfile(account: string): Promise<void> {
    const normalizedAccount = this.normalizeAccount(account);
    return this.esimService.reissueEsimProfile(normalizedAccount);
  }

  /**
   * Reissue eSIM profile with enhanced options
   */
  async reissueEsimProfileEnhanced(
    account: string,
    newEid: string,
    options: { oldProductNumber?: string; oldEid?: string; planCode?: string } = {}
  ): Promise<void> {
    const normalizedAccount = this.normalizeAccount(account);
    return this.esimService.reissueEsimProfileEnhanced(normalizedAccount, newEid, options);
  }

  /**
   * Activate new eSIM account using PA05-41 (addAcct)
   */
  async activateEsimAccountNew(params: EsimActivationParams): Promise<void> {
    const normalizedParams = {
      ...params,
      account: this.normalizeAccount(params.account),
    };
    return this.esimService.activateEsimAccountNew(normalizedParams);
  }
}
