"""
Configuración de plantilla CSV para Pedimentos (EstructuraCatPedimentos.xls).
Layout Clarion: Cols 1-3 = AÑO (2), PATENTE (4), NUMERO (7); luego TIPO, CLAVE PEDIMENTO, REGIMEN,
fechas, ADUANA Y SECCION CRUCE, etc. Compatibilidad: PEDIMENTO (##-####-#######) y layout legacy.
"""
import csv
import io
from typing import Dict, List, Any, Optional, Tuple

# Convierte valor de celda a str; si es lista (p. ej. CSV con columnas duplicadas), toma el primer elemento.
# Re-exportado desde common para uso en validators; ver layouts_csv.common.cell_value.
from ..common.cell_value import cell_to_str as _cell_to_str
from ..common.inject_csv_labels_en import inject_en_labels_into_template_columns
from ..common.template_locale import merge_download_header_into_lookup, merge_labels_into_lookup
from .pedimentos_csv_hints import apply_pedimentos_csv_hints
from ..common import csv_reader as common_csv_reader


# Longitudes para validación (sin afectar modelos)
AÑO_LEN = 2
PATENTE_LEN = 4
NUMERO_LEN = 7

# Columnas Clarion (canónicos) + aliases exactos de la plantilla y legacy
TEMPLATE_COLUMNS: Dict[str, List[Dict[str, Any]]] = {
    "pedimentos": [
        # Cols 1-3: AÑO, PATENTE, NUMERO (reemplazan Col A única PEDIMENTO)
        {"canonical": "AÑO", "aliases": ["YEAR", "ANIO"]},
        {"canonical": "PATENTE", "aliases": ["LICENCIA", "LICENSE", "LIC"]},
        {"canonical": "NUMERO", "aliases": ["PEDIMENTO_NUMBER", "PEDIMENTO NUMBER"]},
        # Col B
        {"canonical": "TIPO_OPERACION", "aliases": ["TIPO MOV(I=Importación,E=Exportación)", "TIPO MOV(I=Impotación,E=Expotación)", "TIPO MOV", "TIPO", "OPERATION_TYPE", "OPERACION"]},
        # Col C
        {"canonical": "CLAVE_PEDIMENTO", "aliases": ["CLAVE PEDIMENTO", "CODIGO_PEDIMENTO", "PEDIMENTO_CODE", "CODIGO"]},
        # Col D
        {"canonical": "REGIMEN", "aliases": ["REGIME", "CLAVE RÉGIMEN"]},
        # Col E, F, G
        {"canonical": "FECHA_INICIO", "aliases": ["FECHA INICIO", "FECHA INICIAL"]},
        {"canonical": "FECHA_FINAL", "aliases": ["FECHA FINAL", "FECHA FIN"]},
        {
            "canonical": "FECHA_PAGO",
            "aliases": [
                "FECHA DE PAGO",
                "FECHA PAGO",
                "FECHA_ENTRADA",
                "FECHA ENTRADA",
                "ENTRY_DATE",
                "ENTRY DATE",
            ],
        },
        # Col H
        {"canonical": "ADUANA_SECCION_CRUCE", "aliases": ["ADUANA Y SECCION DE CRUCE", "ADUANA Y SECCION CRUCE", "ADUANA", "CUSTOMS_OFFICE", "CUSTOMS OFFICE"]},
        # Col I
        {"canonical": "ACUSE_ELECTRONICO", "aliases": ["ACUSE ELECTRONICO", "ACUSE ELECTRÓNICO"]},
        # Col J
        {"canonical": "INDIVIDUAL_CONSOLIDADO", "aliases": ["INDIVIDUAL o CONSOLIDADO (IND,CON)", "INDIVIDUAL o CONSOLIDADO", "IND/CON", "INDIVIDUAL CONSOLIDADO"]},
        # Col K, L, M
        {"canonical": "MET_TRANSP_ENTRADA", "aliases": ["MET TRANS ENTRADA", "METODO TRANSP ENTRADA"]},
        {"canonical": "MET_TRANSP_ARRIVO", "aliases": ["MET TRANS ARRIVO", "METODO TRANSP ARRIVO"]},
        {"canonical": "MET_TRANSP_SALIDA", "aliases": ["MET TRANS SALIDA", "METODO TRANSP SALIDA"]},
        # Col N (desfase) y resto de columnas de la plantilla
        {"canonical": "IEPS", "aliases": []},
        {"canonical": "DTA", "aliases": []},
        {"canonical": "CNT", "aliases": []},
        {"canonical": "PREVALIDACION", "aliases": []},
        {"canonical": "MONTO_TIGIE", "aliases": ["MONTO TIGIE"]},
        {"canonical": "PAGO_IMPUESTO", "aliases": ["PAGO IMPUESTO? (S/N)"]},
        {"canonical": "ES_MIXTO", "aliases": ["ES MIXTO (SI/NO)"]},
        {"canonical": "OBS_RECTIFICA", "aliases": ["OBS RECTIFICA"]},
        {"canonical": "OPCION_DESTINO", "aliases": ["OPCION DESTINO(Interior del Pais/Región Fronteriza/Franja Fronteriza)", "OPCION DESTINO"]},
        {"canonical": "VALOR_IVA", "aliases": ["VALOR IVA"]},
        {"canonical": "VALOR_ME", "aliases": ["VALOR ME"]},
        {"canonical": "VALOR_ADUANAS", "aliases": ["VALOR ADUANAS"]},
        {"canonical": "FLETE", "aliases": []},
        {"canonical": "VALOR_SEGUROS", "aliases": ["VALOR SEGUROS"]},
        {"canonical": "SEGUROS", "aliases": []},
        {"canonical": "EMBALAJES", "aliases": []},
        {"canonical": "OTROS_INCREMENTABLES", "aliases": ["OTROS INCREMENTABLES"]},
        {"canonical": "ESTATUS", "aliases": ["ESTATUS (ABIERTO/CERRADO)", "STATUS", "ESTADO"]},
        {"canonical": "PERSONA_REV", "aliases": ["PERSONA REV"]},
        {"canonical": "FECHA_CIERRE", "aliases": ["FECHA CIERRE"]},
        {"canonical": "FECHA_REVISION", "aliases": ["FECHA REVISION"]},
        {"canonical": "FECHA_AUTORIZACION", "aliases": ["FECHA AUTORIZACION"]},
        {"canonical": "FECHA_RECIBIDO", "aliases": ["FECHA RECIBIDO"]},
        {"canonical": "REPRESENTANTE_AA", "aliases": ["REPRESENTANTE AA"]},
        {"canonical": "CLAVE_DEST_ORIGEN", "aliases": ["CLAVE DEST ORIGEN"]},
        {"canonical": "FECHA_ENTRADA_RECINTO", "aliases": ["FECHA ENTRADA RECINTO"]},
        {"canonical": "FECHA_EXTRACCION_RECINTO", "aliases": ["FECHA EXTRACCION RECINTO"]},
        {"canonical": "ERRORES", "aliases": []},
        {"canonical": "FORMA_PAGO_DTA", "aliases": ["FORMA PAGO DTA"]},
        {"canonical": "FORMA_PAGO_IGI", "aliases": ["FORMA PAGO IGI"]},
        {"canonical": "FORMA_PAGO_PREVAL", "aliases": ["FORMA PAGO PREVAL"]},
        {"canonical": "FORMA_PAGO_IVA", "aliases": ["FORMA PAGO IVA"]},
        {"canonical": "RECARGOS", "aliases": []},
        {"canonical": "MULTAS", "aliases": []},
        {"canonical": "IVA_DE_PREV", "aliases": ["IVA DE PREV"]},
        {"canonical": "CUOTAS_COMPENSATORIAS", "aliases": ["CUOTAS CONPENSATORIAS"]},
        {"canonical": "IDENTIFICADORES", "aliases": []},
        {"canonical": "IEPS_2", "aliases": ["IEPS 2"]},
        {"canonical": "FORMA_PAGO_IEPS_2", "aliases": ["FORMA DE PAGO IEPS 2"]},
        {"canonical": "DTA_2", "aliases": ["DTA 2"]},
        {"canonical": "FORMA_PAGO_DTA_2", "aliases": ["FORMA DE PAGO DTA 2"]},
        {"canonical": "IVA_2", "aliases": ["IVA 2"]},
        {"canonical": "FORMA_PAGO_IVA_2", "aliases": ["FORMA DE PAGO IVA 2"]},
        {"canonical": "IGI_2", "aliases": ["IGI 2"]},
        {"canonical": "FORMA_PAGO_IGI_2", "aliases": ["FORMA DE PAGO IGI 2"]},
        {"canonical": "FORMA_PAGO_PREVALIDACION_2", "aliases": ["FORMA DE PAGO PREVALIDACION 2"]},
        {"canonical": "CNT_2", "aliases": ["CNT 2"]},
        {"canonical": "FORMA_PAGO_CNT_2", "aliases": ["FORMA DE PAGO CNT 2"]},
        # Legacy / compatibilidad (PEDIMENTO una columna ##-####-#######, y otros)
        {"canonical": "PEDIMENTO", "aliases": ["NUMERO DE PEDIMENTO (##-####-######)", "NUMERO DE PEDIMENTO", "NUMERO PEDIMENTO", "PED"]},
        {"canonical": "CLIENTE_SHORT_NAME", "aliases": ["CLIENTE", "SHORT_NAME", "CLIENTE_ID", "CLIENT_ID", "ID CLIENTE"]},
        {"canonical": "TIPO_PEDIMENTO", "aliases": ["PEDIMENTO_TYPE", "TIPO PED"]},
        {"canonical": "VALOR_USD", "aliases": ["USD_VALUE", "VALOR USD", "USD"]},
        {"canonical": "PRECIO_PAGADO", "aliases": ["PAID_PRICE", "PRECIO PAGADO"]},
        {"canonical": "PESO_BRUTO", "aliases": ["GROSS_WEIGHT", "PESO BRUTO", "PESO"]},
        {"canonical": "TIPO_CAMBIO", "aliases": ["EXCHANGE_RATE", "TIPO CAMBIO", "CAMBIO"]},
        {"canonical": "OBSERVACIONES", "aliases": ["OBSERVATIONS", "OBS", "NOTAS"]},
    ],
}

