// src/contabilidad/services/saldo-puente-importacion.ts
import { PrismaService } from '../../prisma/prisma.service';

/**
 * Saldo (debe − haber, en guaraníes) que la importación dejó en la cuenta
 * puente: suma las líneas de esa cuenta en los asientos vigentes de su
 * despacho, de las compras y gastos cargados como componentes de costo (y de
 * las notas de crédito de esas compras) y de los pagos de tesorería del
 * embarque. Una NC que no tocó la puente aporta 0. Solo cuenta asientos CONFIRMADO: uno
 * revertido queda REVERTIDO y su espejo se crea sin `origen_id`, así que
 * ninguno de los dos suma. El asiento de cierre (`imp_cierre`) no entra en
 * la búsqueda, por lo que regenerarlo no se resta a sí mismo.
 */
export async function saldoPuenteDeImportacion(
  prisma: PrismaService,
  empresaId: string,
  embarqueId: string,
  cuentaPuente: string,
): Promise<number> {
  const [despachos, componentes, pagos] = await Promise.all([
    prisma.imp_despachos.findMany({ where: { embarque_id: embarqueId }, select: { id: true } }),
    prisma.imp_componentes_costo.findMany({
      where: { embarque_id: embarqueId, empresa_id: empresaId, activo: true },
      select: { compra_id: true, gasto_id: true },
    }),
    prisma.tes_movimientos.findMany({
      where: { embarque_id: embarqueId, estado: { not: 'ANULADO' } },
      select: { id: true },
    }),
  ]);
  const ids = (xs: Array<string | null>) => [...new Set(xs.filter((x): x is string => !!x))];
  const compras = ids(componentes.map((c) => c.compra_id));
  const ncs = compras.length
    ? await prisma.nota_credito_compra_cab.findMany({
        where: { empresa_id: empresaId, compra_id: { in: compras } },
        select: { id: true },
      })
    : [];
  const origenes = [
    { origen_tipo: 'imp_despacho', origen_id: { in: despachos.map((d) => d.id) } },
    { origen_tipo: 'compra_cab', origen_id: { in: compras } },
    { origen_tipo: 'nota_credito_compra_cab', origen_id: { in: ncs.map((n) => n.id) } },
    { origen_tipo: 'gasto_cab', origen_id: { in: ids(componentes.map((c) => c.gasto_id)) } },
    { origen_tipo: 'tes_movimientos', origen_id: { in: pagos.map((p) => p.id) } },
  ].filter((o) => o.origen_id.in.length > 0);
  if (origenes.length === 0) return 0;

  const docs = await prisma.cont_documentos.findMany({
    where: { empresa_id: empresaId, OR: origenes },
    select: { id: true },
  });
  if (docs.length === 0) return 0;
  const asientos = await prisma.cont_asientos.findMany({
    where: { documento_id: { in: docs.map((d) => d.id) }, estado: 'CONFIRMADO' },
    select: { id: true },
  });
  if (asientos.length === 0) return 0;
  const agg = await prisma.cont_asientos_det.aggregate({
    where: { asiento_id: { in: asientos.map((a) => a.id) }, cuenta_id: cuentaPuente },
    _sum: { debe_pyg: true, haber_pyg: true },
  });
  return Math.round((Number(agg._sum.debe_pyg ?? 0) - Number(agg._sum.haber_pyg ?? 0) + Number.EPSILON) * 100) / 100;
}
