"""Admin-only user management: GET/POST/PATCH/DELETE /api/admin/users."""

from __future__ import annotations

from fastapi import APIRouter, Depends, HTTPException, status

from cyclone.auth import users
from cyclone.auth.deps import get_current_user
from cyclone.auth.permissions import Role
from cyclone.db import SessionLocal, User

router = APIRouter(prefix="/api/admin/users", tags=["admin"])


def _require_admin(user: dict = Depends(get_current_user)) -> dict:
    if user.get("role") != Role.ADMIN.value:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="forbidden",
        )
    return user


def _validate_role(role: str) -> None:
    valid = {Role.ADMIN.value, Role.USER.value, Role.VIEWER.value}
    if role not in valid:
        raise HTTPException(
            status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
            detail=f"role must be one of {sorted(valid)}",
        )


@router.get("")
def list_users(_admin=Depends(_require_admin)):
    with SessionLocal()() as db:
        all_users = db.query(User).all()
    return [users.to_public(u) for u in all_users]


@router.post("", status_code=status.HTTP_201_CREATED)
def create_user(body: dict, _admin=Depends(_require_admin)):
    username = (body.get("username") or "").strip()
    password = body.get("password") or ""
    role = body.get("role") or ""
    if not username or len(username) < 3:
        raise HTTPException(status_code=422, detail="username must be at least 3 chars")
    if len(password) < 12:
        raise HTTPException(status_code=422, detail="password must be at least 12 chars")
    _validate_role(role)
    with SessionLocal()() as db:
        if users.get_by_username(db, username) is not None:
            raise HTTPException(status_code=409, detail="username already exists")
        u = users.create(db, username=username, password=password, role=role)
        return users.to_public(u)


@router.patch("/{user_id}")
def patch_user(user_id: int, body: dict, admin=Depends(_require_admin)):
    me = admin
    if me.get("id") == user_id and body.get("role") and body["role"] != Role.ADMIN.value:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail="cannot_demote_self",
        )

    with SessionLocal()() as db:
        if body.get("role") is not None:
            _validate_role(body["role"])
            users.update_role(db, user_id, body["role"])
        if body.get("password") is not None:
            if len(body["password"]) < 12:
                raise HTTPException(status_code=422, detail="password must be at least 12 chars")
            users.update_password(db, user_id, body["password"])
        if body.get("disabled") is True:
            users.disable(db, user_id)
        u = users.get(db, user_id)
        if u is None:
            raise HTTPException(status_code=404, detail="user not found")
        return users.to_public(u)


@router.delete("/{user_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_user(user_id: int, admin=Depends(_require_admin)):
    me = admin
    if me.get("id") == user_id:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail="cannot_delete_self",
        )
    with SessionLocal()() as db:
        u = users.get(db, user_id)
        if u is None:
            raise HTTPException(status_code=404, detail="user not found")
        users.disable(db, user_id)
    return None
