from sqlalchemy import create_engine, text
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import StaticPool
from app.db.base import Base
from app.crud.orders import create_order, create_order_item

from app.crud.inventory import create_inventory_item
from app.crud.products import create_product, create_variant

from app.models.product import ProductComponent


def setup_in_memory_db():
    engine = create_engine(
        "sqlite://",
        connect_args={"check_same_thread": False},
        poolclass=StaticPool,
        future=True,
    )
    TestingSessionLocal = sessionmaker(bind=engine)
    Base.metadata.create_all(bind=engine)
    return TestingSessionLocal


def test_reserve_inventory_on_order_item():
    DB = setup_in_memory_db()
    db = DB()

    # create inventory item
    inv = create_inventory_item(db, item_data={"name": "Papel A4", "sku": "PAP-A4", "type": "paper", "unit": "hoja", "quantity_on_hand": 100})

    # create product and variant
    product = create_product(db, product_data={"name": "Taza 11oz", "sku": "TAZA11"})
    variant = create_variant(db, variant_data={"product_id": product.id, "name": "Taza 11oz", "canvas_width_mm": 200, "canvas_height_mm": 90})

    # link component: variant uses 1 hoja per unit
    comp = ProductComponent(product_variant_id=variant.id, inventory_item_id=inv.id, qty_per_unit=1.0, unit="hoja")
    db.add(comp)
    db.commit()

    # create order
    order = create_order(db, order_data={"order_number": "ORD-TEST-1", "client_id": 1})

    # create order item (quantity 3) -> should reserve 3 hojas
    oi = create_order_item(db, item_data={"order_id": order.id, "product_variant_id": variant.id, "quantity": 3})

    # refresh inventory
    refreshed = db.query(type(inv)).filter_by(id=inv.id).one()
    assert refreshed.quantity_on_hand == 97

    # check reservation exists
    reservations = db.execute(text("select * from inventory_reservations where order_item_id = :oid"), {"oid": oi.id}).fetchall()
    assert len(reservations) == 1
