"""
Clase base abstracta para Origin (sistemas de almacenamiento).
"""
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import List, Optional, TYPE_CHECKING

from tai_alphi import Alphi

if TYPE_CHECKING:
    from .folder import Folder

logger = Alphi.get_logger_by_name('tai-storage')


class Origin(ABC):
    """
    Clase base abstracta que representa un sistema de almacenamiento de archivos.
    
    Un origen puede ser Azure Blob Storage, SFTP, FTP, SharePoint, sistema local, etc.
    Define la interfaz común que todas las implementaciones deben seguir.
    """
    
    def __init__(self, **kwargs):
        """
        Inicializa el origen.
        
        Args:
            **kwargs: Parámetros específicos de cada implementación
        """
        self._connected = False
        logger.debug(f"Initializing {self.__class__.__name__}")
    
    @abstractmethod
    def connect(self) -> None:
        """
        Establece conexión con el origen.
        
        Raises:
            OriginConnectionError: Si falla la conexión
        """
        pass
    
    @abstractmethod
    def disconnect(self) -> None:
        """
        Cierra la conexión con el origen.
        """
        pass
    
    @abstractmethod
    def is_connected(self) -> bool:
        """
        Verifica si hay conexión activa con el origen.
        
        Returns:
            True si está conectado, False en caso contrario
        """
        pass
    
    @abstractmethod
    def get_folder(self, path: str) -> Folder:
        """
        Obtiene una referencia a una carpeta en el origen.
        
        Args:
            path: Ruta de la carpeta
            
        Returns:
            Instancia de Folder
            
        Note:
            No verifica si la carpeta existe, solo crea la referencia
        """
        pass
    
    @abstractmethod
    def list_folders(self, path: str = '', pattern: Optional[str] = None) -> List[Folder]:
        """
        Lista las carpetas en una ruta específica como objetos Folder.
        
        Args:
            path: Ruta base donde buscar carpetas (vacío = raíz)
            pattern: Patrón regex opcional para filtrar
            
        Returns:
            Lista de objetos Folder
            
        Examples:
            >>> # Listar todas las carpetas en la raíz
            >>> folders = origin.list_folders()
            
            >>> # Listar carpetas en un path específico
            >>> folders = origin.list_folders('data/reports')
            
            >>> # Filtrar por patrón
            >>> backups = origin.list_folders(pattern=r'^backup.*')
        """
        pass
    
    @abstractmethod
    def create_folder(self, path: str, parents: bool = True) -> Folder:
        """
        Crea una carpeta en el origen.
        
        Args:
            path: Ruta de la carpeta a crear
            parents: Si True, crea carpetas padres si no existen
            
        Returns:
            Instancia de Folder creada
            
        Raises:
            FolderAlreadyExistsError: Si la carpeta ya existe
            InvalidPathError: Si la ruta es inválida
        """
        pass
    
    @abstractmethod
    def delete_folder(self, path: str, recursive: bool = False) -> None:
        """
        Elimina una carpeta del origen.
        
        Args:
            path: Ruta de la carpeta a eliminar
            recursive: Si True, elimina contenido recursivamente
            
        Raises:
            FolderNotFoundError: Si la carpeta no existe
            PermissionError: Si no hay permisos suficientes
        """
        pass
    
    @abstractmethod
    def folder_exists(self, path: str) -> bool:
        """
        Verifica si una carpeta existe.
        
        Args:
            path: Ruta de la carpeta
            
        Returns:
            True si existe, False en caso contrario
        """
        pass
    
    def __enter__(self):
        """Context manager: conecta al entrar."""
        self.connect()
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """Context manager: desconecta al salir."""
        self.disconnect()
        return False
    
    def __repr__(self) -> str:
        """Representación string del origen."""
        return f"<{self.__class__.__name__} connected={self.is_connected()}>"
