import { Injectable, Inject } from "@nestjs/common";
import { Logger } from "nestjs-pino";
import { FreebitOrchestratorService } from "@bff/integrations/freebit/services/freebit-orchestrator.service";
import { SimValidationService } from "./sim-validation.service";
import { SimUsageStoreService } from "../../sim-usage-store.service";
import { getErrorMessage } from "@bff/core/utils/error.util";
import type { SimTopUpHistory, SimUsage } from "@customer-portal/domain/sim";
import type { SimTopUpHistoryRequest } from "@customer-portal/domain/sim";
import { SimScheduleService } from "./sim-schedule.service";

@Injectable()
export class SimUsageService {
  constructor(
    private readonly freebitService: FreebitOrchestratorService,
    private readonly simValidation: SimValidationService,
    private readonly usageStore: SimUsageStoreService,
    private readonly simSchedule: SimScheduleService,
    @Inject(Logger) private readonly logger: Logger
  ) {}

  /**
   * Get SIM data usage for a subscription
   */
  async getSimUsage(userId: string, subscriptionId: number): Promise<SimUsage> {
    try {
      const { account } = await this.simValidation.validateSimSubscription(userId, subscriptionId);

      const simUsage = await this.freebitService.getSimUsage(account);

      // Persist today's usage for monthly charts and cleanup previous months
      try {
        await this.usageStore.upsertToday(account, simUsage.todayUsageMb);
        await this.usageStore.cleanupPreviousMonths();
        const stored = await this.usageStore.getLastNDays(account, 30);
        if (stored.length > 0) {
          simUsage.recentDaysUsage = stored.map(d => ({
            date: d.date,
            usageKb: Math.round(d.usageMb * 1000),
            usageMb: d.usageMb,
          }));
        }
      } catch (e) {
        const sanitizedError = getErrorMessage(e);
        this.logger.warn("SIM usage persistence failed (non-fatal)", {
          account,
          error: sanitizedError,
        });
      }

      this.logger.log(`Retrieved SIM usage for subscription ${subscriptionId}`, {
        userId,
        subscriptionId,
        account,
        todayUsageMb: simUsage.todayUsageMb,
      });

      return simUsage;
    } catch (error) {
      const sanitizedError = getErrorMessage(error);
      this.logger.error(`Failed to get SIM usage for subscription ${subscriptionId}`, {
        error: sanitizedError,
        userId,
        subscriptionId,
      });
      throw error;
    }
  }

  /**
   * Get SIM top-up history
   */
  async getSimTopUpHistory(
    userId: string,
    subscriptionId: number,
    request: SimTopUpHistoryRequest
  ): Promise<SimTopUpHistory> {
    try {
      const { account } = await this.simValidation.validateSimSubscription(userId, subscriptionId);

      const fromDate = this.simSchedule.ensureYyyyMmDd(request.fromDate, "fromDate");
      const toDate = this.simSchedule.ensureYyyyMmDd(request.toDate, "toDate");

      const history = await this.freebitService.getSimTopUpHistory(
        account,
        fromDate,
        toDate
      );

      this.logger.log(`Retrieved SIM top-up history for subscription ${subscriptionId}`, {
        userId,
        subscriptionId,
        account,
        totalAdditions: history.totalAdditions,
      });

      return history;
    } catch (error) {
      const sanitizedError = getErrorMessage(error);
      this.logger.error(`Failed to get SIM top-up history for subscription ${subscriptionId}`, {
        error: sanitizedError,
        userId,
        subscriptionId,
      });
      throw error;
    }
  }
}
