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, release_reservations_for_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_release_reservations():
    DB = setup_in_memory_db()
    db = DB()

    inv = create_inventory_item(db, item_data={"name": "Papel A4", "sku": "PAP-A4", "type": "paper", "unit": "hoja", "quantity_on_hand": 10})
    product = create_product(db, product_data={"name": "Gorra", "sku": "GORRO"})
    variant = create_variant(db, variant_data={"product_id": product.id, "name": "Gorra Talla U"})

    comp = ProductComponent(product_variant_id=variant.id, inventory_item_id=inv.id, qty_per_unit=2.0, unit="hoja")
    db.add(comp)
    db.commit()

    order = create_order(db, order_data={"order_number": "ORD-REL-1", "client_id": 1})
    oi = create_order_item(db, item_data={"order_id": order.id, "product_variant_id": variant.id, "quantity": 2})

    # inventory should have decreased by 4
    refreshed = db.query(type(inv)).filter_by(id=inv.id).one()
    assert refreshed.quantity_on_hand == 6

    # release
    count = release_reservations_for_item(db, oi.id)
    assert count == 1

    refreshed2 = db.query(type(inv)).filter_by(id=inv.id).one()
    assert refreshed2.quantity_on_hand == 10

    # reservations should be marked released
    rows = db.execute(text("select released_at from inventory_reservations where order_item_id = :oid"), {"oid": oi.id}).fetchall()
    assert rows[0][0] is not None
