from sqlalchemy.orm import Session
from api.v1.modules.a76.invoices.models import InvoiceFinancials, InvoiceHeader
from core.exceptions import ErrorCollector

from ...models import LineItem
from api.v1.modules.a76.classes.models import Class


def apply_calculations(
    db: Session, line: LineItem, tenant_id: int, company_id: int, line_number: int
):
    #TODO: SSisGen Logic 
    # if ssisgen.calcularcostounitarioenbaseavalortotalscaf = 1:
    #   unit_cost_capture = line.financial.total_value / line.financial.total_value <-- habria que revisar por que esta asi, por que para mi no tiene sentido, pero es lo que esta en clarion
    calculate_values(db, line, tenant_id, company_id)
    apply_calculations_after_values(db, line, tenant_id, company_id, line_number)


def apply_calculations_after_values(
    db: Session, line: LineItem, tenant_id: int, company_id: int, line_number: int
):
    """
    Aplica solo depreciation_date, descripción desde part/class y subitem_number.
    Usado por el flujo CSV para no sobrescribir los valores ya calculados por currency_type.
    """
    fa_data = getattr(line, "fa_data", None)
    if fa_data is not None and not getattr(fa_data, "is_subitem", True):
        fa_data.subitem_number = 0

    invoice_date = db.query(InvoiceHeader.invoice_date).filter(
        InvoiceHeader.id == line.invoice_id,
        InvoiceHeader.tenant_id == tenant_id,
        InvoiceHeader.company_id == company_id,
    ).scalar()
    if invoice_date is not None:
        line.depreciation_date = invoice_date

    if not getattr(line.description, "description_spanish", None) and not getattr(
        line.description, "description_english", None
    ):
        part_info = getattr(line, "part_info", None)
        if part_info and getattr(part_info, "description_spanish", None) and getattr(part_info, "description_english", None):
            line.description.description_spanish = part_info.description_spanish
            line.description.description_english = part_info.description_english
        else:
            if not getattr(line.description, "description_spanish", None):
                class_desc = (
                    db.query(Class.description_es, Class.description_en)
                    .filter(
                        Class.id == line.class_id,
                        Class.tenant_id == tenant_id,
                        Class.company_id == company_id,
                    )
                    .first()
                )
                if class_desc:
                    line.description.description_spanish, line.description.description_english = class_desc


def calculate_values(
    db: Session, line: LineItem, tenant_id: int, company_id: int
):
    """
    Una sola fuente de verdad: usa currency_type (USD/ME, MXN/MN) cuando está presente,
    para paridad con create.py y cargas CSV. Si no hay currency_type, usa currency (foreign/local/manual).
    """
    result = (
        db.query(
            InvoiceFinancials.currency,
            InvoiceFinancials.currency_type,
            InvoiceFinancials.exchange_rate,
        )
        .filter(
            InvoiceFinancials.invoice_id == line.invoice_id,
            InvoiceFinancials.tenant_id == tenant_id,
            InvoiceFinancials.company_id == company_id,
        )
        .first()
    )
    if not result:
        return

    currency, currency_type, exchange_rate = result
    # Prioridad: currency_type para alinear con create.py y CSV
    if currency_type in ("USD", "ME"):
        currency = "foreign"
    elif currency_type in ("MXN", "MN"):
        currency = "local"
    # si currency_type es otro o None, se usa currency tal cual

    if currency == "foreign":
        line.financial.unit_cost_usd = line.financial.unit_cost_capture
        line.financial.value_usd = line.financial.unit_cost_usd * line.quantity.quantity
        line.financial.unit_cost_mxn = line.financial.unit_cost_capture * (exchange_rate or 1)
        line.financial.value_mxn = line.financial.unit_cost_mxn * line.quantity.quantity
        line.financial.value_mc = line.financial.unit_cost_usd * line.quantity.quantity
    elif currency == "local":
        line.financial.unit_cost_mxn = line.financial.unit_cost_capture
        line.financial.value_mxn = line.financial.unit_cost_mxn * line.quantity.quantity
        line.financial.unit_cost_usd = line.financial.unit_cost_capture / (exchange_rate or 1)
        line.financial.value_usd = line.financial.unit_cost_usd * line.quantity.quantity
        line.financial.value_mc = line.financial.unit_cost_usd * line.quantity.quantity
    elif currency == "manual":
        line.financial.unit_cost_usd = line.financial.unit_cost_capture / (exchange_rate or 1)
        line.financial.value_usd = line.financial.unit_cost_usd * line.quantity.quantity
        line.financial.unit_cost_mxn = line.financial.unit_cost_usd * (exchange_rate or 1)
        line.financial.value_mxn = line.financial.unit_cost_mxn * line.quantity.quantity
        line.financial.value_mc = line.financial.unit_cost_capture * line.quantity.quantity