"""Generación de condición de operación (gCamCond).

Incluye pagos/entregas para contado y estructuras básicas para crédito.
"""

from __future__ import annotations

from lxml import etree

from .catalogs import descripcion_moneda


def _descripcion_condicion_operacion(tipo: int) -> str:
    """Descripción mínima de la condición de operación."""
    if tipo == 1:
        return "Contado"
    if tipo == 2:
        return "Crédito"
    return ""


def _descripcion_condicion_credito(tipo: int) -> str:
    """Descripción mínima de la condición de crédito."""
    if tipo == 1:
        return "Plazo"
    if tipo == 2:
        return "Cuota"
    return ""


def _descripcion_tipo_pago(tipo: int) -> str:
    """Descripción mínima del tipo de pago."""
    if tipo == 1:
        return "Efectivo"
    if tipo == 2:
        return "Cheque"
    if tipo == 3:
        return "Tarjeta de crédito"
    if tipo == 4:
        return "Tarjeta de débito"
    if tipo == 5:
        return "Transferencia"
    if tipo == 10:
        return "Retención"
    if tipo == 99:
        return "Otro"
    return ""


def build_gcamcond(parent: etree._Element, data: dict) -> None:
    """Construye `gCamCond` dentro de `gDtipDE` si `data.condicion` existe."""
    condicion = data.get("condicion")
    if not condicion:
        return

    tipo = int(condicion.get("tipo") or 0)

    gcamcond = etree.SubElement(parent, "gCamCond")
    etree.SubElement(gcamcond, "iCondOpe").text = str(tipo)
    etree.SubElement(gcamcond, "dDCondOpe").text = _descripcion_condicion_operacion(tipo)

    # Crédito (v150): cuando iCondOpe=2, el grupo gPagCred es obligatorio.
    # Fuente: tgCamCond -> gPagCred (DE_v150.xsd)
    credito = condicion.get("credito") or {}
    if tipo == 2:
        gpagcred = etree.SubElement(gcamcond, "gPagCred")
        i_cond_cred = int(credito.get("tipo") or 1)
        if i_cond_cred not in (1, 2):
            i_cond_cred = 1
        etree.SubElement(gpagcred, "iCondCred").text = str(i_cond_cred)
        etree.SubElement(gpagcred, "dDCondCred").text = _descripcion_condicion_credito(i_cond_cred)

        # dPlazoCre solo aplica si iCondCred=1 (Plazo)
        if i_cond_cred == 1:
            # Plazo del crédito (string 2..15). Si viene como días numérico, lo formateamos.
            plazo = credito.get("plazo")
            if plazo is not None and str(plazo).strip() != "":
                try:
                    plazo_i = int(plazo)
                    if plazo_i > 0:
                        etree.SubElement(gpagcred, "dPlazoCre").text = f"{plazo_i} dias"
                except Exception:
                    # Si viene como texto (ej: "30 dias"), lo usamos tal cual.
                    plazo_s = str(plazo).strip()
                    if len(plazo_s) >= 2:
                        etree.SubElement(gpagcred, "dPlazoCre").text = plazo_s[:15]

        # dCuotas solo aplica si iCondCred=2 (Cuota)
        cuotas = credito.get("cuotas")
        if i_cond_cred == 2 and cuotas is not None and str(cuotas).strip() != "":
            try:
                cuotas_i = int(cuotas)
                if cuotas_i > 0:
                    etree.SubElement(gpagcred, "dCuotas").text = str(cuotas_i)
            except Exception:
                pass

        # dMonEnt (monto de entrega inicial) opcional para crédito
        try:
            ent_ini = float(credito.get("entrega_inicial") or 0.0)
        except Exception:
            ent_ini = 0.0
        if ent_ini > 0:
            # tMontoBase4
            etree.SubElement(gpagcred, "dMonEnt").text = f"{ent_ini:.4f}"

    entregas = condicion.get("entregas") or []
    if entregas:
        for entrega in entregas:
            gpa = etree.SubElement(gcamcond, "gPaConEIni")
            ti_pago = int(entrega.get("tipo") or 0)
            etree.SubElement(gpa, "iTiPago").text = str(ti_pago)
            etree.SubElement(gpa, "dDesTiPag").text = _descripcion_tipo_pago(ti_pago)

            # TS usa toFixed(4)
            monto = float(entrega.get("monto") or 0)
            etree.SubElement(gpa, "dMonTiPag").text = f"{monto:.4f}"

            moneda = entrega.get("moneda")
            if moneda is not None:
                etree.SubElement(gpa, "cMoneTiPag").text = str(moneda)
            mon_desc = entrega.get("monedaDescripcion")
            if mon_desc is None and moneda is not None:
                mon_desc = descripcion_moneda(str(moneda))
            if mon_desc:
                etree.SubElement(gpa, "dDMoneTiPag").text = str(mon_desc)

            cambio = entrega.get("cambio")
            if moneda is not None and str(moneda) != "PYG" and cambio:
                etree.SubElement(gpa, "dTiCamTiPag").text = str(cambio)