inject_en_labels_into_template_columns(TEMPLATE_COLUMNS)

apply_pedimentos_csv_hints(TEMPLATE_COLUMNS.get("pedimentos"))

# Orden de columnas para CSV sin cabecera (primera fila = datos). Usado por detect_headers_or_data.
PEDIMENTOS_TEMPLATE_ORDER: List[str] = [
    item["canonical"] for item in TEMPLATE_COLUMNS["pedimentos"]
]


def _first_row_looks_like_three_cols_data(first_row: List[str]) -> bool:
    """True si las primeras 3 celdas son AÑO (2 dígitos), PATENTE (4), NUMERO (7)."""
    if not first_row or len(first_row) < 3:
        return False
    c0 = (first_row[0] or "").strip()
    c1 = (first_row[1] or "").strip()
    c2 = (first_row[2] or "").strip()
    return (
        len(c0) <= AÑO_LEN and c0.isdigit()
        and len(c1) <= PATENTE_LEN and c1.isdigit()
        and len(c2) <= NUMERO_LEN and c2.isdigit()
    )


def detect_headers_or_data(
    file_path: str,
    normalize_header_fn,
    parse_pedimento_fn,
    encoding: str = "utf-8-sig",
) -> Tuple[Optional[List[str]], bool]:
    """
    Lee la primera línea del CSV y decide si es cabecera o dato.
    - Si las primeras 3 celdas son 2, 4 y 7 dígitos (AÑO, PATENTE, NUMERO) -> has_header=False.
    - Si la primera celda tiene formato ##-####-####### (compatibilidad) -> has_header=False.
    - Si no -> has_header=True. Devuelve (fieldnames, has_header).
    """
    try:
        sample, _ = common_csv_reader.read_text_sample(
            file_path,
            requested_encoding=encoding,
            sample_chars=2048,
        )
    except Exception:
        try:
            sample, _ = common_csv_reader.read_text_sample(
                file_path,
                requested_encoding="auto",
                sample_chars=2048,
            )
        except Exception:
            return None, True
    lines = sample.splitlines()
    if not lines:
        return None, True
    dialect = common_csv_reader.detect_csv_dialect(sample, delimiters=",;\t")
    reader = csv.reader(io.StringIO(lines[0]), dialect=dialect)
    first_row = next(reader, None)
    if not first_row:
        return None, True
    if _first_row_looks_like_three_cols_data(first_row):
        return list(PEDIMENTOS_TEMPLATE_ORDER), False
    first_cell = (first_row[0] or "").strip()
    if parse_pedimento_fn(first_cell) is not None:
        return list(PEDIMENTOS_TEMPLATE_ORDER), False
    return None, True


