from uuid import UUID

from fastapi import Depends, FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy.orm import Session

from . import schemas, utils
from .database import SessionLocal, create_database

create_database()

app = FastAPI()

origins = ["http://127.0.0.1:8000", "http://localhost:3000", "http://localhost:3002"]


app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


# Dependency
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()


@app.post("/item/prepare", response_model=schemas.Item)
def add_item(item: schemas.ItemCreatePrepareShipping, db: Session = Depends(get_db)):
    return utils.prepare_item_shipping(db, item)


@app.get("/item/{item_uuid}", response_model=schemas.Item)
def get_item(item_uuid: str, db: Session = Depends(get_db)):
    item = utils.get_item_by_uuid(db, UUID(item_uuid))
    if not item:
        raise HTTPException(status_code=404, detail="Item not found")
    return utils.get_item_by_uuid(db, UUID(item_uuid))


@app.get("/tag/{tag}", response_model=schemas.Item)
def get_item_by_tag(tag: str, db: Session = Depends(get_db)):
    item = utils.get_item_by_tag(db, tag)
    if not item:
        raise HTTPException(status_code=404, detail="Item not found")
    return utils.get_item_by_tag(db, tag)


@app.get("/storages", response_model=list[schemas.Storage])
def list_storages(db: Session = Depends(get_db)):
    return utils.get_storages(db)


@app.post("/checkin", response_model=schemas.Item)
def checkin_item_by_uuid(checkin: schemas.ItemCheckin, db: Session = Depends(get_db)):
    item = utils.get_item_by_uuid(db, UUID(checkin.item_uuid))
    if item is None:
        raise HTTPException(status_code=404, detail="Item not found")
    storage = utils.get_storage(db, checkin.storage_name)
    if storage is None:
        raise HTTPException(status_code=404, detail="Storage not found")
    return utils.receive_item(db, item, storage)