"""
REVISA_CLASE
Validates that every line item of an export invoice has a valid class in the
catalog (QClaAct) and that the associated tariff fraction exists in either
the active fractions catalog (SFracciones) or the historical catalog
(GFraccionesHistorico).

Two-pass logic (ported from legacy SCAII):
  Pass A – no class errors:
    Iterate all lines and validate their fractions.
  Pass B – class errors detected:
    Report each missing class and also validate its fraction.
"""

from typing import List

from sqlalchemy import func, or_
from sqlalchemy.orm import Session

from api.v1.modules.a76.classes.models import Class
from api.v1.modules.a76.general_catalogs.fractions.historical_tariff_fractions.models import (
    HistoricalTariffFraction,
)
from api.v1.modules.a76.general_catalogs.fractions.tariff_fractions.models import TariffFraction
from api.v1.modules.a76.invoices.models import InvoiceHeader
from api.v1.modules.a76.items.models import LineItem
from core.exceptions import ErrorCollector


# ---------------------------------------------------------------------------
# Fraction helpers (shared with imports, same catalog sources)
# ---------------------------------------------------------------------------

def _fraction_exists_via_sitar(fraction_code: str) -> bool:
    """
    Returns True when the fraction exists in SITAR (active or anterior).
    Falls back to False when SITAR is not configured or unreachable.

    Format: first 8 chars = base fraction, chars 9-10 = NICO/country (optional).
    """
    if not fraction_code:
        return True

    base_frac = fraction_code[:8].strip()
    nico = fraction_code[8:10].strip() if len(fraction_code) > 8 else ""

    try:
        from api.v1.modules.sitar.fracciones.service import FraccionesService
        from api.v1.modules.sitar.fracciones_anteriores.service import (
            FraccionesAnterioresService,
        )

        results = FraccionesService.search_sync(
            fraccion=base_frac,
            nico=nico if nico else None,
            limit=1,
        )
        if results:
            return True

        hist_results = FraccionesAnterioresService.search_sync(
            fraccion_anterior=base_frac,
            limit=1,
        )
        return len(hist_results) > 0

    except Exception:
        return False


def _fraction_exists_in_local_db(db: Session, fraction_code: str) -> bool:
    """Fallback: validates against local TariffFraction and HistoricalTariffFraction tables."""
    if not fraction_code:
        return True

    base_frac = fraction_code[:8]
    nico = fraction_code[8:10] if len(fraction_code) > 8 else ""

    tariff_q = db.query(TariffFraction).filter(
        func.left(TariffFraction.code, 8) == base_frac
    )
    if nico:
        tariff_q = tariff_q.filter(TariffFraction.nico == nico)
    else:
        tariff_q = tariff_q.filter(
            or_(TariffFraction.nico.is_(None), TariffFraction.nico == "")
        )
    if tariff_q.first() is not None:
        return True

    hist_q = db.query(HistoricalTariffFraction).filter(
        HistoricalTariffFraction.historical_fraction == base_frac
    )
    if nico:
        hist_q = hist_q.filter(HistoricalTariffFraction.country == nico)
    else:
        hist_q = hist_q.filter(
            or_(
                HistoricalTariffFraction.country.is_(None),
                HistoricalTariffFraction.country == "",
            )
        )
    return hist_q.first() is not None


def _fraction_exists_in_catalog(db: Session, fraction_code: str) -> bool:
    """SITAR first, local DB as fallback."""
    if _fraction_exists_via_sitar(fraction_code):
        return True
    return _fraction_exists_in_local_db(db, fraction_code)


def _validate_line_fraction(
    db: Session,
    line: LineItem,
    errors: ErrorCollector,
) -> None:
    """Adds a FRACCION error when the line's export fraction is not in any catalog."""
    fraction = line.customs.fraction if line.customs else None
    if not fraction:
        return

    if _fraction_exists_in_catalog(db, fraction):
        return

    class_code = line.class_info.class_code if line.class_info else ""
    errors.add_error(
        field=f"line[{line.line_number}].fraction",
        message=(
            f"La Factura contiene la fraccion: {fraction} asociada al Clase {class_code} "
            "que no existe en el catálogo de fracciones"
        ),
        solution=["Agregar la fracción a fracciones históricas."],
        code="FRACCION",
    )


# ---------------------------------------------------------------------------
# Main entry point
# ---------------------------------------------------------------------------

def review_class(
    db: Session,    
    lines: List[LineItem],
    errors: ErrorCollector,
) -> None:
    """
    Validates class and fraction integrity for all line items of an export invoice.

    Logic ported from legacy REVISA_CLASE:

    1. Count line items whose class_id is not present in the active classes catalog.
    2a. No class errors (TotalReg = 0):
        Iterate every line and validate its tariff fraction.
    2b. Class errors found (TotalReg > 0):
        For each invalid line: report a CLASE error, then validate its fraction.
    """
    invalid_class_lines = [
        line for line in lines
        if line.class_id is None or db.get(Class, line.class_id) is None
    ]
    has_class_errors = bool(invalid_class_lines)

    if not has_class_errors:
        # Pass A: all classes exist — validate fractions for every line
        for line in lines:
            _validate_line_fraction(db, line, errors)
    else:
        # Pass B: report missing classes and validate their fractions
        for line in invalid_class_lines:
            class_code = line.class_info.class_code if line.class_info else ""
            errors.add_error(
                field=f"line[{line.line_number}].class",
                message=f"La clase: {class_code or '(vacía)'} no existe en catálogo de clases",
                solution=[
                    f"Borrar la partida: {line.line_number}, "
                    f"o dar de alta la clase: {class_code or '(vacía)'} en el catálogo de Clases"
                ],
                code="CLASE",
            )
            _validate_line_fraction(db, line, errors)
