"""
Registro centralizado para la modulación de permisos.
Permite que cada módulo registre sus propios permisos de forma dinámica.
"""

import logging
from typing import Dict, List, Optional, Any
from dataclasses import dataclass, field

logger = logging.getLogger(__name__)

@dataclass
class PermissionDefinition:
    """Representa la definición de un permiso en un módulo."""
    code: str
    description: Optional[str] = None
    module: Optional[str] = None
    action: Optional[str] = None
    is_active: bool = True

    def __post_init__(self):
        """Lógica de autocompletado para evitar redundancia."""
        # Si el código tiene el formato "modulo.sub.accion" o "modulo.accion"
        parts = self.code.split(".")
        
        # Extraer módulo si no se especificó
        if not self.module and len(parts) > 1:
            self.module = parts[0]
        elif not self.module:
            self.module = "system" # Default fallback
            
        # Extraer acción si no se especificó (es la última parte del código)
        if not self.action and len(parts) > 1:
            self.action = parts[-1]
        elif not self.action:
            self.action = "view" # Default fallback


class PermissionRegistry:
    """
    Registro Singleton para permisos de la aplicación.
    Cada módulo de la API debe importar este registro y dar de alta sus permisos.
    """
    _instance = None
    _permissions: Dict[str, PermissionDefinition] = {}

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super(PermissionRegistry, cls).__new__(cls)
            cls._permissions = {}
        return cls._instance

    @classmethod
    def register(cls, 
                 code: str, 
                 description: Optional[str] = None, 
                 module: Optional[str] = None, 
                 action: Optional[str] = None) -> None:
        """
        Registra un nuevo permiso en el sistema.
        """
        if code in cls._permissions:
            logger.debug(f"Permiso {code} ya está registrado, actualizando metadatos.")
            
        cls._permissions[code] = PermissionDefinition(
            code=code,
            description=description,
            module=module,
            action=action
        )

    @classmethod
    def register_many(cls, permissions_list: List[tuple]) -> None:
        """
        Registra múltiples permisos desde una lista de tuplas.
        Útil para migrar seeds estáticos.
        """
        for item in permissions_list:
            if len(item) == 2: # (code, description)
                cls.register(code=item[0], description=item[1])
            elif len(item) >= 3: # (code, description, module, ...)
                cls.register(
                    code=item[0], 
                    description=item[1], 
                    module=item[2],
                    action=item[3] if len(item) > 3 else None
                )

    @classmethod
    def get_all(cls) -> List[PermissionDefinition]:
        """Retorna todos los permisos registrados."""
        return list(cls._permissions.values())

    @classmethod
    def get_by_module(cls, module_name: str) -> List[PermissionDefinition]:
        """Retorna los permisos de un módulo específico."""
        return [p for p in cls._permissions.values() if p.module == module_name]


# Instancia global para facilitar el acceso
registry = PermissionRegistry()
