import type { Pool } from 'pg';

export interface MetricaMensual {
  anio: number;
  mes: number;
  regimenFiscal: string | null;
  ivaTrasladado16: number;
  ivaTrasladado8: number;
  ivaTrasladado0: number;
  ivaTrasladadoExento: number;
  ivaTrasladadoTotal: number;
  ivaAcreditable: number;
  ivaRetenidoCobrado: number;
  ivaRetenidoPagado: number;
  ivaResultado: number;
  ivaAFavorMes: number;
  isrIngresosBrutos: number;
  isrDeduccionesAutoriz: number;
  isrBase: number;
  isrCausado: number;
  isrRetenido: number;
  isrAPagar: number;
  cfdisEmitidosCount: number;
  cfdisRecibidosCount: number;
  cfdisCanceladosCount: number;
  ingresosDevengados: number;
  ingresosCobrados: number;
  egresosDevengados: number;
  egresosPagados: number;
  utilidadDevengada: number;
  utilidadRealizada: number;
  flujoEntradas: number;
  flujoSalidas: number;
  flujoNeto: number;
  cxcSaldoFinal: number;
  cxpSaldoFinal: number;
  cerrado: boolean;
  computedAt: string;
}

export async function getMetricasMensuales(
  pool: Pool,
  contribuyenteId: string,
  anio: number,
  regimenFiscal?: string
): Promise<MetricaMensual[]> {
  const currentYear = new Date().getFullYear();

  if (anio < currentYear) {
    // COLD: read pre-computed
    const params: unknown[] = [contribuyenteId, anio];
    let query = `
      SELECT
        anio, mes,
        regimen_fiscal AS "regimenFiscal",
        iva_trasladado_16 AS "ivaTrasladado16",
        iva_trasladado_8 AS "ivaTrasladado8",
        iva_trasladado_0 AS "ivaTrasladado0",
        iva_trasladado_exento AS "ivaTrasladadoExento",
        iva_trasladado_total AS "ivaTrasladadoTotal",
        iva_acreditable AS "ivaAcreditable",
        iva_retenido_cobrado AS "ivaRetenidoCobrado",
        iva_retenido_pagado AS "ivaRetenidoPagado",
        iva_resultado AS "ivaResultado",
        iva_a_favor_mes AS "ivaAFavorMes",
        isr_ingresos_brutos AS "isrIngresosBrutos",
        isr_deducciones_autoriz AS "isrDeduccionesAutoriz",
        isr_base AS "isrBase",
        isr_causado AS "isrCausado",
        isr_retenido AS "isrRetenido",
        isr_a_pagar AS "isrAPagar",
        cfdis_emitidos_count AS "cfdisEmitidosCount",
        cfdis_recibidos_count AS "cfdisRecibidosCount",
        cfdis_cancelados_count AS "cfdisCanceladosCount",
        ingresos_devengados AS "ingresosDevengados",
        ingresos_cobrados AS "ingresosCobrados",
        egresos_devengados AS "egresosDevengados",
        egresos_pagados AS "egresosPagados",
        utilidad_devengada AS "utilidadDevengada",
        utilidad_realizada AS "utilidadRealizada",
        flujo_entradas AS "flujoEntradas",
        flujo_salidas AS "flujoSalidas",
        flujo_neto AS "flujoNeto",
        cxc_saldo_final AS "cxcSaldoFinal",
        cxp_saldo_final AS "cxpSaldoFinal",
        cerrado,
        computed_at AS "computedAt"
      FROM metricas_mensuales
      WHERE contribuyente_id = $1 AND anio = $2
    `;
    if (regimenFiscal) {
      query += ' AND regimen_fiscal = $3';
      params.push(regimenFiscal);
    }
    query += ' ORDER BY mes';

    const { rows } = await pool.query(query, params);
    return rows.map(r => ({ ...r, cerrado: r.cerrado ?? false, computedAt: r.computedAt?.toISOString?.() ?? '' }));
  }

  // HOT: current year — return empty (caller should use dashboard/impuestos services for on-the-fly computation)
  return [];
}

export async function markForInvalidation(
  pool: Pool,
  contribuyenteId: string,
  anio: number,
  mes: number,
  reason: string
): Promise<void> {
  await pool.query(`
    INSERT INTO metricas_invalidaciones (contribuyente_id, anio, mes, reason)
    VALUES ($1, $2, $3, $4)
    ON CONFLICT (contribuyente_id, anio, mes) DO UPDATE SET marcado_at = now(), reason = $4
  `, [contribuyenteId, anio, mes, reason]);
}

