"""Roles API endpoints for RBAC."""

from __future__ import annotations

from typing import TYPE_CHECKING
from uuid import UUID

from vikdata.models.role import (
    RoleCreate,
    RoleListResponse,
    RolePermissionRequest,
    RoleResponse,
    RoleUpdate,
)

if TYPE_CHECKING:
    from vikdata.client import VikdataClient


class RolesAPI:
    """Roles API endpoints.

    Handles role CRUD operations and permission assignment.
    """

    def __init__(self, client: "VikdataClient") -> None:
        """Initialize roles API.

        Args:
            client: VikdataClient instance
        """
        self._client = client

    async def list(self, include_system: bool = True) -> RoleListResponse:
        """List all roles accessible by the current user.

        Args:
            include_system: Whether to include system roles (default: True)

        Returns:
            RoleListResponse with list of roles

        Raises:
            AuthenticationError: Not authenticated
            AuthorizationError: Missing 'roles:read' permission
        """
        params = {"include_system": include_system}
        return await self._client.request(
            "GET",
            "/api/v1/roles",
            params=params,
            response_model=RoleListResponse,
        )

    async def create(
        self,
        name: str,
        slug: str,
        description: str | None = None,
        permission_ids: list[UUID] | None = None,
    ) -> RoleResponse:
        """Create a new role.

        Args:
            name: Role display name
            slug: Role slug/identifier
            description: Optional role description
            permission_ids: Optional list of permission IDs to assign

        Returns:
            RoleResponse with created role

        Raises:
            AuthenticationError: Not authenticated
            AuthorizationError: Missing 'roles:write' permission
            ValidationError: Invalid input data
        """
        request = RoleCreate(
            name=name,
            slug=slug,
            description=description,
            permission_ids=permission_ids or [],
        )
        return await self._client.request(
            "POST",
            "/api/v1/roles",
            json=request,
            response_model=RoleResponse,
        )

    async def get(self, role_id: UUID) -> RoleResponse:
        """Get a specific role by ID.

        Args:
            role_id: Role ID

        Returns:
            RoleResponse with role details

        Raises:
            AuthenticationError: Not authenticated
            AuthorizationError: Missing 'roles:read' permission
            ResourceNotFoundError: Role not found
        """
        return await self._client.request(
            "GET",
            f"/api/v1/roles/{role_id}",
            response_model=RoleResponse,
        )

    async def update(
        self,
        role_id: UUID,
        name: str | None = None,
        description: str | None = None,
    ) -> RoleResponse:
        """Update a role.

        Args:
            role_id: Role ID
            name: Optional new role name
            description: Optional new description

        Returns:
            RoleResponse with updated role

        Raises:
            AuthenticationError: Not authenticated
            AuthorizationError: Missing 'roles:write' permission or trying to modify system role
            ResourceNotFoundError: Role not found
        """
        request = RoleUpdate(name=name, description=description)
        return await self._client.request(
            "PUT",
            f"/api/v1/roles/{role_id}",
            json=request,
            response_model=RoleResponse,
        )

    async def delete(self, role_id: UUID) -> None:
        """Delete a role.

        Args:
            role_id: Role ID

        Raises:
            AuthenticationError: Not authenticated
            AuthorizationError: Missing 'roles:delete' permission or trying to delete system role
            ResourceNotFoundError: Role not found
        """
        await self._client.request(
            "DELETE",
            f"/api/v1/roles/{role_id}",
        )

    async def assign_permissions(
        self,
        role_id: UUID,
        permission_ids: list[UUID],
    ) -> RoleResponse:
        """Assign permissions to a role.

        Args:
            role_id: Role ID
            permission_ids: List of permission IDs to assign

        Returns:
            RoleResponse with updated role

        Raises:
            AuthenticationError: Not authenticated
            AuthorizationError: Missing 'roles:write' permission or trying to modify system role
            ResourceNotFoundError: Role or permission not found
        """
        request = RolePermissionRequest(permission_ids=permission_ids)
        return await self._client.request(
            "POST",
            f"/api/v1/roles/{role_id}/permissions",
            json=request,
            response_model=RoleResponse,
        )

    async def remove_permission(
        self,
        role_id: UUID,
        permission_id: UUID,
    ) -> RoleResponse:
        """Remove a permission from a role.

        Args:
            role_id: Role ID
            permission_id: Permission ID to remove

        Returns:
            RoleResponse with updated role

        Raises:
            AuthenticationError: Not authenticated
            AuthorizationError: Missing 'roles:write' permission or trying to modify system role
            ResourceNotFoundError: Role or permission not found
        """
        return await self._client.request(
            "DELETE",
            f"/api/v1/roles/{role_id}/permissions/{permission_id}",
            response_model=RoleResponse,
        )
