from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from sqlalchemy.exc import IntegrityError
from app.db.session import SessionLocal
from app.schemas.order import (
    OrderCreate,
    OrderOut,
    OrderUpdate,
    OrderItemCreate,
    OrderItemOut,
)
from app.crud.orders import (
    create_order,
    get_order,
    get_orders,
    update_order,
    delete_order,
    create_order_item,
    get_items_for_order,
    get_order_item,
    update_order_item,
    delete_order_item,
    release_reservations_for_item,
    release_reservations_for_order,
    finalize_reservations_for_order,
)
from app.crud.orders import get_orders_by_cedula

from app.crud.orders import get_order as crud_get_order

router = APIRouter()

# Dependency
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@router.post("/", response_model=OrderOut)
def create_order_endpoint(payload: OrderCreate, db: Session = Depends(get_db)):
    try:
        return create_order(db, order_data=payload.model_dump())
    except IntegrityError as e:
        # likely duplicate order_number or FK constraint
        db.rollback()
        raise HTTPException(status_code=409, detail="No se pudo crear el pedido: número duplicado o datos inválidos.")


@router.get("/search/{order_number}", response_model=OrderOut)
def search_order_by_number(order_number: str, db: Session = Depends(get_db)):
    from app.models.order import Order
    found = db.query(Order).filter(Order.order_number == order_number).first()
    if not found:
        raise HTTPException(status_code=404, detail="Pedido no encontrado")
    return found


@router.get('/generate_number')
def generate_order_number():
    import time
    num = f"ORD{int(time.time() * 1000)}"
    return {"order_number": num}


@router.get("/search/cedula/{cedula}", response_model=list[OrderOut])
def search_orders_by_cedula(cedula: str, skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
    orders = get_orders_by_cedula(db, cedula=cedula, skip=skip, limit=limit)
    if not orders:
        raise HTTPException(status_code=404, detail="No se encontraron pedidos para la cédula proporcionada")
    return orders

@router.get("/", response_model=list[OrderOut])
def list_orders(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
    return get_orders(db, skip=skip, limit=limit)

@router.get("/{order_id}", response_model=OrderOut)
def get_order_endpoint(order_id: int, db: Session = Depends(get_db)):
    o = get_order(db, order_id)
    if not o:
        raise HTTPException(status_code=404, detail="Order not found")
    return o

@router.put("/{order_id}", response_model=OrderOut)
def update_order_endpoint(order_id: int, updates: OrderUpdate, db: Session = Depends(get_db)):
    o = get_order(db, order_id)
    if not o:
        raise HTTPException(status_code=404, detail="Order not found")
    try:
        return update_order(db, o, updates.model_dump(exclude_unset=True))
    except IntegrityError:
        db.rollback()
        raise HTTPException(status_code=409, detail="No se pudo actualizar el pedido: número duplicado o datos inválidos.")

@router.delete("/{order_id}")
def delete_order_endpoint(order_id: int, db: Session = Depends(get_db)):
    o = get_order(db, order_id)
    if not o:
        raise HTTPException(status_code=404, detail="Order not found")
    delete_order(db, o)
    return {"ok": True}

# Order items
@router.post("/{order_id}/items", response_model=OrderItemOut)
def create_order_item_endpoint(order_id: int, payload: OrderItemCreate, db: Session = Depends(get_db)):
    data = payload.model_dump()
    data['order_id'] = order_id
    return create_order_item(db, item_data=data)

@router.get("/{order_id}/items", response_model=list[OrderItemOut])
def list_order_items(order_id: int, db: Session = Depends(get_db)):
    return get_items_for_order(db, order_id)

@router.get("/items/{item_id}", response_model=OrderItemOut)
def get_order_item_endpoint(item_id: int, db: Session = Depends(get_db)):
    it = get_order_item(db, item_id)
    if not it:
        raise HTTPException(status_code=404, detail="Order item not found")
    return it

@router.put("/items/{item_id}", response_model=OrderItemOut)
def update_order_item_endpoint(item_id: int, updates: OrderItemCreate, db: Session = Depends(get_db)):
    it = get_order_item(db, item_id)
    if not it:
        raise HTTPException(status_code=404, detail="Order item not found")
    return update_order_item(db, it, updates.model_dump(exclude_unset=True))

@router.delete("/items/{item_id}")
def delete_order_item_endpoint(item_id: int, db: Session = Depends(get_db)):
    it = get_order_item(db, item_id)
    if not it:
        raise HTTPException(status_code=404, detail="Order item not found")
    delete_order_item(db, it)
    return {"ok": True}


@router.post('/items/{item_id}/release')
def release_order_item_reservations(item_id: int, db: Session = Depends(get_db)):
    try:
        released = release_reservations_for_item(db, item_id)
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))
    return {"released": released}

@router.post('/{order_id}/release')
def release_order_reservations(order_id: int, db: Session = Depends(get_db)):
    try:
        released = release_reservations_for_order(db, order_id)
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))
    return {"released": released}

@router.post('/{order_id}/finalize')
def finalize_order_reservations(order_id: int, db: Session = Depends(get_db)):
    try:
        finalized = finalize_reservations_for_order(db, order_id)
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))
    return {"finalized": finalized}
