"""
Validaciones comunes de fila para import CSV de agentes aduanales.
Paridad Clarion: VALIDA_TODA_AGENTE_ADUANAL, VALIDA_PARCIAL_AGENTE_ADUANAL, VALIDACIONES_AGENTE_ADUANAL.
"""
from typing import Dict, Any, Optional, Set, List

from ..common.common_validators import (
    check_required_broker_key,
    check_optional_license,
    check_desfase,
    check_tipo_mex_ame,
    check_patente_obligatoria_si_mex,
    check_rfc_max,
    check_curp_max,
    check_rfc_format,
    check_curp_format,
    check_pais_catalogo,
    check_phone_format,
    check_optional_email_format,
)

MSG_CLAVE_NO_EXISTE = "Error: (Col. B) Clave de A. Aduanal No Existe en el Catalogo."
MSG_CLAVE_NO_EXISTE_SOLUCION = "La clave debe existir en el catálogo cuando el modo es Actualizar."
MSG_CAMPOS_OBLIGATORIOS = "Existen campos vacíos que son obligatorios, es la {campos}."
MSG_CAMPOS_OBLIGATORIOS_SOLUCION = "Revisar la línea del archivo y capturar los campos con la información correcta."


def validaciones_agente_aduanal(
    row: Dict[str, Any],
    line_num: int,
    valid_country_m3: Optional[Set[str]] = None,
) -> List[Dict[str, Any]]:
    """
    VALIDACIONES_AGENTE_ADUANAL: reglas de dominio compartidas.
    Tipo MEX/AME + coherencia País, patente si MEX, RFC/CURP máx, país en catálogo, licencia formato.
    """
    errors: List[Dict[str, Any]] = []

    checks = [
        check_tipo_mex_ame,
        check_patente_obligatoria_si_mex,
        check_optional_license,
        check_rfc_max,
        check_rfc_format,
        check_curp_max,
        check_curp_format,
        lambda r, ln: check_pais_catalogo(r, ln, valid_country_m3),
        check_optional_email_format,
        check_phone_format,
    ]

    for fn in checks:
        err = fn(row, line_num)
        if err:
            errors.append(err)

    return errors


def valida_toda_agente_aduanal(
    row: Dict[str, Any],
    line_num: int,
    valid_country_m3: Optional[Set[str]] = None,
) -> List[Dict[str, Any]]:
    """
    VALIDA_TODA: TIPO (Col A) y NOMBRE (Col D) obligatorios; luego VALIDACIONES_AGENTE_ADUANAL.
    """
    campos_oblig = []
    if not (row.get("TIPO") or "").strip():
        campos_oblig.append("(Col.A) Tipo")
    if not (row.get("NOMBRE") or "").strip():
        campos_oblig.append("(Col.D) Nombre")
    if campos_oblig:
        err = {
            "line": line_num,
            "col": "TIPO" if not (row.get("TIPO") or "").strip() else "NOMBRE",
            "msg": MSG_CAMPOS_OBLIGATORIOS.format(campos=", ".join(campos_oblig)),
            "solution": MSG_CAMPOS_OBLIGATORIOS_SOLUCION,
        }
        # No cortamos: también queremos ver errores de columnas dependientes/no-dependientes.
        return [err] + validaciones_agente_aduanal(row, line_num, valid_country_m3)

    return validaciones_agente_aduanal(row, line_num, valid_country_m3)


def valida_parcial_agente_aduanal(
    row: Dict[str, Any],
    line_num: int,
    valid_country_m3: Optional[Set[str]] = None,
) -> List[Dict[str, Any]]:
    """VALIDA_PARCIAL: solo VALIDACIONES_AGENTE_ADUANAL (no exige TIPO ni NOMBRE)."""
    return validaciones_agente_aduanal(row, line_num, valid_country_m3)


def validate_row_customs_broker(
    row: Dict[str, Any],
    line_num: int,
    actualizar: bool = False,
    existing_broker_keys: Optional[Set[str]] = None,
    valid_country_m3: Optional[Set[str]] = None,
) -> List[Dict[str, Any]]:
    """
    Valida una fila de CSV de agentes aduanales.
    1. Desfase (COL_EXTRA) primero.
    2. Clave vacía → error.
    3. Si actualizar y clave no existe en existing_broker_keys → error.
    4. Si actualizar y clave existe → valida_parcial_agente_aduanal.
    5. Si no actualizar o clave no existe → valida_toda_agente_aduanal.
    """
    errors: List[Dict[str, Any]] = []

    err = check_desfase(row, line_num)
    if err:
        errors.append(err)

    err = check_required_broker_key(row, line_num)
    if err:
        errors.append(err)

    clave = (row.get("CLAVE") or "").strip()
    existing = existing_broker_keys or set()
    use_partial = actualizar and clave in existing

    if actualizar and clave and clave not in existing:
        errors.append({
            "line": line_num,
            "col": "CLAVE",
            "msg": MSG_CLAVE_NO_EXISTE,
            "solution": MSG_CLAVE_NO_EXISTE_SOLUCION,
        })

    if use_partial:
        errors.extend(valida_parcial_agente_aduanal(row, line_num, valid_country_m3))
    else:
        errors.extend(valida_toda_agente_aduanal(row, line_num, valid_country_m3))

    return errors