def build_normalized_lookup(normalize_header_fn, template_id: str = "pedimentos") -> Dict[str, str]:
    """normalized_header -> canonical_name para plantilla pedimentos."""
    cols = TEMPLATE_COLUMNS.get(template_id)
    if not cols:
        return {}
    lookup: Dict[str, str] = {}
    for item in cols:
        canonical = item["canonical"]
        lookup[normalize_header_fn(canonical)] = canonical
        for alias in item.get("aliases") or []:
            lookup[normalize_header_fn(alias)] = canonical
        merge_labels_into_lookup(item, canonical, normalize_header_fn, lookup)
        merge_download_header_into_lookup(item, canonical, normalize_header_fn, lookup)
    return lookup


def row_from_template(row: Dict[str, Any], normalize_header_fn, template_id: str = "pedimentos") -> Dict[str, Any]:
    """Fila CSV con solo columnas de la plantilla, en nombres canónicos. Valores siempre str (listas convertidas)."""
    lookup = build_normalized_lookup(normalize_header_fn, template_id)
    if not lookup:
        return {normalize_header_fn(k): _cell_to_str(v) for k, v in row.items()}
    out: Dict[str, Any] = {}
    for csv_header, value in row.items():
        key_norm = normalize_header_fn(csv_header)
        if key_norm in lookup:
            out[lookup[key_norm]] = _cell_to_str(value)
    return out


