"""
Esquemas Pydantic para el módulo de permisos.
Define los modelos de request/response para las APIs de permisos.
"""

from typing import List, Optional
from datetime import datetime
from pydantic import BaseModel, Field, ConfigDict


# ============================================================================
# SCHEMAS DE RESPONSE
# ============================================================================


class PermissionResponse(BaseModel):
    """Esquema de respuesta para un permiso individual."""

    id: int
    code: str = Field(..., description="Código único del permiso (ej: 'invoice.view')")
    description: Optional[str] = Field(None, description="Descripción del permiso")
    module: str = Field(..., description="Módulo al que pertenece (ej: 'invoice')")
    action: str = Field(..., description="Acción específica (ej: 'view', 'edit')")
    is_active: bool = Field(..., description="Si el permiso está activo")

    model_config = ConfigDict(from_attributes=True)


class CompanyRoleResponse(BaseModel):
    """Esquema de respuesta para un rol de companye."""

    id: int
    company_id: int = Field(..., description="ID del companye al que pertenece el rol")
    name: str = Field(..., description="Nombre del rol (ej: 'Administrador')")
    code: str = Field(..., description="Código del rol (ej: 'admin')")
    description: Optional[str] = Field(None, description="Descripción del rol")
    is_active: bool = Field(..., description="Si el rol está activo")
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


class CompanyRoleWithPermissionsResponse(CompanyRoleResponse):
    """Esquema de respuesta para un rol con sus permisos incluidos."""

    permissions: List[PermissionResponse] = Field(
        default_factory=list, description="Lista de permisos asignados a este rol"
    )


class UserPermissionsResponse(BaseModel):
    """Esquema de respuesta para los permisos de un usuario."""

    user_id: str = Field(..., description="ID del usuario")
    company_id: int = Field(..., description="ID del companye")
    permissions: List[str] = Field(
        default_factory=list, description="Lista de códigos de permisos del usuario"
    )
    roles: List[str] = Field(
        default_factory=list, description="Lista de nombres de roles del usuario"
    )


class UserCompanyRoleResponse(BaseModel):
    """Esquema de respuesta para la asignación de rol a usuario."""

    id: int
    user_id: str
    company_id: int
    company_role_id: int
    is_active: bool
    created_at: datetime
    assigned_by: Optional[str] = None
    company_role: Optional[CompanyRoleResponse] = Field(None, description="Información del rol asignado")

    model_config = ConfigDict(from_attributes=True)


class UserCompanyPermissionResponse(BaseModel):
    """Esquema de respuesta para un permiso directo de usuario."""

    id: int
    user_id: str
    company_id: int
    permission_id: int
    permission_code: Optional[str] = None
    is_granted: bool = Field(
        ..., description="True si está concedido, False si está revocado"
    )
    is_active: bool
    created_at: datetime
    assigned_by: Optional[str] = None
    expires_at: Optional[datetime] = Field(
        None, description="Fecha de expiración del permiso"
    )

    model_config = ConfigDict(from_attributes=True)


# ============================================================================
# SCHEMAS DE REQUEST
# ============================================================================


class AssignRoleRequest(BaseModel):
    """Esquema de request para asignar un rol a un usuario."""

    user_id: str = Field(..., description="ID del usuario al que se asignará el rol")
    role_id: int = Field(..., description="ID del rol a asignar")


class RemoveRoleRequest(BaseModel):
    """Esquema de request para remover un rol de un usuario."""

    user_id: str = Field(..., description="ID del usuario")
    role_id: int = Field(..., description="ID del rol a remover")


class GrantPermissionRequest(BaseModel):
    """Esquema de request para conceder un permiso directo a un usuario."""

    user_id: str = Field(..., description="ID del usuario")
    permission_code: str = Field(
        ..., description="Código del permiso a conceder (ej: 'invoice.delete')"
    )
    expires_at: Optional[datetime] = Field(
        None, description="Fecha de expiración del permiso (opcional)"
    )


class RevokePermissionRequest(BaseModel):
    """Esquema de request para revocar un permiso directo."""

    user_id: str = Field(..., description="ID del usuario")
    permission_code: str = Field(..., description="Código del permiso a revocar")


class CreateRoleRequest(BaseModel):
    """Esquema de request para crear un rol personalizado."""

    name: str = Field(..., min_length=1, max_length=100, description="Nombre del rol")
    code: str = Field(
        ...,
        min_length=1,
        max_length=100,
        description="Código único del rol (ej: 'custom_admin')",
    )
    description: Optional[str] = Field(
        None, max_length=255, description="Descripción del rol"
    )
    permission_ids: List[int] = Field(
        default_factory=list, description="IDs de permisos a asignar al rol"
    )


