import os
from typing import Optional
from .interfaces import StorageInterface
from .cache import CacheSystem

class ProjectStorage(StorageInterface):
    """Project storage system implementation."""
    
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super(ProjectStorage, cls).__new__(cls)
            cls._instance._initialize()
        return cls._instance
    
    def _initialize(self):
        """Initialize the storage system."""
        # Get the user's home directory
        self.home_dir = os.path.expanduser("~")
        # Define the base directory
        self.base_dir = os.path.join(self.home_dir, ".diona")
        
        # Create directories if they don't exist
        os.makedirs(self.base_dir, exist_ok=True)
        
        # Define subdirectories
        self.project_dir = os.path.join(self.base_dir, "project")
        self.cache_dir = os.path.join(self.base_dir, "cache")
        self.user_dir = os.path.join(self.base_dir, "user")
        
        # Create subdirectories
        os.makedirs(self.project_dir, exist_ok=True)
        os.makedirs(self.cache_dir, exist_ok=True)
        os.makedirs(self.user_dir, exist_ok=True)
        
        # Initialize cache system
        self.cache_system = CacheSystem(self.cache_dir)
    
    def get_path(self, module_name: str, relative_path: str, storage_type: str = "project") -> str:
        """Get the full path for a given module and relative path."""
        if storage_type == "project":
            base = self.project_dir
        elif storage_type == "cache":
            base = self.cache_dir
        elif storage_type == "user":
            base = self.user_dir
        else:
            base = self.project_dir
        
        module_dir = os.path.join(base, module_name)
        os.makedirs(module_dir, exist_ok=True)
        
        # Handle relative paths
        if relative_path.startswith("/"):
            relative_path = relative_path[1:]
        
        return os.path.join(module_dir, relative_path)
    
    def exists(self, module_name: str, relative_path: str, storage_type: str = "project") -> bool:
        """Check if a path exists."""
        return os.path.exists(self.get_path(module_name, relative_path, storage_type))
    
    def create(self, module_name: str, relative_path: str, storage_type: str = "project") -> bool:
        """Create a file or directory."""
        try:
            path = self.get_path(module_name, relative_path, storage_type)
            os.makedirs(os.path.dirname(path), exist_ok=True)
            if not os.path.exists(path):
                open(path, 'w', encoding='utf-8').close()
            return True
        except:
            return False
    
    def read(self, module_name: str, relative_path: str, encoding: str = 'utf-8', storage_type: str = "project") -> Optional[str]:
        """Read content from a file."""
        try:
            with open(self.get_path(module_name, relative_path, storage_type), 'r', encoding=encoding) as f:
                return f.read()
        except:
            return None
    
    def write(self, module_name: str, relative_path: str, content: str, encoding: str = 'utf-8', storage_type: str = "project") -> bool:
        """Write content to a file."""
        try:
            path = self.get_path(module_name, relative_path, storage_type)
            os.makedirs(os.path.dirname(path), exist_ok=True)
            with open(path, 'w', encoding=encoding) as f:
                f.write(content)
            return True
        except:
            return False
    
    def delete(self, module_name: str, relative_path: str, storage_type: str = "project") -> bool:
        """Delete a file or directory."""
        try:
            path = self.get_path(module_name, relative_path, storage_type)
            if os.path.exists(path):
                if os.path.isfile(path):
                    os.remove(path)
                else:
                    import shutil
                    shutil.rmtree(path)
            return True
        except:
            return False
    
    def update(self, module_name: str, relative_path: str, content: str, encoding: str = 'utf-8', storage_type: str = "project") -> bool:
        """Update content in a file."""
        return self.write(module_name, relative_path, content, encoding, storage_type)
    
    # Cache system methods
    def set_cache(self, module_name: str, key: str, value, expiration: int = 3600):
        """Set a cache value with expiration."""
        return self.cache_system.set_cache(module_name, key, value, expiration)
    
    def get_cache(self, module_name: str, key: str):
        """Get a cache value."""
        return self.cache_system.get_cache(module_name, key)
    
    def delete_cache(self, module_name: str, key: str):
        """Delete a cache value."""
        return self.cache_system.delete_cache(module_name, key)
    
    def clear_cache(self, module_name: str):
        """Clear all cache for a module."""
        return self.cache_system.clear_cache(module_name)

# Singleton factory function
def get_storage_instance():
    """Get the singleton storage instance."""
    return ProjectStorage()
