"""Users router — endpoints for user management and SPBU role assignments."""

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.database import get_db
from app.dependencies import get_current_user
from app.models.user import User
from app.schemas.user import UserCreate, UserResponse, UserUpdate, UserSpbuAssignmentCreate, UserSpbuAssignmentResponse
from app.services import user_service


def _service_error(e: ValueError | PermissionError) -> HTTPException:
    """Convert service-layer ValueError → 404 and PermissionError → 403."""
    if isinstance(e, PermissionError):
        return HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=str(e))
    return HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))


router = APIRouter()


@router.get("", response_model=dict)
async def list_users(
    skip: int = 0,
    limit: int = 50,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Return a paginated list of all users."""
    users, total = await user_service.list_users(db, current_user, skip, limit)
    return {
        "data": [UserResponse.model_validate(u) for u in users],
        "meta": {"total": total, "page": skip // limit + 1, "per_page": limit},
    }


@router.post("", response_model=dict, status_code=status.HTTP_201_CREATED)
async def create_user(
    data: UserCreate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Create a new user account."""
    try:
        user = await user_service.create_user(db, data, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": UserResponse.model_validate(user), "message": "User berhasil dibuat"}


@router.get("/{user_id}", response_model=dict)
async def get_user(
    user_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Return details for a single user."""
    try:
        user = await user_service.get_user(db, user_id)
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
    return {"data": UserResponse.model_validate(user)}


@router.patch("/{user_id}", response_model=dict)
async def update_user(
    user_id: int,
    data: UserUpdate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Update scalar fields on a user account."""
    try:
        user = await user_service.update_user(db, user_id, data, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": UserResponse.model_validate(user), "message": "User berhasil diupdate"}


@router.delete("/{user_id}", response_model=dict)
async def deactivate_user(
    user_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Deactivate a user account (soft delete)."""
    try:
        user = await user_service.deactivate_user(db, user_id, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": UserResponse.model_validate(user), "message": "User berhasil dinonaktifkan"}


@router.delete("/{user_id}/delete", status_code=status.HTTP_204_NO_CONTENT)
async def delete_user(
    user_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> None:
    """Permanently delete a user in dev mode, soft-delete in production."""
    try:
        await user_service.delete_user(db, user_id, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)


@router.get("/{user_id}/assignments", response_model=dict)
async def get_assignments(
    user_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Return all SPBU role assignments for a given user."""
    try:
        assignments = await user_service.get_assignments(db, user_id)
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
    return {"data": [UserSpbuAssignmentResponse.model_validate(a) for a in assignments]}


@router.post("/{user_id}/assignments", response_model=dict, status_code=status.HTTP_201_CREATED)
async def assign_user(
    user_id: int,
    data: UserSpbuAssignmentCreate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Assign a user to an SPBU with a specific role (upserts if assignment already exists)."""
    try:
        assignment = await user_service.assign_to_spbu(db, user_id, data.spbu_id, data.role_id, current_user)
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
    return {"data": UserSpbuAssignmentResponse.model_validate(assignment), "message": "Assignment berhasil dibuat"}


@router.delete("/{user_id}/assignments/{spbu_id}", status_code=status.HTTP_204_NO_CONTENT)
async def remove_assignment(
    user_id: int,
    spbu_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> None:
    """Remove a user's role assignment from an SPBU."""
    try:
        await user_service.remove_assignment(db, user_id, spbu_id, current_user)
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
