from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session, joinedload
from typing import List
from app.database import get_db
from app.models.position_slot import PositionSlot
from app.models.area import Area
from app.models.position_type import PositionType
from app.schemas.position_slot import PositionSlotCreate, PositionSlotUpdate, PositionSlotResponse

router = APIRouter(prefix="/api/position-slots", tags=["Position Slots"])


def _load_slot(db: Session, slot_id: int) -> PositionSlot:
    return (
        db.query(PositionSlot)
        .options(joinedload(PositionSlot.area), joinedload(PositionSlot.position_types))
        .filter(PositionSlot.id == slot_id)
        .first()
    )


def _set_types(db: Session, slot: PositionSlot, codes: List[str]):
    types = db.query(PositionType).filter(PositionType.code.in_(codes)).all()
    if len(types) != len(codes):
        raise HTTPException(status_code=404, detail="Satu atau lebih tipe posisi tidak ditemukan")
    slot.position_types = types


@router.get("/", response_model=List[PositionSlotResponse])
def get_all(db: Session = Depends(get_db)):
    return (
        db.query(PositionSlot)
        .options(joinedload(PositionSlot.area), joinedload(PositionSlot.position_types))
        .filter(PositionSlot.is_active == True)
        .order_by(PositionSlot.area_id, PositionSlot.sort_order, PositionSlot.nomor)
        .all()
    )


@router.post("/", response_model=PositionSlotResponse)
def create(data: PositionSlotCreate, db: Session = Depends(get_db)):
    if not db.query(Area).filter(Area.id == data.area_id, Area.is_active == True).first():
        raise HTTPException(status_code=404, detail="Area tidak ditemukan")
    payload = data.model_dump(exclude={"position_type_codes"})
    slot = PositionSlot(**payload)
    db.add(slot)
    db.flush()
    _set_types(db, slot, data.position_type_codes)
    try:
        db.commit()
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal menyimpan posisi baru")
    return _load_slot(db, slot.id)


@router.put("/{slot_id}", response_model=PositionSlotResponse)
def update(slot_id: int, data: PositionSlotUpdate, db: Session = Depends(get_db)):
    slot = db.query(PositionSlot).filter(PositionSlot.id == slot_id).first()
    if not slot:
        raise HTTPException(status_code=404, detail="Posisi tidak ditemukan")
    payload = data.model_dump(exclude_unset=True, exclude={"position_type_codes"})
    for key, value in payload.items():
        setattr(slot, key, value)
    if data.position_type_codes is not None:
        _set_types(db, slot, data.position_type_codes)
    try:
        db.commit()
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal memperbarui data posisi")
    return _load_slot(db, slot_id)


@router.delete("/{slot_id}")
def delete(slot_id: int, db: Session = Depends(get_db)):
    slot = db.query(PositionSlot).filter(PositionSlot.id == slot_id).first()
    if not slot:
        raise HTTPException(status_code=404, detail="Posisi tidak ditemukan")
    db.delete(slot)
    try:
        db.commit()
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal menghapus posisi")
    return {"message": "Posisi dihapus"}
