import { Injectable, Inject } from "@nestjs/common";
import { PrismaService } from "@bff/infra/database/prisma.service";
import { Logger } from "nestjs-pino";

@Injectable()
export class SimUsageStoreService {
  constructor(
    private readonly prisma: PrismaService,
    @Inject(Logger) private readonly logger: Logger
  ) {}

  private get store(): {
    upsert: (args: unknown) => Promise<unknown>;
    findMany: (args: unknown) => Promise<unknown>;
    deleteMany: (args: unknown) => Promise<unknown>;
  } | null {
    const s = (
      this.prisma as {
        simUsageDaily?: {
          upsert: (args: unknown) => Promise<unknown>;
          findMany: (args: unknown) => Promise<unknown>;
          deleteMany: (args: unknown) => Promise<unknown>;
        };
      }
    )?.simUsageDaily;
    return s && typeof s === "object" ? s : null;
  }

  private normalizeDate(date?: Date): Date {
    const d = date ? new Date(date) : new Date();
    // strip time to YYYY-MM-DD
    const iso = d.toISOString().split("T")[0];
    return new Date(iso + "T00:00:00.000Z");
  }

  async upsertToday(account: string, usageMb: number, date?: Date): Promise<void> {
    const day = this.normalizeDate(date);
    try {
      const store = this.store;
      if (!store) {
        this.logger.debug("SIM usage store not configured; skipping persist");
        return;
      }
      await store.upsert({
        where: { account_date: { account, date: day } },
        update: { usageMb },
        create: { account, date: day, usageMb },
      });
    } catch (e: unknown) {
      const message = e instanceof Error ? e.message : String(e);
      this.logger.error("Failed to upsert daily usage", { account, error: message });
    }
  }

  async getLastNDays(
    account: string,
    days = 30
  ): Promise<Array<{ date: string; usageMb: number }>> {
    const end = this.normalizeDate();
    const start = new Date(end);
    start.setUTCDate(end.getUTCDate() - (days - 1));
    const store = this.store;
    if (!store) return [];
    const rows = (await store.findMany({
      where: { account, date: { gte: start, lte: end } },
      orderBy: { date: "desc" },
    })) as Array<{ date: Date; usageMb: number }>;
    return rows.map(r => ({ date: r.date.toISOString().split("T")[0], usageMb: r.usageMb }));
  }

  async cleanupPreviousMonths(): Promise<number> {
    const now = new Date();
    const firstOfMonth = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1));
    const store = this.store;
    if (!store) return 0;
    const result = (await store.deleteMany({
      where: { date: { lt: firstOfMonth } },
    })) as { count: number };
    return result.count;
  }
}
