from typing import Optional
from pydantic import BaseModel, Field


class LoginRequest(BaseModel):
    email: str = Field(..., description="Correo electrónico del usuario")
    password: str = Field(..., description="Contraseña del usuario")


class CreateConnectionRequest(BaseModel):
    name: str = Field(..., description="Nombre descriptivo de la conexión")
    base_url: str = Field(..., description="URL base de la instancia Alfresco (ej: https://alfresco.empresa.com)")
    ip_server: str = Field(..., description="IP del servidor Alfresco para autorización de webhooks")
    username: Optional[str] = Field("", description="Usuario de Alfresco para sincronización (workers)")
    password: Optional[str] = Field(None, description="Contraseña de Alfresco para sincronización (se cifra con Fernet)")
    api_username: Optional[str] = Field(None, description="Usuario de Alfresco para API/Webhooks (si no se configura, usa las credenciales de sincronización)")
    api_password: Optional[str] = Field(None, description="Contraseña de Alfresco para API/Webhooks (se cifra con Fernet)")
    client_id: Optional[str] = Field("", description="Client ID para OAuth2")
    client_secret: Optional[str] = Field(None, description="Client Secret para OAuth2 (se cifra con Fernet)")
    auth_type: Optional[str] = Field("basic", description="Tipo de autenticación: basic u oauth2")
    active: Optional[bool] = Field(True, description="Conexión activa")
    notes: Optional[str] = Field("", description="Notas adicionales")


class UpdateConnectionRequest(BaseModel):
    name: Optional[str] = Field(None, description="Nombre descriptivo de la conexión")
    base_url: Optional[str] = Field(None, description="URL base de la instancia Alfresco")
    ip_server: Optional[str] = Field(None, description="IP del servidor Alfresco")
    username: Optional[str] = Field(None, description="Usuario de Alfresco para sincronización")
    password: Optional[str] = Field(None, description="Nueva contraseña para sincronización (se cifra con Fernet)")
    api_username: Optional[str] = Field(None, description="Usuario de Alfresco para API/Webhooks")
    api_password: Optional[str] = Field(None, description="Nueva contraseña para API/Webhooks (se cifra con Fernet)")
    client_id: Optional[str] = Field(None, description="Client ID para OAuth2")
    client_secret: Optional[str] = Field(None, description="Nuevo Client Secret (se cifra con Fernet)")
    auth_type: Optional[str] = Field(None, description="Tipo de autenticación")
    active: Optional[bool] = Field(None, description="Activar/desactivar conexión")
    notes: Optional[str] = Field(None, description="Notas adicionales")


class CreateSiteRequest(BaseModel):
    name: str = Field(..., description="Nombre del sitio")
    site_id: str = Field(..., description="ID del sitio en Alfresco")
    connection_id: int = Field(..., description="ID de la conexión Alfresco asociada")
    title: Optional[str] = Field(None, description="Título del sitio")
    description: Optional[str] = Field("", description="Descripción del sitio")
    visibility: Optional[str] = Field("PUBLIC", description="Visibilidad: PUBLIC o PRIVATE")
    root_folder_id: Optional[str] = Field("", description="Node ID de la Serie, Subserie o Expediente raíz en Alfresco")
    root_folder_path: Optional[str] = Field("", description="Ruta de la Serie, Subserie o Expediente raíz")
    document_library_id: Optional[str] = Field("", description="Node ID de la documentLibrary")
    site_preset: Optional[str] = Field("", description="Preset del sitio")
    site_role: Optional[str] = Field("", description="Rol en el sitio")
    metadata_json: Optional[dict] = Field(None, description="Metadatos adicionales en JSON")
    active: Optional[bool] = Field(True, description="Sitio activo")


class UpdateSiteRequest(BaseModel):
    name: Optional[str] = Field(None, description="Nombre del sitio")
    title: Optional[str] = Field(None, description="Título del sitio")
    description: Optional[str] = Field(None, description="Descripción del sitio")
    visibility: Optional[str] = Field(None, description="Visibilidad")
    root_folder_id: Optional[str] = Field(None, description="Node ID de Serie, Subserie o Expediente raíz")
    root_folder_path: Optional[str] = Field(None, description="Ruta de Serie, Subserie o Expediente raíz")
    document_library_id: Optional[str] = Field(None, description="Node ID de documentLibrary")
    site_preset: Optional[str] = Field(None, description="Preset del sitio")
    site_role: Optional[str] = Field(None, description="Rol en el sitio")
    metadata_json: Optional[dict] = Field(None, description="Metadatos adicionales en JSON")
    connection_id: Optional[int] = Field(None, description="ID de conexión Alfresco")
    active: Optional[bool] = Field(None, description="Activar/desactivar sitio")