export async function getPendingInvalidations(pool: Pool): Promise<Array<{
  contribuyenteId: string;
  anio: number;
  mes: number;
  reason: string;
}>> {
  const { rows } = await pool.query(`
    SELECT contribuyente_id AS "contribuyenteId", anio, mes, reason
    FROM metricas_invalidaciones
    ORDER BY anio, mes
  `);
  return rows;
}

export async function clearInvalidation(pool: Pool, contribuyenteId: string, anio: number, mes: number): Promise<void> {
  await pool.query(
    'DELETE FROM metricas_invalidaciones WHERE contribuyente_id = $1 AND anio = $2 AND mes = $3',
    [contribuyenteId, anio, mes]
  );
}

export async function upsertMetricaMensual(
  pool: Pool,
  contribuyenteId: string,
  anio: number,
  mes: number,
  regimenFiscal: string | null,
  data: Partial<MetricaMensual>
): Promise<void> {
  await pool.query(`
    INSERT INTO metricas_mensuales (
      contribuyente_id, anio, mes, regimen_fiscal,
      iva_trasladado_total, iva_acreditable, iva_retenido_cobrado, iva_retenido_pagado, iva_resultado,
      isr_ingresos_brutos, isr_deducciones_autoriz, isr_base, isr_causado, isr_retenido, isr_a_pagar,
      cfdis_emitidos_count, cfdis_recibidos_count, cfdis_cancelados_count,
      ingresos_devengados, ingresos_cobrados, egresos_devengados, egresos_pagados,
      utilidad_devengada, utilidad_realizada,
      flujo_entradas, flujo_salidas, flujo_neto,
      cxc_saldo_final, cxp_saldo_final,
      computed_at, source_max_cfdi_at
    ) VALUES (
      $1, $2, $3, $4,
      $5, $6, $7, $8, $9,
      $10, $11, $12, $13, $14, $15,
      $16, $17, $18,
      $19, $20, $21, $22,
      $23, $24,
      $25, $26, $27,
      $28, $29,
      now(), now()
    )
    ON CONFLICT (contribuyente_id, anio, mes, regimen_fiscal)
    DO UPDATE SET
      iva_trasladado_total = $5, iva_acreditable = $6, iva_retenido_cobrado = $7, iva_retenido_pagado = $8, iva_resultado = $9,
      isr_ingresos_brutos = $10, isr_deducciones_autoriz = $11, isr_base = $12,
      isr_causado = $13, isr_retenido = $14, isr_a_pagar = $15,
      cfdis_emitidos_count = $16, cfdis_recibidos_count = $17, cfdis_cancelados_count = $18,
      ingresos_devengados = $19, ingresos_cobrados = $20, egresos_devengados = $21, egresos_pagados = $22,
      utilidad_devengada = $23, utilidad_realizada = $24,
      flujo_entradas = $25, flujo_salidas = $26, flujo_neto = $27,
      cxc_saldo_final = $28, cxp_saldo_final = $29,
      computed_at = now(), source_max_cfdi_at = now()
  `, [
    contribuyenteId, anio, mes, regimenFiscal,
    data.ivaTrasladadoTotal ?? 0, data.ivaAcreditable ?? 0, data.ivaRetenidoCobrado ?? 0, data.ivaRetenidoPagado ?? 0, data.ivaResultado ?? 0,
    data.isrIngresosBrutos ?? 0, data.isrDeduccionesAutoriz ?? 0, data.isrBase ?? 0,
    data.isrCausado ?? 0, data.isrRetenido ?? 0, data.isrAPagar ?? 0,
    data.cfdisEmitidosCount ?? 0, data.cfdisRecibidosCount ?? 0, data.cfdisCanceladosCount ?? 0,
    data.ingresosDevengados ?? 0, data.ingresosCobrados ?? 0, data.egresosDevengados ?? 0, data.egresosPagados ?? 0,
    data.utilidadDevengada ?? 0, data.utilidadRealizada ?? 0,
    data.flujoEntradas ?? 0, data.flujoSalidas ?? 0, data.flujoNeto ?? 0,
    data.cxcSaldoFinal ?? 0, data.cxpSaldoFinal ?? 0,
  ]);
}

export async function closeMonth(pool: Pool, anio: number, mes: number): Promise<void> {
  await pool.query(
    'UPDATE metricas_mensuales SET cerrado = true WHERE anio = $1 AND mes = $2',
    [anio, mes]
  );
}

export async function closeYear(pool: Pool, anio: number): Promise<void> {
  await pool.query(
    'UPDATE metricas_mensuales SET cerrado = true WHERE anio = $1',
    [anio]
  );
}
