"""
Punto de entrada de validación para import de una fila de parte.
Flujo Clarion: no ACT → siempre VALIDA_TODA_PARTES; ACT y parte existe → VALIDA_PARCIAL_PARTES;
ACT y parte no existe → VALIDA_TODA_PARTES (obligatorios + validaciones) y en commit se crea (ADD).
"""
from typing import Dict, Any, Optional, Set, List

from .common import (
    validate_row_required,
    validate_row_required_full,
    validaciones_parte,
    validate_row_warnings,
)


def validate_row_part(
    row: Dict[str, Any],
    line_num: int,
    valid_class_codes: Optional[Set[str]] = None,
    valid_uom_codes: Optional[Set[str]] = None,
    valid_currency_codes: Optional[Set[str]] = None,
    valid_fraction_mex_8: Optional[Set[str]] = None,
    valid_country_m3: Optional[Set[str]] = None,
    authorized_sector_keys: Optional[Set[str]] = None,
    company_has_prosec: bool = False,
    is_rfc_exception: bool = False,
    actualizar: bool = False,
    existing_part_numbers: Optional[Set[str]] = None,
) -> List[Dict[str, Any]]:
    """
    Valida una fila de CSV de partes para import.
    - No actualizar: siempre validación completa (obligatorios A,B,E + validaciones_parte).
    - Actualizar y número de parte ya existe: validación parcial (solo validaciones_parte).
    - Actualizar y número de parte no existe: validación completa; si pasa, en commit se crea (ADD).
    Si actualizar y validación full, además exige que el número de parte exista en catálogo.
    """
    errors: List[Dict[str, Any]] = []
    err = validate_row_required(row, line_num)
    if err:
        errors.append(err)

    part_number = (row.get("NUMPARTE") or "").strip().upper()
    use_partial = (
        actualizar
        and existing_part_numbers is not None
        and part_number in existing_part_numbers
    )

    if use_partial:
        errors.extend(
            validate_row_part_partial(
            row,
            line_num,
            valid_class_codes=valid_class_codes,
            valid_uom_codes=valid_uom_codes,
            valid_currency_codes=valid_currency_codes,
            valid_fraction_mex_8=valid_fraction_mex_8,
            valid_country_m3=valid_country_m3,
            authorized_sector_keys=authorized_sector_keys,
            company_has_prosec=company_has_prosec,
            is_rfc_exception=is_rfc_exception,
            )
        )
        return errors

    # Full validation (también cuando actualizar y parte no existe → ADD en commit)
    err = validate_row_required_full(row, line_num, is_rfc_exception=is_rfc_exception)
    if err:
        errors.append(err)
    # No exigir que exista en actualizar: si no existe se valida completa y en commit se crea (ADD)
    errors.extend(
        validaciones_parte(
        row,
        line_num,
        valid_class_codes=valid_class_codes,
        valid_uom_codes=valid_uom_codes,
        valid_currency_codes=valid_currency_codes,
        valid_fraction_mex_8=valid_fraction_mex_8,
        valid_country_m3=valid_country_m3,
        authorized_sector_keys=authorized_sector_keys,
        company_has_prosec=company_has_prosec,
        is_rfc_exception=is_rfc_exception,
        )
    )
    return errors


def validate_row_part_partial(
    row: Dict[str, Any],
    line_num: int,
    valid_class_codes: Optional[Set[str]] = None,
    valid_uom_codes: Optional[Set[str]] = None,
    valid_currency_codes: Optional[Set[str]] = None,
    valid_fraction_mex_8: Optional[Set[str]] = None,
    valid_country_m3: Optional[Set[str]] = None,
    authorized_sector_keys: Optional[Set[str]] = None,
    company_has_prosec: bool = False,
    is_rfc_exception: bool = False,
) -> List[Dict[str, Any]]:
    """
    Validación parcial (modo Actualizar, parte existente): solo NUMPARTE + validaciones_parte.
    Los campos vacíos se rellenan desde la parte existente en el mapper.
    """
    errors: List[Dict[str, Any]] = []
    err = validate_row_required(row, line_num)
    if err:
        errors.append(err)
    errors.extend(
        validaciones_parte(
        row,
        line_num,
        valid_class_codes=valid_class_codes,
        valid_uom_codes=valid_uom_codes,
        valid_currency_codes=valid_currency_codes,
        valid_fraction_mex_8=valid_fraction_mex_8,
        valid_country_m3=valid_country_m3,
        authorized_sector_keys=authorized_sector_keys,
        company_has_prosec=company_has_prosec,
        is_rfc_exception=is_rfc_exception,
        )
    )
    return errors


def get_row_warnings(row: Dict[str, Any], line_num: int) -> list:
    """Devuelve lista de advertencias para la fila (desfase, apóstrofes). No bloquean."""
    return validate_row_warnings(row, line_num)
