import { HttpException, HttpStatus, Injectable, Logger, NotFoundException } from '@nestjs/common';
import { envs } from 'src/config/envs';
import { PrismaService } from 'src/prisma/prisma.service';
import { logoEmisor, nombreFantasiaEmisor } from 'src/utils/emisor-comprobante';

type TipoRetorno = 'view' | 'base64';

@Injectable()
export class PresupuestosPdfService {
  private readonly logger = new Logger(PresupuestosPdfService.name);
  private readonly apiUrl = envs.apiGeneradorPDF;

  constructor(private readonly prisma: PrismaService) {}

  /** Construye el payload que consume el microservicio generador-pdf. */
  private async buildPayload(id: string, empresa_id: string) {
    const p = await this.prisma.presupuesto_cab.findFirst({
      where: { id, empresa_id, deleted: false },
      include: {
        items: { orderBy: { orden: 'asc' } },
        clientes: { include: { personas: true } },
        vendedor: true,
        moneda: true,
        // Logo y nombre comercial salen de la sucursal del presupuesto (como en la factura).
        sucursal: { select: { logo: true, nombre_fantasia: true } },
      },
    });
    if (!p) throw new NotFoundException('Presupuesto no encontrado');

    const [empresa, config] = await Promise.all([
      this.prisma.empresas.findUnique({
        where: { id: empresa_id },
        select: { razon_social: true, nombre_fantasia: true, ruc: true, dv: true, celular: true, email: true, logo: true },
      }),
      this.prisma.presupuesto_config.findUnique({ where: { empresa_id } }),
    ]);

    const persona = p.clientes?.personas;
    const num = (v: unknown) => (v == null ? 0 : Number(v));

    return {
      empresa: {
        razon_social: empresa?.razon_social,
        nombre_fantasia: nombreFantasiaEmisor(p.sucursal, empresa),
        ruc: empresa?.ruc,
        dv: empresa?.dv,
        telefono: empresa?.celular,
        email: empresa?.email,
        logo_url: logoEmisor(p.sucursal, empresa) || undefined,
      },
      numero: p.numero,
      version: p.version,
      estado: p.estado,
      fecha_emision: p.fecha_emision,
      fecha_vigencia: p.fecha_vigencia,
      moneda: p.moneda?.codigo || config?.moneda_base || 'PYG',
      tipo_cambio_usd: p.tipo_cambio_usd ? Number(p.tipo_cambio_usd) : null,
      titulo: p.titulo,
      condicion_pago: p.condicion_pago,
      notas_cliente: p.notas_cliente,
      contacto_cliente: p.contacto_cliente,
      texto_legal: config?.texto_legal_pdf || undefined,
      cliente: {
        razon_social: persona?.razon_social,
        ruc: persona?.ruc,
        documento: persona?.nro_documento,
        telefono: persona?.telefono,
        email: persona?.email,
      },
      vendedor: p.vendedor
        ? { nombre: p.vendedor.nombre, apellido: p.vendedor.apellido, email: p.vendedor.email, telefono: p.vendedor.telefono }
        : null,
      items: p.items.map((it) => ({
        orden: it.orden,
        tipo: it.tipo,
        descripcion: it.descripcion,
        notas_item: it.notas_item,
        cantidad: num(it.cantidad),
        unidad_medida: it.unidad_medida,
        precio_unitario: num(it.precio_unitario),
        descuento_pct: num(it.descuento_pct),
        descuento_monto: num(it.descuento_monto),
        iva_categoria: it.iva_categoria,
        subtotal_con_iva: num(it.subtotal_con_iva),
        monto_iva: num(it.monto_iva),
      })),
      totales: {
        subtotal_exento: num(p.subtotal_exento),
        base_iva5: num(p.base_iva5),
        iva5: num(p.iva5),
        base_iva10: num(p.base_iva10),
        iva10: num(p.iva10),
        descuento_global_pct: num(p.descuento_global_pct),
        descuento_global_monto: num(p.descuento_global_monto),
        total: num(p.total),
        total_equivalente: p.total_equivalente != null ? Number(p.total_equivalente) : null,
      },
    };
  }

  /** Genera el PDF del presupuesto llamando al microservicio (patrón kude.service). */
  async generatePdf(id: string, empresa_id: string, tipo: TipoRetorno = 'view'): Promise<Buffer> {
    const payload = await this.buildPayload(id, empresa_id);
    const url = `${this.apiUrl}/api/presupuesto/generate-pdf`;
    this.logger.log(`Generando PDF presupuesto ${payload.numero} (tipo=${tipo})`);

    let response: globalThis.Response;
    try {
      response = await fetch(url, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ ...payload, tipo }),
      });
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Error desconocido';
      throw new HttpException(
        { message: 'No se pudo conectar con el servicio de generación de PDF', detail: message },
        HttpStatus.BAD_GATEWAY,
      );
    }

    if (!response.ok) {
      const errorBody = await response.text();
      this.logger.error(`generador-pdf respondió ${response.status}: ${errorBody}`);
      throw new HttpException({ message: 'Error al generar el PDF del presupuesto', detail: errorBody }, HttpStatus.BAD_GATEWAY);
    }

    if (tipo === 'base64') {
      const json = (await response.json()) as { status: string; pdf_base64?: string; message?: string };
      if (json.status !== 'success' || !json.pdf_base64) {
        throw new HttpException({ message: json.message || 'Error al generar el PDF' }, HttpStatus.BAD_GATEWAY);
      }
      return Buffer.from(json.pdf_base64, 'base64');
    }

    const arrayBuffer = await response.arrayBuffer();
    return Buffer.from(arrayBuffer);
  }
}