class UpdateRoleRequest(BaseModel):
    """Esquema de request para actualizar un rol existente."""

    name: Optional[str] = Field(None, min_length=1, max_length=100)
    description: Optional[str] = Field(None, max_length=255)
    is_active: Optional[bool] = None


class AssignPermissionsToRoleRequest(BaseModel):
    """Esquema de request para asignar permisos a un rol."""

    permission_ids: List[int] = Field(
        ..., description="Lista de IDs de permisos a asignar al rol"
    )
    replace_existing: bool = Field(
        False,
        description="Si True, reemplaza los permisos existentes. Si False, los agrega.",
    )


class CreatePermissionRequest(BaseModel):
    """Esquema de request para crear un nuevo permiso (uso administrativo)."""

    code: str = Field(
        ...,
        min_length=1,
        max_length=100,
        description="Código único del permiso (ej: 'custom_module.action')",
    )
    description: Optional[str] = Field(None, max_length=255)
    module: str = Field(
        ..., min_length=1, max_length=50, description="Módulo del permiso"
    )
    action: str = Field(
        ..., min_length=1, max_length=50, description="Acción del permiso"
    )


# ============================================================================
# SCHEMAS DE RESPUESTA GENÉRICOS
# ============================================================================


class SuccessResponse(BaseModel):
    """Respuesta genérica de éxito."""

    success: bool = True
    message: str = Field(..., description="Mensaje descriptivo de la operación")
    data: Optional[dict] = Field(None, description="Datos adicionales opcionales")


class ErrorResponse(BaseModel):
    """Respuesta genérica de error."""

    success: bool = False
    detail: str = Field(..., description="Descripción del error")
    error_code: Optional[str] = Field(None, description="Código de error específico")


# ============================================================================
# SCHEMAS DE PAGINACIÓN
# ============================================================================


class PaginatedResponse(BaseModel):
    """Esquema genérico para respuestas paginadas."""

    items: List[dict] = Field(default_factory=list)
    total: int = Field(..., description="Total de items disponibles")
    page: int = Field(..., description="Página actual")
    page_size: int = Field(..., description="Tamaño de página")
    total_pages: int = Field(..., description="Total de páginas disponibles")


class PermissionListResponse(BaseModel):
    """Lista paginada de permisos."""

    items: List[PermissionResponse]
    total: int
    page: int = 1
    page_size: int = 100


class RoleListResponse(BaseModel):
    """Lista paginada de roles."""

    items: List[CompanyRoleResponse]
    total: int
    page: int = 1
    page_size: int = 100


class UserRoleListResponse(BaseModel):
    """Lista paginada de asignaciones de roles a usuarios."""

    items: List[UserCompanyRoleResponse]
    total: int
    page: int = 1
    page_size: int = 100


class AssignUserRoleRequest(BaseModel):
    """Esquema de request para asignar un rol a un usuario."""

    user_id: str = Field(..., description="ID del usuario")
    company_role_id: int = Field(..., description="ID del rol a asignar")


# ============================================================================
# SCHEMAS PARA PERMISOS INDIVIDUALES DE USUARIO
# ============================================================================


class UserPermissionResponse(BaseModel):
    """Esquema de respuesta para un permiso individual de usuario."""

    id: int
    user_id: str
    permission_id: int
    company_id: int
    tenant_id: int
    is_granted: bool = Field(..., description="True = permiso concedido, False = permiso revocado")
    is_active: bool
    assigned_by: Optional[str] = None
    expires_at: Optional[datetime] = None
    created_at: datetime
    updated_at: datetime
    permission: Optional[PermissionResponse] = None

    model_config = ConfigDict(from_attributes=True)


class AssignUserPermissionRequest(BaseModel):
    """Esquema de request para asignar un permiso individual a un usuario."""

    permission_id: int = Field(..., description="ID del permiso")
    is_granted: bool = Field(True, description="True para conceder, False para revocar")
    expires_at: Optional[datetime] = Field(None, description="Fecha de expiración (opcional)")


class UserPermissionsListResponse(BaseModel):
    """Lista de permisos individuales de un usuario."""

    items: List[UserPermissionResponse]
    total: int


class EffectiveUserPermissionsResponse(BaseModel):
    """Permisos efectivos de un usuario (roles + individuales - revocados)."""

    user_id: str
    company_id: int
    role_permissions: List[PermissionResponse] = Field(
        default_factory=list, description="Permisos heredados de roles"
    )
    granted_permissions: List[PermissionResponse] = Field(
        default_factory=list, description="Permisos individuales concedidos"
    )
    revoked_permissions: List[PermissionResponse] = Field(
        default_factory=list, description="Permisos revocados explícitamente"
    )
    effective_permissions: List[PermissionResponse] = Field(
        default_factory=list, description="Permisos finales efectivos"
    )
