from decimal import Decimal

from sqlalchemy import func
from sqlalchemy.orm import Session

from api.v1.modules.a76.general_catalogs.exchange_rate.models import ExchangeRate
from api.v1.modules.a76.invoices.models import InvoiceHeader
from core.exceptions import ErrorCollector


def review_exchange_rate(
    db: Session,
    invoice: InvoiceHeader,
    cal_val_base_tc: int,
    errors: ErrorCollector,
) -> None:
    """
    Validates that the invoice's exchange rate matches the one registered in the
    catalog for the invoice date (gtipocambio / ExchangeRate table).

    Ported from legacy REVISA_TIPOCAMBIO routine.
    Only runs when the system is NOT configured to use the pedimento's exchange
    rate (SisGen:CalValBaseTCPed = 0).
    """
    if cal_val_base_tc == 1:
        # SKIP: TC is derived from pedimento payment date
        return
    if not invoice.invoice_date:
        return

    catalog_rate: ExchangeRate | None = (
        db.query(ExchangeRate)
        .filter(
            ExchangeRate.tenant_id == invoice.tenant_id,
            ExchangeRate.company_id == invoice.company_id,
            func.date(ExchangeRate.date) == invoice.invoice_date,
        )
        .first()
    )

    if catalog_rate is None:
        errors.add_error(
            field="exchange_rate",
            message="No existe tipo de cambio registrado para la fecha de la factura",
            solution=[
                "Capture el tipo de cambio correspondiente a la fecha de la factura "
                "en el catálogo de Tipo de Cambio"
            ],
            code="TIPO_DE_CAMBIO",
        )
        return

    invoice_tc = (
        Decimal(str(invoice.financials.exchange_rate))
        if invoice.financials and invoice.financials.exchange_rate is not None
        else None
    )
    catalog_tc = catalog_rate.value

    if invoice_tc is None or catalog_tc is None or invoice_tc != catalog_tc:
        errors.add_error(
            field="exchange_rate",
            message="No esta capturado correctamente el Tipo de Cambio",
            solution=[
                "Capture o modifique el tipo de cambio que corresponda a la factura "
                "en el catálogo de Tipo de Cambio"
            ],
            code="TIPO_DE_CAMBIO",
        )
