"""State -> District -> Center CRUD (create + list, including nested lists)."""
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import Session

from database import get_db
from model.state import State
from model.district import District
from model.center import Center
from schemas import (
    StateCreate, StateOut,
    DistrictCreate, DistrictOut,
    CenterCreate, CenterOut,
)

router = APIRouter(tags=["Hierarchy"])


# ============================================================
# States
# ============================================================
@router.post("/states", response_model=StateOut, status_code=status.HTTP_201_CREATED)
def create_state(payload: StateCreate, db: Session = Depends(get_db)):
    if db.query(State).filter(State.name == payload.name).first():
        raise HTTPException(status.HTTP_409_CONFLICT, "State already exists")
    state = State(name=payload.name)
    db.add(state)
    db.commit()
    db.refresh(state)
    return state


@router.get("/states", response_model=list[StateOut])
def list_states(db: Session = Depends(get_db)):
    return db.query(State).order_by(State.name).all()


# ============================================================
# Districts
# ============================================================
@router.post("/districts", response_model=DistrictOut, status_code=status.HTTP_201_CREATED)
def create_district(payload: DistrictCreate, db: Session = Depends(get_db)):
    if not db.get(State, payload.state_id):
        raise HTTPException(status.HTTP_404_NOT_FOUND, "State not found")
    district = District(name=payload.name, state_id=payload.state_id)
    db.add(district)
    try:
        db.commit()
    except IntegrityError:
        db.rollback()
        raise HTTPException(status.HTTP_409_CONFLICT, "District already exists in this state")
    db.refresh(district)
    return district


@router.get("/districts", response_model=list[DistrictOut])
def list_districts(db: Session = Depends(get_db)):
    return db.query(District).order_by(District.name).all()


@router.get("/states/{state_id}/districts", response_model=list[DistrictOut])
def list_districts_of_state(state_id: int, db: Session = Depends(get_db)):
    if not db.get(State, state_id):
        raise HTTPException(status.HTTP_404_NOT_FOUND, "State not found")
    return (
        db.query(District)
        .filter(District.state_id == state_id)
        .order_by(District.name)
        .all()
    )


# ============================================================
# Centers
# ============================================================
@router.post("/centers", response_model=CenterOut, status_code=status.HTTP_201_CREATED)
def create_center(payload: CenterCreate, db: Session = Depends(get_db)):
    if not db.get(District, payload.district_id):
        raise HTTPException(status.HTTP_404_NOT_FOUND, "District not found")
    center = Center(
        name=payload.name,
        district_id=payload.district_id,
        address=payload.address,
    )
    db.add(center)
    try:
        db.commit()
    except IntegrityError:
        db.rollback()
        raise HTTPException(status.HTTP_409_CONFLICT, "Center already exists in this district")
    db.refresh(center)
    return center


@router.get("/centers", response_model=list[CenterOut])
def list_centers(db: Session = Depends(get_db)):
    return db.query(Center).order_by(Center.name).all()


@router.get("/districts/{district_id}/centers", response_model=list[CenterOut])
def list_centers_of_district(district_id: int, db: Session = Depends(get_db)):
    if not db.get(District, district_id):
        raise HTTPException(status.HTTP_404_NOT_FOUND, "District not found")
    return (
        db.query(Center)
        .filter(Center.district_id == district_id)
        .order_by(Center.name)
        .all()
    )
