import { Processor, WorkerHost } from "@nestjs/bullmq";
import { Logger } from "@nestjs/common";
import { InvoiceStatus } from "@prisma/client";
import { Job } from "bullmq";
import { PrismaService } from "../prisma/prisma.service";
import {
  BILLING_JOBS,
  BILLING_QUEUE,
  type BillingJobName,
} from "./billing.constants";
import { InvoiceService } from "./invoice.service";

@Processor(BILLING_QUEUE, { concurrency: 1 })
export class BillingProcessor extends WorkerHost {
  private readonly logger = new Logger(BillingProcessor.name);

  constructor(
    private readonly invoices: InvoiceService,
    private readonly prisma: PrismaService,
  ) {
    super();
  }

  async process(job: Job<unknown, unknown, BillingJobName>): Promise<void> {
    switch (job.name) {
      case BILLING_JOBS.GENERATE_MONTHLY:
        await this.generateMonthly();
        return;
      case BILLING_JOBS.MARK_OVERDUE:
        await this.markOverdue();
        return;
      default:
        this.logger.warn(`Job desconocido en cola billing: ${job.name}`);
    }
  }

  private async generateMonthly(): Promise<void> {
    const result = await this.invoices.generate();
    this.logger.log(
      `Generación mensual: ${result.generated.length} generadas, ${result.skipped.length} skipeadas`,
    );
  }

  private async markOverdue(): Promise<void> {
    const now = new Date();
    const res = await this.prisma.merchantInvoice.updateMany({
      where: {
        status: InvoiceStatus.pending,
        dueAt: { lt: now },
      },
      data: { status: InvoiceStatus.overdue },
    });
    if (res.count > 0) {
      this.logger.log(`${res.count} facturas pasaron a overdue`);
    }
  }
}
