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 { FreebitMapperService } from "./freebit-mapper.service.js";
import type {
  FreebitTrafficInfoRequest,
  FreebitTrafficInfoResponse,
  FreebitTopUpResponse,
  FreebitQuotaHistoryRequest,
  FreebitQuotaHistoryResponse,
  SimUsage,
  SimTopUpHistory,
} from "../interfaces/freebit.types.js";

/**
 * Service for Freebit SIM usage and top-up operations.
 * Handles usage queries, top-ups, and quota history.
 */
@Injectable()
export class FreebitUsageService {
  constructor(
    private readonly client: FreebitClientService,
    private readonly mapper: FreebitMapperService,
    @Inject(Logger) private readonly logger: Logger
  ) {}

  /**
   * Get SIM usage/traffic information
   */
  async getSimUsage(account: string): Promise<SimUsage> {
    try {
      const request: Omit<FreebitTrafficInfoRequest, "authKey"> = { account };

      const response = await this.client.makeAuthenticatedRequest<
        FreebitTrafficInfoResponse,
        typeof request
      >("/mvno/getTrafficInfo/", request);

      return this.mapper.mapToSimUsage(response);
    } catch (error) {
      const message = extractErrorMessage(error);
      this.logger.error(`Failed to get SIM usage for account ${account}`, {
        account,
        error: message,
      });
      throw new BadRequestException(`Failed to get SIM usage: ${message}`);
    }
  }

  /**
   * Top up SIM data quota
   */
  async topUpSim(
    account: string,
    quotaMb: number,
    options: { campaignCode?: string; expiryDate?: string; scheduledAt?: string } = {}
  ): Promise<void> {
    try {
      // Note: Freebit addSpec API expects quota in MB (not KB as previously thought)
      // Also requires 'kind' field for MVNO operations
      const baseRequest = {
        account,
        quota: quotaMb, // MB units for addSpec
        kind: "MVNO", // Required for MVNO operations
        quotaCode: options.campaignCode,
        expire: options.expiryDate,
      };

      const scheduled = !!options.scheduledAt;
      const endpoint = scheduled ? "/mvno/eachQuota/" : "/master/addSpec/";

      // For scheduled operations, use KB and add runTime
      const request = scheduled
        ? { ...baseRequest, quota: Math.round(quotaMb * 1024), runTime: options.scheduledAt }
        : baseRequest;

      // Log the request details for debugging
      this.logger.log(`Freebit addSpec request details`, {
        endpoint,
        account,
        quotaMb,
        quotaUnit: scheduled ? "KB" : "MB",
        kind: "MVNO",
        quotaCode: options.campaignCode || "(none)",
        expire: options.expiryDate || "(none)",
        scheduled,
        requestPayload: JSON.stringify(request),
      });

      await this.client.makeAuthenticatedRequest<FreebitTopUpResponse, typeof request>(
        endpoint,
        request
      );

      this.logger.log(`Successfully topped up ${quotaMb}MB for account ${account}`, {
        account,
        endpoint,
        quotaMb,
        scheduled,
      });
    } catch (error) {
      const message = extractErrorMessage(error);
      this.logger.error(`Failed to top up SIM for account ${account}`, {
        account,
        quotaMb,
        error: message,
      });
      throw new BadRequestException(`Failed to top up SIM: ${message}`);
    }
  }

  /**
   * Get SIM top-up history
   */
  async getSimTopUpHistory(
    account: string,
    fromDate: string,
    toDate: string
  ): Promise<SimTopUpHistory> {
    try {
      const request: Omit<FreebitQuotaHistoryRequest, "authKey"> = {
        account,
        fromDate,
        toDate,
      };

      const response = await this.client.makeAuthenticatedRequest<
        FreebitQuotaHistoryResponse,
        typeof request
      >("/mvno/getQuotaHistory/", request);

      return this.mapper.mapToSimTopUpHistory(response, account);
    } catch (error) {
      const message = extractErrorMessage(error);
      this.logger.error(`Failed to get SIM top-up history for account ${account}`, {
        account,
        fromDate,
        toDate,
        error: message,
      });
      throw new BadRequestException(`Failed to get SIM top-up history: ${message}`);
    }
  }
}
