"""
Punto de entrada de validación para import de una fila pedimento.
Flujo Clarion:
  - Modo actualizar: crear si no existe, actualizar si existe. Si existe → VALIDA_PARCIAL; si no existe → VALIDA_TODA.
  - Modo crear: crear siempre; si existe reemplazar. Siempre VALIDA_TODA.
Legacy: si la fila no tiene PEDIMENTO (Col A Clarion), se usa validación por AÑO/ADUANA/PATENTE/NUMERO.
"""
from typing import Dict, Any, Optional, Set, Tuple, List

from ..template_config import is_clarion_layout, parse_pedimento_col_a
from ..common.fk_loader import pedimento_key_from_parsed
from .common import (
    validate_row_desfase_pedimento,
    validate_row_pedimento_required_col_a,
    validate_row_pedimento_format,
    validate_row_pedimento_required_three_cols,
    validate_row_pedimento_required_full,
    validaciones_pedimento,
    validate_row_pedimento_required_legacy,
    validate_row_pedimento_fk_legacy,
    validate_row_pedimento_optionals_legacy,
)


def _clarion_pedimento_key(row: Dict[str, Any]) -> Optional[str]:
    """Construye la clave (year|customs_office|license|pedimento_number) desde fila Clarion (3 cols o PEDIMENTO)."""
    año = (row.get("AÑO") or "").strip()
    patente = (row.get("PATENTE") or "").strip()
    numero = (row.get("NUMERO") or "").strip()
    if año and patente and numero:
        aduana = (row.get("ADUANA_SECCION_CRUCE") or "").strip()[:3]
        return pedimento_key_from_parsed(año[:2], aduana, patente[:4], numero[:7])
    parsed = parse_pedimento_col_a((row.get("PEDIMENTO") or "").strip())
    if not parsed:
        return None
    year, license_val, pedimento_number = parsed
    aduana = (row.get("ADUANA_SECCION_CRUCE") or "").strip()[:3]
    return pedimento_key_from_parsed(year, aduana, license_val, pedimento_number)


def validate_row_pedimento(
    row: Dict[str, Any],
    line_num: int,
    short_name_to_id: Dict[str, int],
    valid_regimes: Set[str],
    valid_pedimento_codes: Set[str],
    valid_clave_regimen_tipo: Set[Tuple[str, str, str]],
    valid_aduana_seccion: Set[str],
    existing_pedimento_keys: Set[str],
    valid_anexo22_claves: Set[str],
    valid_patentes: Set[str],
    actualizar: bool = False,
    raw_row: Optional[Dict[str, Any]] = None,
    date_format_preference: Optional[str] = None,
) -> List[Dict[str, Any]]:
    """
    Valida una fila de CSV de pedimentos.
    - Si raw_row está presente, se valida desfase (Col N) primero.
    - Layout Clarion (PEDIMENTO con valor): flujo VALIDA_TODA / VALIDA_PARCIAL según actualizar y existing_pedimento_keys.
    - Layout legacy (sin PEDIMENTO): requeridos AÑO, ADUANA, PATENTE, NUMERO, CODIGO_PEDIMENTO, REGIMEN; CLIENTE_SHORT_NAME opcional.
    """
    errors: List[Dict[str, Any]] = []

    if raw_row is not None:
        err = validate_row_desfase_pedimento(raw_row, line_num)
        if err:
            errors.append(err)

    if not is_clarion_layout(row):
        err = validate_row_pedimento_required_legacy(row, line_num)
        if err:
            errors.append(err)

        err = validate_row_pedimento_fk_legacy(
            row, line_num, short_name_to_id, valid_regimes, valid_pedimento_codes
        )
        if err:
            errors.append(err)

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

        return errors

    # Layout Clarion: validar Cols 1-3 (AÑO, PATENTE, NUMERO) o Col A (PEDIMENTO) si compatibilidad
    has_three_cols = (
        (row.get("AÑO") or "").strip()
        and (row.get("PATENTE") or "").strip()
        and (row.get("NUMERO") or "").strip()
    )
    if has_three_cols:
        err = validate_row_pedimento_required_three_cols(row, line_num)
    else:
        err = validate_row_pedimento_required_col_a(row, line_num)
        # Formato solo aplica cuando hay valor en Col A, pero podemos acumular igualmente.
        fmt_err = validate_row_pedimento_format(row, line_num)
        if fmt_err:
            errors.append(fmt_err)

    if err:
        errors.append(err)

    key = _clarion_pedimento_key(row)
    # Actualizar: si existe → validación parcial; si no existe → validación completa (crear).
    # Crear: siempre validación completa (crear siempre; si existe reemplazar).
    use_partial = (
        actualizar
        and key is not None
        and key in existing_pedimento_keys
    )

    if use_partial:
        errors.extend(
            validaciones_pedimento(
            row,
            line_num,
            valid_clave_regimen_tipo,
            valid_aduana_seccion,
            valid_anexo22_claves,
            valid_patentes,
            short_name_to_id=short_name_to_id,
            date_format_preference=date_format_preference,
        )
        )
        return errors

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

    errors.extend(
        validaciones_pedimento(
            row,
            line_num,
            valid_clave_regimen_tipo,
            valid_aduana_seccion,
            valid_anexo22_claves,
            valid_patentes,
            short_name_to_id=short_name_to_id,
            date_format_preference=date_format_preference,
        )
    )
    return errors
