import { Processor, WorkerHost } from '@nestjs/bullmq';
import { Logger } from '@nestjs/common';
import type { Job } from 'bullmq';
import { existsSync, mkdirSync, writeFileSync } from 'fs';
import { join } from 'path';
import { SifenPayloadService } from 'src/facturas/sifen-payload.service';
import { MiddlewareSifenService } from 'src/middleware-sifen/middleware-sifen.service';
import { PrismaService } from 'src/prisma/prisma.service';
import type { SendFacturaToSifenJob } from '../types/sifen-job.interface';

@Processor('sifen-queue')
export class SifenProcessor extends WorkerHost {
  private readonly logger = new Logger(SifenProcessor.name);

  constructor(
    private readonly prisma: PrismaService,
    private readonly middlewareSifenService: MiddlewareSifenService,
    private readonly sifenPayloadService: SifenPayloadService,
  ) {
    super();
  }

  private savePayloadToLog(payload: Record<string, unknown>): void {
    try {
      const logsDir = join(process.cwd(), 'logs', 'sifen');
      if (!existsSync(logsDir)) {
        mkdirSync(logsDir, { recursive: true });
      }
      const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
      const filename = `payload_${timestamp}.json`;
      const filepath = join(logsDir, filename);
      writeFileSync(filepath, JSON.stringify(payload, null, 2), 'utf-8');
      this.logger.log(`Payload guardado en: ${filepath}`);
    } catch (error) {
      this.logger.error(`Error guardando payload en log: ${error}`);
    }
  }

  private async buildSifenPayload(facturaId: string, empresaId: string): Promise<Record<string, unknown>> {
    const payload = await this.sifenPayloadService.buildFacturaPayload(facturaId, empresaId);
    const payloadMiddleware = {
      nro_lote: String('novasispy-' + Date.now()),
      tipOpe: '1',
      iTiDE: '1',
      comprobantes: [payload],
    };
    return payloadMiddleware;
  }

  async process(job: Job<SendFacturaToSifenJob>): Promise<void> {
    this.logger.log(`Processing SIFEN job ${job.id} factura=${job.data.facturaId}`);

    try {
      await this.prisma.factura_cab.update({
        where: { id: job.data.facturaId },
        data: { estado: 'Enviando', estado_sifen: 'Enviando' },
      });

      const payload = await this.buildSifenPayload(job.data.facturaId, job.data.empresaId);
      this.savePayloadToLog(payload);

      // Guardar nro_lote antes de enviar para posterior consulta
      const nroLote = payload.nro_lote as string;
      await this.prisma.factura_cab.update({
        where: { id: job.data.facturaId },
        data: { nro_lote: nroLote, fecha_envio_sifen: new Date() },
      });

      await this.middlewareSifenService.sendDocumentToMiddlewareSifen(payload);

      await this.prisma.factura_cab.update({
        where: { id: job.data.facturaId },
        data: { estado: 'Enviado', estado_sifen: 'Enviado' },
      });

      this.logger.log(`Factura ${job.data.facturaId} enviada a SIFEN correctamente con lote ${nroLote}`);
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Error desconocido';
      this.logger.error(`Error enviando factura ${job.data.facturaId} a SIFEN: ${message}`);

      await this.prisma.factura_cab.update({
        where: { id: job.data.facturaId },
        data: {
          estado: 'Pendiente',
          estado_sifen: 'Error',
          mensaje_sifen: message,
        },
      });

      throw error;
    }
  }
}
