# -*- coding: utf-8 -*-
"""
================================================================================
PARTE 2 — EGRESOS (DFPGFC) — Libro Excel independiente de plano_siigo_compras.xlsx
================================================================================
Cruce cuentas por pagar (2205* / 2335*) vs tesorería 11050501, comprobante tipo 11
(Egresos en SIIGO). Misma base de datos COMPRAS + BASE PROVEEDORES que la parte 1.

Ejecutar:  python generar_egresos_siigo.py

Parámetros (cuenta tesorería, consecutivo inicial, nombre de salida, etc.):
  generar_plano_siigo.py — bloque «PARÁMETROS DEL PROYECTO» y constantes RUTA_SALIDA_EGRESOS.
"""
import os

import pandas as pd

import generar_plano_siigo as gps


def _cxp_cuenta_aplica_egreso(cxp_str):
    c = str(cxp_str or "").strip()
    return c.startswith("2205") or c.startswith("2335")


def _calc_retenciones_y_totales(row, prov_row):
    """
    Mismos totales que la línea CxP del plano principal (Fedepapa + retenciones).
    Devuelve (cxpagar_cuenta, total_retenciones, total_doc).
    """
    base_doc = gps.valor_num(row.get("BASE", 0))
    total_doc = gps.valor_num(row.get("Total", 0))
    cxpagar_cuenta = gps.cuenta_del_proveedor(prov_row, "CxPagar", gps.CUENTA_CXPAGAR_DEFECTO)

    fedepapa_cuenta = gps.cuenta_del_proveedor(prov_row, gps.COL_FEDEPAPA_PROVEEDOR, "")
    if not fedepapa_cuenta:
        for cand in ("FEDEPAPA", "Fedepapá"):
            fedepapa_cuenta = gps.cuenta_del_proveedor(prov_row, cand, "")
            if fedepapa_cuenta:
                break
    cxp_es_2205 = str(cxpagar_cuenta).strip().startswith("2205")
    aplica_fedepapa = bool(fedepapa_cuenta) and base_doc > 0 and cxp_es_2205
    fedepapa_monto = round(base_doc * 0.01, 2) if aplica_fedepapa else 0

    rete_iva_monto = gps.valor_num(row.get("Rete IVA", 0))
    rete_ica_monto = gps.valor_num(row.get("Rete ICA", 0))
    rete_renta_monto = gps.valor_num(row.get("Rete Renta", 0))
    if gps.APLICAR_RETE_RENTA_POR_REGLA and rete_renta_monto <= 0:
        base_min, tarifa_pct = gps.retencion_renta_regla(prov_row, base_doc)
        if base_min is not None and tarifa_pct is not None and base_doc >= base_min:
            rete_renta_monto = round(base_doc * tarifa_pct / 100, 2)
            if not gps.cuenta_del_proveedor(prov_row, "Rete Renta", ""):
                rete_renta_monto = 0
    total_retenciones = rete_iva_monto + rete_renta_monto + rete_ica_monto + fedepapa_monto
    return cxpagar_cuenta, total_retenciones, total_doc


