"""
RBAC administration endpoints — permission catalog and role/user permission management.
"""

from uuid import UUID

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

from app.core.auth_deps import get_current_active_user, require_permission, require_superadmin
from app.core.dependencies import get_db
from app.core.permissions import PermissionCode, resolve_user_permissions
from app.core.responses import SuccessResponse
from app.models.user import User
from app.schemas.rbac import (
    PermissionDefinitionResponse,
    PermissionSyncResponse,
    PermissionToggleRequest,
    RoleCreateRequest,
    RolePermissionsResponse,
    RolePermissionsUpdateRequest,
    RoleResponse,
    RoleUpdateRequest,
    UserPermissionDetailResponse,
    UserPermissionOverridesUpdateRequest,
)
from app.services.rbac_service import RbacService

router = APIRouter(prefix="/rbac", tags=["RBAC"])
_service = RbacService()


@router.get(
    "/permissions",
    response_model=SuccessResponse[list[PermissionDefinitionResponse]],
    status_code=status.HTTP_200_OK,
    summary="List permission definitions",
    dependencies=[Depends(require_permission(PermissionCode.USER_READ))],
)
async def list_permissions(
    db: AsyncSession = Depends(get_db),
) -> SuccessResponse[list[PermissionDefinitionResponse]]:
    data = await _service.list_permission_definitions(db)
    return SuccessResponse(data=data)


@router.post(
    "/sync",
    response_model=SuccessResponse[PermissionSyncResponse],
    status_code=status.HTTP_200_OK,
    summary="Synchronize system permissions & feature definitions",
    dependencies=[Depends(require_superadmin())],
)
async def sync_permissions(
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_superadmin()),
) -> SuccessResponse[PermissionSyncResponse]:
    result = await _service.sync_permissions(db, actor=current_user)
    return SuccessResponse(data=result, message=f"Successfully synced {result.synced} capabilities.")


@router.patch(
    "/permissions/{permission_id}/toggle",
    response_model=SuccessResponse[PermissionDefinitionResponse],
    status_code=status.HTTP_200_OK,
    summary="Toggle feature capability on/off",
    dependencies=[Depends(require_superadmin())],
)
async def toggle_permission(
    permission_id: UUID,
    payload: PermissionToggleRequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_superadmin()),
) -> SuccessResponse[PermissionDefinitionResponse]:
    result = await _service.toggle_permission(db, permission_id, payload.is_active, actor=current_user)
    action = "enabled" if payload.is_active else "disabled"
    return SuccessResponse(data=result, message=f"Feature capability {result.code} {action}.")


@router.get(
    "/roles",
    response_model=SuccessResponse[list[RoleResponse]],
    status_code=status.HTTP_200_OK,
    summary="List manageable roles",
    dependencies=[Depends(require_permission(PermissionCode.USER_READ))],
)
async def list_roles(
    db: AsyncSession = Depends(get_db),
) -> SuccessResponse[list[RoleResponse]]:
    data = await _service.list_roles(db)
    return SuccessResponse(data=data)


@router.post(
    "/roles",
    response_model=SuccessResponse[RoleResponse],
    status_code=status.HTTP_201_CREATED,
    summary="Create custom staff role",
    dependencies=[Depends(require_permission(PermissionCode.USER_WRITE))],
)
async def create_role(
    payload: RoleCreateRequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
) -> SuccessResponse[RoleResponse]:
    data = await _service.create_role(db, payload, actor=current_user)
    return SuccessResponse(
        data=data,
        message=f"Role '{data.name}' ({data.code}) created successfully.",
    )


@router.put(
    "/roles/{role_code}",
    response_model=SuccessResponse[RoleResponse],
    status_code=status.HTTP_200_OK,
    summary="Update staff role details",
    dependencies=[Depends(require_permission(PermissionCode.USER_WRITE))],
)
async def update_role(
    role_code: str,
    payload: RoleUpdateRequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
) -> SuccessResponse[RoleResponse]:
    data = await _service.update_role(db, role_code, payload, actor=current_user)
    return SuccessResponse(
        data=data,
        message=f"Role '{data.name}' updated successfully.",
    )


@router.delete(
    "/roles/{role_code}",
    response_model=SuccessResponse[None],
    status_code=status.HTTP_200_OK,
    summary="Delete custom staff role",
    dependencies=[Depends(require_permission(PermissionCode.USER_WRITE))],
)
async def delete_role(
    role_code: str,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
) -> SuccessResponse[None]:
    await _service.delete_role(db, role_code, actor=current_user)
    return SuccessResponse(data=None, message=f"Role '{role_code}' deleted successfully.")


@router.get(
    "/roles/{role}/permissions",
    response_model=SuccessResponse[RolePermissionsResponse],
    status_code=status.HTTP_200_OK,
    summary="Get role permission matrix",
    dependencies=[Depends(require_permission(PermissionCode.USER_READ))],
)
async def get_role_permissions(
    role: str,
    db: AsyncSession = Depends(get_db),
) -> SuccessResponse[RolePermissionsResponse]:
    data = await _service.get_role_permissions(db, role)
    return SuccessResponse(data=data)


@router.put(
    "/roles/{role}/permissions",
    response_model=SuccessResponse[RolePermissionsResponse],
    status_code=status.HTTP_200_OK,
    summary="Update role default permissions",
)
async def update_role_permissions(
    role: str,
    payload: RolePermissionsUpdateRequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_superadmin()),
) -> SuccessResponse[RolePermissionsResponse]:
    data = await _service.update_role_permissions(db, role, payload, actor=current_user)
    return SuccessResponse(data=data, message="Role permissions updated.")


@router.get(
    "/users/{user_id}/permissions",
    response_model=SuccessResponse[UserPermissionDetailResponse],
    status_code=status.HTTP_200_OK,
    summary="Get user effective permissions and overrides",
    dependencies=[Depends(require_permission(PermissionCode.USER_READ))],
)
async def get_user_permissions(
    user_id: UUID,
    db: AsyncSession = Depends(get_db),
) -> SuccessResponse[UserPermissionDetailResponse]:
    data = await _service.get_user_permission_detail(db, user_id)
    return SuccessResponse(data=data)


@router.put(
    "/users/{user_id}/permission-overrides",
    response_model=SuccessResponse[UserPermissionDetailResponse],
    status_code=status.HTTP_200_OK,
    summary="Set user permission overrides",
)
async def update_user_permission_overrides(
    user_id: UUID,
    payload: UserPermissionOverridesUpdateRequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_superadmin()),
) -> SuccessResponse[UserPermissionDetailResponse]:
    data = await _service.update_user_overrides(db, user_id, payload, actor=current_user)
    return SuccessResponse(data=data, message="User permission overrides saved.")


@router.get(
    "/me/permissions",
    response_model=SuccessResponse[list[str]],
    status_code=status.HTTP_200_OK,
    summary="Effective permissions for current user",
)
async def get_my_permissions(
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
) -> SuccessResponse[list[str]]:
    perms = sorted(await resolve_user_permissions(db, current_user))
    return SuccessResponse(data=perms)
