from typing import List, Optional

from pydantic import ConfigDict, field_validator

from fides.api.oauth.roles import RoleRegistryEnum
from fides.api.schemas.base_class import FidesSchema
from fides.common.api.scope_registry import SCOPE_REGISTRY, ScopeRegistryEnum


class UserPermissionsCreate(FidesSchema):
    """Data required to create a FidesUserPermissions record

    Users will be assigned role(s) directly which are associated with a list of scopes. Scopes
    cannot be assigned directly to users.
    """

    roles: List[RoleRegistryEnum]
    model_config = ConfigDict(use_enum_values=True)


class UserPermissionsEdit(UserPermissionsCreate):
    """Data required to edit a FidesUserPermissions record."""

    id: Optional[str] = (
        None  # I don't think this should be in the request body, so making it optional.
    )


class UserPermissionsResponse(UserPermissionsCreate):
    """Response after creating, editing, or retrieving a FidesUserPermissions record."""

    id: str
    user_id: str
    total_scopes: List[
        ScopeRegistryEnum
    ]  # Returns a list of scopes inherited via roles
    model_config = ConfigDict(use_enum_values=True)

    @field_validator("total_scopes", mode="before")
    @classmethod
    def validate_obsolete_total_scopes(
        cls, total_scopes: List[ScopeRegistryEnum]
    ) -> List[ScopeRegistryEnum]:
        """Filter out obsolete total scopes if the scope registry has changed"""
        return [scope for scope in total_scopes or [] if scope in SCOPE_REGISTRY]