def main():
    merged, bp_uniq, columnas_plano, COL = gps.cargar_merged_y_plano()

    consecutivo_11 = gps.CONSECUTIVO_INICIAL_11
    lineas = []

    def rellenar_base_egreso(row, consecutivo_comp, tipo_comp_orig, incluir_prefijo=False):
        prefijo_texto = gps.prefijo_documento(row, tipo_comp_orig)
        folio = row.get("Folio")
        if pd.notna(folio) and isinstance(folio, float):
            folio = int(folio)
        folio = str(folio).strip() if folio is not None else ""
        # Fecha de elaboración del egreso = misma lógica que fecha en línea CxP del plano 1 (emisión / venc. CxP)
        fecha_fab = gps.fecha_emision_str(row)
        nit = str(row.get("NIT Emisor", "")).strip()
        ref_doc = f"{prefijo_texto}-{folio}".strip("-").strip()
        desc = f"{gps.PREFIJO_TEXTO_EGRESO_CANCELACION} {ref_doc}".strip() if ref_doc else gps.PREFIJO_TEXTO_EGRESO_CANCELACION
        desc = desc[:200]
        return {
            COL["tipo_comprobante"]: gps.TIPO_COMPROBANTE_EGRESOS,
            COL["consecutivo"]: consecutivo_comp,
            COL["fecha_elab"]: fecha_fab,
            COL["sigla_moneda"]: None,
            COL["tasa_cambio"]: None,
            COL["id_tercero"]: nit,
            COL["sucursal"]: None,
            COL["cod_producto"]: None,
            COL["cod_bodega"]: None,
            COL["accion"]: None,
            COL["cantidad"]: None,
            COL["prefijo"]: prefijo_texto if incluir_prefijo else None,
            COL["consecutivo_doc"]: folio if incluir_prefijo else None,
            COL["no_cuota"]: None,
            COL["fecha_venc"]: None,
            COL["codigo_impuesto"]: None,
            COL["cod_grupo_activo"]: None,
            COL["cod_activo_fijo"]: None,
            COL["descripcion"]: desc,
            COL["centro_costos"]: None,
            COL["debito"]: None,
            COL["credito"]: None,
            COL["observaciones"]: desc,
            COL["base_gravable"]: None,
            COL["base_exenta"]: None,
            COL["mes_cierre"]: None,
        }

    fecha_para_cxp = gps.fecha_emision_str

    for idx, row in merged.iterrows():
        nit_norm = row["nit_norm"]
        prov = bp_uniq[bp_uniq["nit_norm"] == nit_norm]
        prov_row = prov.iloc[0] if len(prov) else pd.Series({})

        tipo_comp = gps.tipo_comprobante_desde_row(row, prov_row)
        cxpagar_cuenta, total_retenciones, total_doc = _calc_retenciones_y_totales(row, prov_row)

        if not _cxp_cuenta_aplica_egreso(cxpagar_cuenta):
            continue
        monto = round(total_doc - total_retenciones, 2)
        if monto <= 0:
            continue

        fecha_doc_str = fecha_para_cxp(row)
        consecutivo_comp = consecutivo_11
        consecutivo_11 += 1

        # 1) Tesorería 11050501: crédito (sin prefijo ni consecutivo documento)
        lin_t = rellenar_base_egreso(row, consecutivo_comp, tipo_comp, incluir_prefijo=False)
        lin_t[COL["codigo_cuenta"]] = gps.CUENTA_TESORERIA_EGRESOS
        lin_t[COL["credito"]] = monto
        lin_t[COL["debito"]] = None
        gps.limpiar_codigo_impuesto_si_cuenta_5(lin_t, COL["codigo_cuenta"], COL["codigo_impuesto"])
        gps.fijar_vencimiento_y_cuota_si_aplica(lin_t, COL["codigo_cuenta"], COL["no_cuota"], COL["fecha_venc"], fecha_doc_str)
        lineas.append(lin_t.copy())

        # 2) CxP: débito; prefijo, consecutivo doc, cuota y venc. solo en esta línea
        lin_c = rellenar_base_egreso(row, consecutivo_comp, tipo_comp, incluir_prefijo=True)
        lin_c[COL["codigo_cuenta"]] = str(cxpagar_cuenta).strip()
        lin_c[COL["debito"]] = monto
        lin_c[COL["credito"]] = None
        gps.limpiar_codigo_impuesto_si_cuenta_5(lin_c, COL["codigo_cuenta"], COL["codigo_impuesto"])
        gps.fijar_vencimiento_y_cuota_si_aplica(lin_c, COL["codigo_cuenta"], COL["no_cuota"], COL["fecha_venc"], fecha_doc_str)
        lineas.append(lin_c.copy())

    df_out = pd.DataFrame(lineas)
    df_out = df_out[[c for c in columnas_plano if c in df_out.columns]]

    col_deb = columnas_plano[21]
    col_cred = columnas_plano[22]
    total_deb = pd.to_numeric(df_out[col_deb], errors="coerce").fillna(0).sum()
    total_cred = pd.to_numeric(df_out[col_cred], errors="coerce").fillna(0).sum()
    print()
    print("--- Egresos (DFPGFC) ---")
    print("Documentos (pares) generados:", len(lineas) // 2)
    print("Líneas:", len(df_out))
    print("Total débitos: ", total_deb)
    print("Total créditos:", total_cred)
    if abs(total_deb - total_cred) > 0.02:
        print("ADVERTENCIA: En egresos los totales débito/crédito no cuadran.")
    else:
        print("Validación OK: débitos = créditos.")

    base_dir = os.path.dirname(os.path.abspath(__file__))
    ruta = os.path.join(base_dir, gps.RUTA_SALIDA_EGRESOS)
    df_out.to_excel(ruta, sheet_name=gps.HOJA_EGRESOS, index=False)
    print("Guardado:", ruta, "| hoja:", gps.HOJA_EGRESOS)
    return df_out


if __name__ == "__main__":
    main()
