import { Body, Controller, HttpException, HttpStatus, Post, Res, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiBearerAuth, ApiBody, ApiOperation, ApiTags } from '@nestjs/swagger';
import type { Response } from 'express';
import type { LoginUserInfo } from 'src/auth/dto/login.dto';
import { GetUser } from 'src/auth/get-user.decorator';
import { GenerateKudeDto } from './dto/generate-kude.dto';
import { KudeService } from './kude.service';
import { PrismaService } from 'src/prisma/prisma.service';
import { fechaArchivo, nombreArchivo } from 'src/common/utils/nombre-archivo.util';

@ApiTags('KUDE - Generación de PDF')
@Controller({ path: 'kude', version: '1' })
export class KudeController {
  constructor(
    private readonly kudeService: KudeService,
    private readonly prisma: PrismaService,
  ) {}

  /** Nombre de archivo con el número del documento (no su id). */
  private async nombreArchivoKude(tipoDocumento: number, documentoId: string, empresaId: string): Promise<string> {
    const where = { id: documentoId, empresa_id: empresaId };
    const select = { dest: true, dpunexp: true, dnumdoc: true };
    let doc: { dest: string | null; dpunexp: string | null; dnumdoc: string | null } | null = null;
    let prefijo = 'kude';
    if (tipoDocumento === 1) {
      prefijo = 'factura';
      doc = await this.prisma.factura_cab.findFirst({ where, select });
    } else if (tipoDocumento === 5) {
      prefijo = 'nota-credito';
      doc = await this.prisma.nota_credito_cab.findFirst({ where, select });
    } else if (tipoDocumento === 7) {
      prefijo = 'nota-remision';
      doc = await this.prisma.nota_remision_cab.findFirst({ where, select });
    }
    const numero = doc?.dest && doc.dpunexp && doc.dnumdoc ? `${doc.dest}-${doc.dpunexp}-${doc.dnumdoc}` : fechaArchivo();
    return nombreArchivo(['kude', prefijo, numero], 'pdf');
  }

  @Post('generate')
  @UseGuards(AuthGuard('jwt'))
  @ApiBearerAuth()
  @ApiOperation({ summary: 'Genera el KUDE (PDF) de un documento electrónico' })
  @ApiBody({ type: GenerateKudeDto })
  async generateKude(
    @Body() dto: GenerateKudeDto,
    @GetUser() user: LoginUserInfo,
    @Res() res: Response,
  ) {
    try {
      const options = {
        ticket: dto.ticket ?? false,
        tipo_retorno: dto.tipo_retorno ?? 'view',
      };

      let result: { pdfBuffer?: Buffer; base64?: string; contentType: string };

      switch (dto.tipo_documento) {
        case 1: // Factura
          result = await this.kudeService.generateKudeFactura(dto.documento_id, user.empresa_id, options);
          break;
        case 5: // Nota de Crédito
          result = await this.kudeService.generateKudeNotaCredito(dto.documento_id, user.empresa_id, options);
          break;
        case 7: // Nota de Remisión
          result = await this.kudeService.generateKudeNotaRemision(dto.documento_id, user.empresa_id, options);
          break;
        default:
          throw new HttpException(
            { message: `Tipo de documento ${dto.tipo_documento} no soportado aún` },
            HttpStatus.BAD_REQUEST,
          );
      }

      if (options.tipo_retorno === 'base64') {
        return res.json({ status: 'success', kude_base64: result.base64 });
      }

      // Retornar PDF binario
      const filename = await this.nombreArchivoKude(dto.tipo_documento, dto.documento_id, user.empresa_id);
      res.set({
        'Content-Type': 'application/pdf',
        'Content-Disposition': `inline; filename="${filename}"`,
      });

      if (result.pdfBuffer) {
        res.send(result.pdfBuffer);
      }
    } catch (error) {
      if (error instanceof HttpException) throw error;
      const errorMessage = error instanceof Error ? error.message : 'Error desconocido';
      throw new HttpException(
        { success: false, message: 'Error al generar KUDE', error: errorMessage },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }
}
