"""
Implementación de Origin para Azure Blob Storage.
"""
from __future__ import annotations
from typing import List, Optional, TYPE_CHECKING

from azure.storage.blob import BlobServiceClient
from azure.core.exceptions import ResourceNotFoundError

from tai_alphi import Alphi
from ...base.origin import Origin
from ...exceptions import (
    OriginConnectionError,
    FolderNotFoundError,
    OperationNotSupportedError
)

if TYPE_CHECKING:
    from .folder import AzureBlobFolder

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


class AzureBlobOrigin(Origin):
    """
    Origin para Azure Blob Storage.
    
    En Azure Blob Storage, los "folders" son realmente containers.
    Los paths dentro de containers se simulan usando prefijos en blob names.
    
    Args:
        account_name: Nombre de la cuenta de Azure Storage
        account_key: Key de acceso de la cuenta
        connection_string: String de conexión completo (alternativa a account_name + account_key)
    """
    
    def __init__(
        self,
        account_name: Optional[str] = None,
        account_key: Optional[str] = None,
        connection_string: Optional[str] = None
    ):
        if connection_string:
            self.connection_string = connection_string
            self.account_name = None
            self.account_key = None
        elif account_name and account_key:
            self.account_name = account_name
            self.account_key = account_key
            self.connection_string = (
                f"DefaultEndpointsProtocol=https;"
                f"AccountName={account_name};"
                f"AccountKey={account_key};"
                f"EndpointSuffix=core.windows.net"
            )
        else:
            raise ValueError(
                "Debes proporcionar connection_string O (account_name + account_key)"
            )
        
        self._blob_service_client: Optional[BlobServiceClient] = None
        
        logger.info(f"AzureBlobOrigin inicializado")
    
    def connect(self) -> None:
        """Establece conexión con Azure Blob Storage."""
        try:
            self._blob_service_client = BlobServiceClient.from_connection_string(
                self.connection_string
            )
            
            # Verificar conexión listando containers (test básico)
            _ = list(self._blob_service_client.list_containers(max_results=1))
            
            logger.info("✓ Conectado a Azure Blob Storage")
            
        except Exception as e:
            logger.error(f"Error conectando a Azure: {e}")
            raise OriginConnectionError(f"Error de conexión a Azure Blob Storage: {e}")
    
    def disconnect(self) -> None:
        """Cierra la conexión con Azure Blob Storage."""
        if self._blob_service_client:
            self._blob_service_client.close()
            self._blob_service_client = None
        logger.info("Desconectado de Azure Blob Storage")
    
    def is_connected(self) -> bool:
        """Verifica si hay conexión activa."""
        return self._blob_service_client is not None
    
    def get_folder(self, path: str) -> AzureBlobFolder:
        """
        Obtiene una referencia a un container (folder en Azure Blob).
        
        En Azure Blob Storage, los folders de primer nivel son containers.
        Paths con '/' representan prefijos virtuales dentro de un container.
        
        Args:
            path: Nombre del container o "container/prefix/path"
            
        Returns:
            AzureBlobFolder configurado
        """
        if not self.is_connected():
            self.connect()
        
        from .folder import AzureBlobFolder
        
        folder = AzureBlobFolder(self, path)
        
        # Verificar que el container existe
        if not folder.exists():
            raise FolderNotFoundError(f"El container/folder '{path}' no existe")
        
        logger.debug(f"Obtenido folder: {path}")
        return folder
    
    def create_folder(self, path: str, parents: bool = True) -> AzureBlobFolder:
        """
        Crea un container en Azure Blob Storage.
        
        Nota: En Azure Blob, solo el primer nivel (container) se crea realmente.
        Los niveles internos (prefijos) se crean automáticamente al subir blobs.
        
        Args:
            path: Nombre del container o "container/prefix"
            parents: No aplicable en Azure Blob (los prefijos se crean automáticamente)
            
        Returns:
            AzureBlobFolder creado
        """
        if not self.is_connected():
            self.connect()
        
        from .folder import AzureBlobFolder
        
        # Separar container y prefix
        parts = path.split('/', 1)
        container_name = parts[0]
        
        # Crear container si no existe
        try:
            container_client = self._blob_service_client.get_container_client(container_name)
            
            if not container_client.exists():
                container_client.create_container()
                logger.info(f"✓ Container creado: {container_name}")
            else:
                logger.debug(f"Container '{container_name}' ya existe")
            
        except Exception as e:
            raise OriginConnectionError(f"Error creando container: {e}")
        
        return AzureBlobFolder(self, path)
    
    def folder_exists(self, path: str) -> bool:
        """
        Verifica si existe un container/folder.
        
        Args:
            path: Nombre del container o "container/prefix"
            
        Returns:
            True si existe, False si no
        """
        if not self.is_connected():
            self.connect()
        
        from .folder import AzureBlobFolder
        
        folder = AzureBlobFolder(self, path)
        return folder.exists()
    
    def list_folders(self, path: str = "", pattern: Optional[str] = None) -> List['AzureBlobFolder']:
        """
        Lista containers o subcarpetas virtuales como objetos AzureBlobFolder.
        
        Args:
            path: Vacío para listar containers, "container" para listar prefijos
            pattern: Patrón regex opcional para filtrar
            
        Returns:
            Lista de objetos AzureBlobFolder
        """
        from .folder import AzureBlobFolder
        
        if not self.is_connected():
            self.connect()
        
        if not path:
            # Listar containers como folders
            import re
            folders = []
            for container in self._blob_service_client.list_containers():
                container_name = container['name']
                
                # Aplicar filtro de patrón si existe
                if pattern and not re.search(pattern, container_name, re.IGNORECASE):
                    continue
                
                folder = AzureBlobFolder(self, container_name)
                folders.append(folder)
            return folders
        else:
            # Listar subcarpetas virtuales dentro de un container
            folder = AzureBlobFolder(self, path)
            return folder.list_folders(pattern=pattern)
    
    def delete_folder(self, path: str, recursive: bool = False) -> None:
        """
        Elimina un container de Azure Blob Storage.
        
        Nota: En Azure Blob, el recursive es siempre True efectivamente,
        ya que eliminar un container elimina todos sus blobs.
        
        Args:
            path: Nombre del container a eliminar
            recursive: Ignorado (siempre elimina todo el contenido)
            
        Raises:
            FolderNotFoundError: Si el container no existe
        """
        if not self.is_connected():
            self.connect()
        
        # Separar container y prefix
        parts = path.split('/', 1)
        container_name = parts[0]
        
        if len(parts) > 1:
            raise OperationNotSupportedError(
                "No se puede eliminar prefijos virtuales. "
                "Solo se pueden eliminar containers completos."
            )
        
        try:
            container_client = self._blob_service_client.get_container_client(container_name)
            
            if not container_client.exists():
                raise FolderNotFoundError(f"El container '{container_name}' no existe")
            
            container_client.delete_container()
            logger.info(f"✓ Container eliminado: {container_name}")
            
        except FolderNotFoundError:
            raise
        except Exception as e:
            raise OriginConnectionError(f"Error eliminando container: {e}")
    
    @property
    def client(self) -> BlobServiceClient:
        """BlobServiceClient para operaciones avanzadas."""
        if not self._blob_service_client:
            raise OriginConnectionError("No conectado. Llama a connect() primero.")
        return self._blob_service_client
