"""Unit tests for the backend-owned ordering pricing engine."""
from __future__ import annotations

from sqlalchemy import create_engine
from sqlalchemy.orm import Session, sessionmaker
from sqlalchemy.pool import StaticPool

from app.db.session import Base
from app.models.ordering import (
    CatalogueProduct,
    CustomerPriceAssignment,
    CustomerProductPrice,
    PriceList,
    PriceListItem,
    PriceTier,
)
from app.services.ordering_pricing import resolve_price

CUSTOMER_ID = 1
TENANT = "test-tenant"


def _session() -> Session:
    engine = create_engine(
        "sqlite:///:memory:",
        connect_args={"check_same_thread": False},
        poolclass=StaticPool,
    )
    Base.metadata.create_all(bind=engine)
    return sessionmaker(bind=engine, expire_on_commit=False)()


def _product(db: Session, **overrides) -> CatalogueProduct:
    values = {
        "tenant_id": TENANT,
        "name": "Maize 1T",
        "sku": "MAIZE-1T",
        "category": "grains",
        "base_price": 100.0,
        "min_order_quantity": 1.0,
        "requires_quote": False,
    }
    values.update(overrides)
    product = CatalogueProduct(**values)
    db.add(product)
    db.flush()
    return product


def test_base_price_with_no_rules():
    db = _session()
    product = _product(db)
    res = resolve_price(db, client_account_id=CUSTOMER_ID, product=product, quantity=2)
    assert res.unit_price == 100.0
    assert res.price_source == "base"
    assert res.requires_quote is False
    assert res.line_total(2) == 200.0


def test_customer_discount_applies_to_base():
    db = _session()
    product = _product(db)
    db.add(CustomerPriceAssignment(tenant_id=TENANT, client_account_id=CUSTOMER_ID, discount_percent=10.0))
    db.flush()
    res = resolve_price(db, client_account_id=CUSTOMER_ID, product=product, quantity=1)
    assert res.unit_price == 90.0
    assert res.price_source == "base"
    assert res.discount_percent == 10.0


def test_price_list_overrides_base():
    db = _session()
    product = _product(db)
    pl = PriceList(tenant_id=TENANT, code="WHL", name="Wholesale")
    db.add(pl)
    db.flush()
    db.add(PriceListItem(tenant_id=TENANT, price_list_id=pl.id, product_id=product.id, unit_price=80.0))
    db.add(CustomerPriceAssignment(tenant_id=TENANT, client_account_id=CUSTOMER_ID, price_list_id=pl.id, discount_percent=10.0))
    db.flush()
    res = resolve_price(db, client_account_id=CUSTOMER_ID, product=product, quantity=1)
    # Price list wins over base+discount.
    assert res.unit_price == 80.0
    assert res.price_source == "price_list"


def test_customer_fixed_price_wins_over_price_list():
    db = _session()
    product = _product(db)
    pl = PriceList(tenant_id=TENANT, code="WHL", name="Wholesale")
    db.add(pl)
    db.flush()
    db.add(PriceListItem(tenant_id=TENANT, price_list_id=pl.id, product_id=product.id, unit_price=80.0))
    db.add(CustomerPriceAssignment(tenant_id=TENANT, client_account_id=CUSTOMER_ID, price_list_id=pl.id))
    db.add(
        CustomerProductPrice(
            tenant_id=TENANT, client_account_id=CUSTOMER_ID, product_id=product.id, unit_price=72.5, rule_type="contract"
        )
    )
    db.flush()
    res = resolve_price(db, client_account_id=CUSTOMER_ID, product=product, quantity=1)
    assert res.unit_price == 72.5
    assert res.price_source == "contract"


def test_quantity_tier_wins_when_threshold_met():
    db = _session()
    product = _product(db)
    cpp = CustomerProductPrice(
        tenant_id=TENANT, client_account_id=CUSTOMER_ID, product_id=product.id, unit_price=90.0, rule_type="fixed"
    )
    db.add(cpp)
    db.flush()
    db.add(PriceTier(tenant_id=TENANT, customer_product_price_id=cpp.id, min_quantity=10, unit_price=85.0))
    db.add(PriceTier(tenant_id=TENANT, customer_product_price_id=cpp.id, min_quantity=50, unit_price=80.0))
    db.flush()

    # Below first tier → flat fixed price.
    assert resolve_price(db, client_account_id=CUSTOMER_ID, product=product, quantity=5).unit_price == 90.0
    # Meets first tier.
    mid = resolve_price(db, client_account_id=CUSTOMER_ID, product=product, quantity=10)
    assert mid.unit_price == 85.0
    assert mid.price_source == "tiered"
    # Meets highest tier.
    assert resolve_price(db, client_account_id=CUSTOMER_ID, product=product, quantity=60).unit_price == 80.0


def test_product_requires_quote():
    db = _session()
    product = _product(db, requires_quote=True)
    res = resolve_price(db, client_account_id=CUSTOMER_ID, product=product, quantity=1)
    assert res.requires_quote is True
    assert res.unit_price is None
    assert res.price_source == "quote"
    assert res.line_total(5) is None


def test_customer_quote_rule_forces_quote():
    db = _session()
    product = _product(db)
    db.add(
        CustomerProductPrice(
            tenant_id=TENANT, client_account_id=CUSTOMER_ID, product_id=product.id, unit_price=None, rule_type="quote"
        )
    )
    db.flush()
    res = resolve_price(db, client_account_id=CUSTOMER_ID, product=product, quantity=1)
    assert res.requires_quote is True
    assert res.price_source == "quote"


def test_no_price_falls_back_to_quote():
    db = _session()
    product = _product(db, base_price=None)
    res = resolve_price(db, client_account_id=CUSTOMER_ID, product=product, quantity=1)
    assert res.requires_quote is True
    assert res.price_source == "quote"