# Formato Clarion Col A: ##-####-####### (15 chars, guiones en posiciones 3 y 8, 1-based)
PEDIMENTO_LEN = 15
PEDIMENTO_DASH_POSITIONS = (2, 7)  # 0-based: pos 2 y 7 deben ser '-'


def parse_pedimento_col_a(pedimento_str: str) -> Optional[Tuple[str, str, str]]:
    """
    Parsea Col A (PEDIMENTO) formato ##-####-#######.
    Retorna (year_2, license_4, pedimento_number_7) o None si formato inválido.
    """
    if not pedimento_str or not isinstance(pedimento_str, str):
        return None
    s = (pedimento_str or "").strip()
    if len(s) != PEDIMENTO_LEN:
        return None
    if s[PEDIMENTO_DASH_POSITIONS[0]] != "-" or s[PEDIMENTO_DASH_POSITIONS[1]] != "-":
        return None
    year = s[0:2]
    license_val = s[3:7]
    pedimento_number = s[8:15]
    if not year.isdigit() or not license_val.isdigit() or not pedimento_number.isdigit():
        return None
    return (year, license_val, pedimento_number)


def is_clarion_layout(row_norm: Dict[str, Any]) -> bool:
    """True si la fila tiene las 3 columnas AÑO, PATENTE, NUMERO con valor, o PEDIMENTO con valor (compatibilidad)."""
    año = (row_norm.get("AÑO") or "").strip()
    patente = (row_norm.get("PATENTE") or "").strip()
    numero = (row_norm.get("NUMERO") or "").strip()
    if año and patente and numero:
        return True
    ped = (row_norm.get("PEDIMENTO") or "").strip()
    return bool(ped)
