"""
QUIERE_DESCARGAR
Collects every export line item that has discharge = True and builds the
"QueADescargar" list used by the balance-verification steps that follow
(LLENA_QUEUE_SALDOS_DISPONIBLES_FACTURA, COMPARA_SALDOS_POR_FACTURA,
VERIFICAQCONSOLIDADO).

For each discharge line the routine also triggers two series sub-validations:
  · REVISA_SERIES_EXISTA      → verifies the series to be discharged exist
  · REVISA_SERIES_OTRAS_PAR   → verifies the series are not already discharged
    on another line (REVISA_SERIES_DESC was commented-out in the legacy)

Legacy equivalent
-----------------
SELECT EqiPex.TipoMovImpo, EqiPex.LineaExpo, EqiPex.NumParte,
       EqiPex.Clase, EqiPex.CantExpo, EqiPex.UnidadMedida,
       EqiPex.FacturaImpo, EqiPex.LineaImpo
FROM   QEqeMaq EqiPex
WHERE  Consecutivo = <invoice.id>
  AND  EqiPex.Descarga = 1
"""

from decimal import Decimal
from typing import List, Set, Tuple

from sqlalchemy.orm import Session

from api.v1.modules.a76.invoices.models import InvoiceHeader
from api.v1.modules.a76.items.models import LineItem
from core.exceptions import ErrorCollector
from .discharge_types import AvailableLot, DownloadEntry  # re-exported for callers
from .series.review_series_exist import review_series_exist
from .series.review_series_other_lines import review_series_other_lines


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

def collect_lines_to_discharge(
    db: Session,
    invoice: InvoiceHeader,
    lines: List[LineItem],
    errors: ErrorCollector,
) -> List[DownloadEntry]:
    """
    QUIERE_DESCARGAR
    Builds and returns the list of ``DownloadEntry`` records for every line
    that has ``discharge = True``.  If no lines have discharge enabled the
    list is empty and the subsequent balance steps are skipped.

    For each collected line the function also runs:
      · _revisa_series_exista
      · _revisa_series_otras_par

    Parameters
    ----------
    db      : active SQLAlchemy session
    invoice : the export invoice being processed
    lines   : all line items of the invoice (already loaded by pre_validators)
    errors  : shared error collector

    Returns
    -------
    List[DownloadEntry] — the "QueADescargar" equivalent
    """
    to_discharge: List[DownloadEntry] = []

    discharge_lines = [line for line in lines if line.fa_data and line.fa_data.discharge]

    if not discharge_lines:
        return to_discharge

    # Shared across all lines — accumulates series keys to detect duplicates
    # between lines (equivalent to QueueSeries in the Clarion)
    seen_series: Set[Tuple] = set()

    for line in discharge_lines:
        origin_procedure = (
            line.customs.origin_procedure
            if line.customs and line.customs.origin_procedure
            else ""
        )
        part_number = ""
        if line.part_info:
            part_number = line.part_info.part_number or ""

        class_code = ""
        if line.class_info:
            class_code = line.class_info.class_code or ""

        quantity = (
            line.quantity.quantity or Decimal(0)
            if line.quantity
            else Decimal(0)
        )

        uom_code = ""
        if line.unit_of_measure_info:
            uom_code = line.unit_of_measure_info.code or ""

        import_invoice_number = ""
        import_line_number = 0
        if line.fa_data:
            import_invoice_number = line.fa_data.search_invoice or ""
            import_line_number = line.fa_data.search_line or 0

        entry = DownloadEntry(
            origin_procedure=origin_procedure,
            export_line=line.line_number,
            part_number=part_number,
            class_code=class_code,
            quantity=quantity,
            quantity_used=Decimal(0),
            unit_of_measure=uom_code,
            import_invoice=import_invoice_number,
            import_line=import_line_number,
            line_item_id=line.id,
        )
        to_discharge.append(entry)

        review_series_exist(db, invoice, line, entry, errors)
        review_series_other_lines(db, invoice, line, entry, seen_series, errors)

    return to_discharge
