"""
Implementación de Origin para sistema de archivos local.
"""
import os
from pathlib import Path
from typing import List, Optional, Union

from tai_alphi import Alphi
from tai_storage.base import Origin
from tai_storage.exceptions import (
    FolderNotFoundError,
    FolderAlreadyExistsError,
    InvalidPathError,
)
from tai_storage.utils import normalize_path
from .folder import LocalFolder

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


class LocalOrigin(Origin):
    """
    Implementación de Origin para el sistema de archivos local.
    
    Este origen representa el acceso a archivos y carpetas en el
    sistema de archivos local de la máquina.
    """
    
    def __init__(self, root_path: Union[str, Path]):
        """
        Inicializa el origen local.

        Args:
            root_path: Ruta raíz del almacenamiento local (str o Path)

        Example:
            >>> origin = LocalOrigin(root_path='/home/user/data')
            >>> folder = origin.get_folder('documents')
        """
        super().__init__()
        self.root_path = Path(root_path).resolve()

        logger.info(f"[tai-storage] Initialized LocalOrigin with root: {self.root_path}")

        # Crear directorio raíz si no existe
        if not self.root_path.exists():
            logger.info(f"[tai-storage] Creating root directory: {self.root_path}")
            self.root_path.mkdir(parents=True, exist_ok=True)

        # Para origen local, siempre está "conectado"
        self._connected = True
    
    def connect(self) -> None:
        """
        Establece conexión con el origen.

        Para el sistema local, esta operación verifica que el directorio
        raíz existe y es accesible.
        """
        if not self.root_path.exists():
            logger.error(f"[tai-storage] Root directory does not exist: {self.root_path}")
            raise InvalidPathError(f"Root directory does not exist: {self.root_path}")

        if not self.root_path.is_dir():
            logger.error(f"[tai-storage] Root path is not a directory: {self.root_path}")
            raise InvalidPathError(f"Root path is not a directory: {self.root_path}")

        self._connected = True
        logger.debug(f"[tai-storage] Connected to local origin: {self.root_path}")
    
    def disconnect(self) -> None:
        """
        Cierra la conexión con el origen.
        
        Para el sistema local, esta operación es un no-op.
        """
        self._connected = False
        logger.debug(f"[tai-storage] Disconnected from local origin: {self.root_path}")
    
    def is_connected(self) -> bool:
        """Verifica si hay conexión activa."""
        return self._connected and self.root_path.exists()
    
    def _get_full_path(self, path: Union[str, Path]) -> Path:
        """
        Obtiene la ruta completa combinando root_path con el path relativo.

        Args:
            path: Ruta relativa (str o Path)

        Returns:
            Ruta absoluta completa como Path
        """
        normalized = normalize_path(path)
        if not normalized:
            return self.root_path
        return self.root_path / normalized
    
    def get_folder(self, path: Union[str, Path] = '') -> 'LocalFolder':
        """Obtiene una referencia a una carpeta."""
        full_path = self._get_full_path(path)
        logger.debug(f"[tai-storage] Getting folder reference: {full_path}")
        return LocalFolder(self, full_path)

    def list_folders(self, path: Union[str, Path] = '', pattern: Optional[str] = None) -> List['LocalFolder']:
        """Lista las carpetas en una ruta específica como objetos LocalFolder."""
        full_path = self._get_full_path(path)
        folder = LocalFolder(self, full_path)

        if not folder.exists():
            raise FolderNotFoundError(f"Folder not found: {full_path}")

        return folder.list_folders(pattern=pattern)

    def create_folder(self, path: Union[str, Path], parents: bool = True) -> 'LocalFolder':
        """Crea una carpeta en el origen."""
        full_path = self._get_full_path(path)
        folder = LocalFolder(self, full_path)

        if folder.exists():
            raise FolderAlreadyExistsError(f"Folder already exists: {full_path}")

        logger.info(f"[tai-storage] Creating folder: {full_path} (parents={parents})")
        folder.create(parents=parents)

        return folder

    def delete_folder(self, path: Union[str, Path], recursive: bool = False) -> None:
        """Elimina una carpeta del origen."""
        full_path = self._get_full_path(path)

        # No permitir eliminar el directorio raíz
        if full_path.resolve() == self.root_path:
            raise InvalidPathError("Cannot delete root directory")

        folder = LocalFolder(self, full_path)

        if not folder.exists():
            raise FolderNotFoundError(f"Folder not found: {full_path}")

        logger.warning(f"[tai-storage] Deleting folder: {full_path} (recursive={recursive})")
        folder.delete(recursive=recursive)

    def folder_exists(self, path: Union[str, Path]) -> bool:
        """Verifica si una carpeta existe."""
        full_path = self._get_full_path(path)
        folder = LocalFolder(self, full_path)
        return folder.exists()
    
    def __repr__(self) -> str:
        """Representación string del origen."""
        return f"<LocalOrigin root='{self.root_path}' connected={self.is_connected()}>"
