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";
import { FreebitRateLimiterService } from "./freebit-rate-limiter.service.js";
import type {
  FreebitCancelPlanRequest,
  FreebitCancelPlanResponse,
  FreebitCancelAccountRequest,
  FreebitCancelAccountResponse,
} from "../interfaces/freebit.types.js";

/**
 * Service for Freebit SIM cancellation operations.
 * Handles PA05-04 (plan cancellation) and PA02-04 (account cancellation).
 */
@Injectable()
export class FreebitCancellationService {
  constructor(
    private readonly client: FreebitClientService,
    private readonly rateLimiter: FreebitRateLimiterService,
    @Inject(Logger) private readonly logger: Logger
  ) {}

  /**
   * Cancel SIM plan (PA05-04 - plan cancellation only)
   */
  async cancelSim(account: string, scheduledAt?: string): Promise<void> {
    try {
      await this.rateLimiter.executeWithSpacing(account, "cancellation", async () => {
        const request: Omit<FreebitCancelPlanRequest, "authKey"> = {
          account,
          ...(scheduledAt !== undefined && { runTime: scheduledAt }),
        };

        this.logger.log(`Cancelling SIM plan via PA05-04 for account ${account}`, {
          account,
          runTime: scheduledAt,
        });

        await this.client.makeAuthenticatedRequest<FreebitCancelPlanResponse, typeof request>(
          "/mvno/releasePlan/",
          request
        );

        this.logger.log(`Successfully cancelled SIM plan for account ${account}`, {
          account,
          runTime: scheduledAt,
        });
      });
    } catch (error) {
      const message = extractErrorMessage(error);
      this.logger.error(`Failed to cancel SIM plan for account ${account}`, {
        account,
        scheduledAt,
        error: message,
      });
      throw new BadRequestException(`Failed to cancel SIM plan: ${message}`);
    }
  }

  /**
   * Cancel SIM account (PA02-04 - full account cancellation)
   *
   * IMPORTANT CONSTRAINTS:
   * - Must be sent with runDate as 1st of client's cancellation month n+1
   *   (e.g., cancel end of Jan = runDate 20250201)
   * - After PA02-04 is sent, any subsequent PA05-21 calls will cancel it
   * - PA05-21 and PA02-04 cannot coexist
   * - Must prevent clients from making further changes after cancellation is requested
   */
  async cancelAccount(account: string, runDate?: string): Promise<void> {
    try {
      await this.rateLimiter.executeWithSpacing(account, "cancellation", async () => {
        const request: Omit<FreebitCancelAccountRequest, "authKey"> = {
          kind: "MVNO",
          account,
          ...(runDate !== undefined && { runDate }),
        };

        this.logger.log(`Cancelling SIM account via PA02-04 for account ${account}`, {
          account,
          runDate,
          note: "After this, PA05-21 plan changes will cancel the cancellation",
        });

        await this.client.makeAuthenticatedRequest<FreebitCancelAccountResponse, typeof request>(
          "/master/cnclAcnt/",
          request
        );

        this.logger.log(`Successfully cancelled SIM account for account ${account}`, {
          account,
          runDate,
        });
      });
    } catch (error) {
      const message = extractErrorMessage(error);
      this.logger.error(`Failed to cancel SIM account for account ${account}`, {
        account,
        runDate,
        error: message,
      });
      throw new BadRequestException(`Failed to cancel SIM account: ${message}`);
    }
  }
}