class SyncSiteRequest(BaseModel):
    deep: bool = Field(False, description="True: sincronización recursiva completa. False: solo primer nivel")
    generate_index: bool = Field(True, description="Generar índices electrónicos index.xml para Series, Subseries o Expedientes hoja")


class CreateUserRequest(BaseModel):
    name: Optional[str] = Field("", description="Nombre completo del usuario")
    email: str = Field(..., description="Correo electrónico (debe ser único)")
    password: str = Field(..., description="Contraseña del usuario")
    role: Optional[str] = Field("user", description="Rol asignado (debe existir en roles)")
    active: Optional[bool] = Field(True, description="Usuario activo")


class UpdateUserRequest(BaseModel):
    name: Optional[str] = Field(None, description="Nombre completo del usuario")
    email: Optional[str] = Field(None, description="Correo electrónico")
    password: Optional[str] = Field(None, description="Nueva contraseña")
    role: Optional[str] = Field(None, description="Rol asignado")
    active: Optional[bool] = Field(None, description="Activar/desactivar usuario")


class CreateRoleRequest(BaseModel):
    name: str = Field(..., description="Nombre del rol (debe ser único)")
    all_permissions: bool = Field(False, description="Si es True, este rol tiene todos los permisos sin asignación explícita")
    description: Optional[str] = Field("", description="Descripción del rol")
    permission_ids: Optional[list[int]] = Field(None, description="Lista de IDs de permisos a asignar al rol")


class UpdateRoleRequest(BaseModel):
    name: Optional[str] = Field(None, description="Nombre del rol")
    all_permissions: Optional[bool] = Field(None, description="Tiene todos los permisos")
    description: Optional[str] = Field(None, description="Descripción del rol")
    permission_ids: Optional[list[int]] = Field(None, description="Lista de IDs de permisos a asignar")


class WebhookListenerRequest(BaseModel):
    node_id: str = Field(..., description="Node ID del archivo, Serie, Subserie o Expediente en Alfresco afectado por el evento")
    project_alfresco_name: str = Field("", description="Nombre del proyecto/sitio en Alfresco")
    is_folder: bool = Field(False, description="True si el node_id corresponde a una Serie, Subserie o Expediente, False si es archivo")
    action: int = Field(0, description="Tipo de acción: 1=create, 2=update, 3=delete, 4=move, 5=cerrar expediente, 6=reabrir expediente")
    folder_parent_id: Optional[str] = Field("", description="Node ID de la Serie, Subserie o Expediente padre donde se encuentra el archivo")
    name: Optional[str] = Field("", description="Nombre del archivo, Serie, Subserie o Expediente")
    date_closing: Optional[str] = Field(None, description="Fecha del cierre del expediente (action=5)")
    user_closing: Optional[str] = Field(None, description="Usuario que cerró el expediente (action=5)")
    comment_closing: Optional[str] = Field(None, description="Comentario del cierre del expediente (action=5)")
    date_reopening: Optional[str] = Field(None, description="Fecha de la reapertura del expediente (action=6)")
    user_reopening: Optional[str] = Field(None, description="Usuario que reabrió el expediente (action=6)")
    comment_reopening: Optional[str] = Field(None, description="Comentario de la reapertura del expediente (action=6)")


class CreateReporteRequest(BaseModel):
    name: str = Field(..., description="Nombre del reporte")
    code: str = Field(..., description="Código único del reporte")
    description: Optional[str] = Field("", description="Descripción del reporte")
    type_report: int = Field(1, description="1=interno, 2=externo (URL)")
    url_report: Optional[str] = Field(None, description="URL del reporte externo (requerido si type_report=2)")
    active: Optional[bool] = Field(True, description="Reporte activo")


class UpdateReporteRequest(BaseModel):
    name: Optional[str] = Field(None, description="Nombre del reporte")
    code: Optional[str] = Field(None, description="Código único del reporte")
    description: Optional[str] = Field(None, description="Descripción del reporte")
    type_report: Optional[int] = Field(None, description="1=interno, 2=externo (URL)")
    url_report: Optional[str] = Field(None, description="URL del reporte externo")
    active: Optional[bool] = Field(None, description="Activar/desactivar reporte")
