"""
Helpers reutilizables para validación de filas CSV (partes).
Cada función devuelve Optional[Dict] con keys line, col, msg.
Referencia: a76/invoices (common_validators, validators/common).
"""
from decimal import Decimal, InvalidOperation
from typing import Dict, Any, Optional


def check_required(
    row: Dict[str, Any], col: str, line_num: int
) -> Optional[Dict[str, Any]]:
    """Devuelve error si el campo está vacío."""
    val = (row.get(col) or "").strip()
    if not val:
        return {"line": line_num, "col": col, "msg": "Requerido"}
    return None


def check_max_length(
    row: Dict[str, Any],
    col: str,
    max_len: int,
    line_num: int,
    required: bool = False,
) -> Optional[Dict[str, Any]]:
    """Devuelve error si el campo excede max_len. Si required=True, también exige que haya valor."""
    val = (row.get(col) or "").strip()
    if not val:
        if required:
            return {"line": line_num, "col": col, "msg": "Requerido"}
        return None
    if len(val) > max_len:
        return {"line": line_num, "col": col, "msg": f"Máximo {max_len} caracteres"}
    return None


def check_decimal(
    row: Dict[str, Any], col: str, line_num: int
) -> Optional[Dict[str, Any]]:
    """Devuelve error si el valor no es un número decimal válido (solo cuando hay valor)."""
    val = row.get(col)
    if val is None or val == "":
        return None
    try:
        Decimal(str(val))
    except (InvalidOperation, ValueError, TypeError):
        return {"line": line_num, "col": col, "msg": "Debe ser número"}
    return None
