import type { Prisma, PrismaClient } from '@prisma/client';

/**
 * Una cuota que está en una orden de pago «abierta» todavía no se pagó, pero ya
 * está comprometida: no puede entrar en otra orden (sería pagarla dos veces).
 * Abierta = cualquier estado que no sea PAGADO ni ANULADA (o una orden con anulado = true;
 * anular una orden, aun pagada, libera sus cuotas). RECHAZADA cuenta como
 * abierta porque se puede corregir y volver a enviar; para liberar la cuota hay
 * que anularla.
 */
export const ESTADOS_OP_CERRADA = ['PAGADO', 'ANULADA', 'ANULADO'];

export interface OrdenAbierta {
  orden_id: string;
  numero: string;
  estado: string;
  /** Fecha de pago de la orden (YYYY-MM-DD). */
  fecha_pago: string | null;
}

type Db = PrismaClient | Prisma.TransactionClient;

export async function ordenesAbiertasPorCuota(db: Db, empresaId: string, cuentaPagarIds: string[], excluirOrdenId?: string): Promise<Map<string, OrdenAbierta>> {
  if (!cuentaPagarIds.length) return new Map();
  const dets = await db.orden_pago_proveedor_det.findMany({
    where: {
      cuenta_pagar_id: { in: cuentaPagarIds },
      orden_pago_proveedor_cab: {
        empresa_id: empresaId,
        activo: true,
        OR: [{ anulado: false }, { anulado: null }],
        estado: { notIn: ESTADOS_OP_CERRADA },
        ...(excluirOrdenId ? { id: { not: excluirOrdenId } } : {}),
      },
    },
    select: { cuenta_pagar_id: true, orden_pago_proveedor_cab: { select: { id: true, numero_orden_pago: true, estado: true, fecha_pago: true } } },
  });
  const out = new Map<string, OrdenAbierta>();
  for (const d of dets) {
    const cab = d.orden_pago_proveedor_cab;
    out.set(d.cuenta_pagar_id, {
      orden_id: cab.id,
      numero: cab.numero_orden_pago,
      estado: String(cab.estado || 'BORRADOR').toUpperCase(),
      fecha_pago: cab.fecha_pago ? new Date(cab.fecha_pago).toISOString().slice(0, 10) : null,
    });
  }
  return out;
}

const ESTADO_LEGIBLE: Record<string, string> = {
  BORRADOR: 'en borrador',
  PENDIENTE_APROBACION: 'pendiente de aprobación',
  PENDIENTE: 'aprobada, sin ejecutar',
  RECHAZADA: 'rechazada (anulala para liberar la cuota)',
};

export const describirOrdenAbierta = (o: OrdenAbierta) => `${o.numero} (${ESTADO_LEGIBLE[o.estado] ?? o.estado.toLowerCase()})`;
