"""
Cross-platform persistent directory utilities for PyInstaller compatibility.

This module provides functions to create and manage persistent directories
that survive PyInstaller temporary directory cleanup.
"""
import os
import sys
import platform
from pathlib import Path
import logging

logger = logging.getLogger(__name__)


def get_platform_persistent_dir(app_name="MBetter"):
    """
    Get the appropriate persistent directory for the current platform.
    
    Args:
        app_name (str): Application name for directory naming
        
    Returns:
        Path: Platform-appropriate persistent directory path
    """
    system = platform.system().lower()
    
    if system == "windows":
        # Windows: Use APPDATA\MBetter
        base_dir = os.environ.get('APPDATA')
        if not base_dir:
            # Fallback to user profile
            base_dir = os.path.expanduser('~')
            return Path(base_dir) / app_name
        return Path(base_dir) / app_name
        
    elif system == "darwin":  # macOS
        # macOS: Use ~/Library/Application Support/MBetter
        return Path.home() / "Library" / "Application Support" / app_name
        
    else:  # Linux and other Unix-like systems
        # Linux: Check if we have write permission to /opt, otherwise use user directory
        opt_path = Path("/opt") / app_name
        try:
            # Test if we can write to /opt/MBetter
            opt_path.mkdir(parents=True, exist_ok=True)
            test_file = opt_path / ".write_test"
            test_file.touch()
            test_file.unlink()
            return opt_path
        except (PermissionError, OSError):
            # Fallback to user directory
            return Path.home() / ".local" / "share" / app_name


def get_uploads_directory(custom_path=None):
    """
    Get the uploads directory, with optional custom path override.
    
    Args:
        custom_path (str, optional): Custom path override
        
    Returns:
        Path: Uploads directory path
    """
    if custom_path:
        return Path(custom_path)
    
    # Check environment variable first
    env_path = os.environ.get('MBETTER_UPLOADS_DIR')
    if env_path:
        return Path(env_path)
    
    # Use platform-appropriate persistent directory
    base_dir = get_platform_persistent_dir()
    return base_dir / "uploads"


def get_logs_directory(custom_path=None):
    """
    Get the logs directory, with optional custom path override.
    
    Args:
        custom_path (str, optional): Custom path override
        
    Returns:
        Path: Logs directory path
    """
    if custom_path:
        return Path(custom_path)
    
    # Check environment variable first
    env_path = os.environ.get('MBETTER_LOGS_DIR')
    if env_path:
        return Path(env_path)
    
    # Use platform-appropriate persistent directory
    base_dir = get_platform_persistent_dir()
    return base_dir / "logs"


def get_data_directory(custom_path=None):
    """
    Get the data directory for database and other persistent data.
    
    Args:
        custom_path (str, optional): Custom path override
        
    Returns:
        Path: Data directory path
    """
    if custom_path:
        return Path(custom_path)
    
    # Check environment variable first
    env_path = os.environ.get('MBETTER_DATA_DIR')
    if env_path:
        return Path(env_path)
    
    # Use platform-appropriate persistent directory
    base_dir = get_platform_persistent_dir()
    return base_dir / "data"


def get_config_directory(custom_path=None):
    """
    Get the config directory for configuration files.
    
    Args:
        custom_path (str, optional): Custom path override
        
    Returns:
        Path: Config directory path
    """
    if custom_path:
        return Path(custom_path)
    
    # Check environment variable first
    env_path = os.environ.get('MBETTER_CONFIG_DIR')
    if env_path:
        return Path(env_path)
    
    # Use platform-appropriate persistent directory
    base_dir = get_platform_persistent_dir()
    return base_dir / "config"


def ensure_directory_exists(directory_path, description="directory"):
    """
    Ensure a directory exists, creating it if necessary.
    
    Args:
        directory_path (Path or str): Directory path to create
        description (str): Description for logging purposes
        
    Returns:
        Path: The created/existing directory path
        
    Raises:
        OSError: If directory cannot be created
    """
    path = Path(directory_path)
    
    try:
        path.mkdir(parents=True, exist_ok=True)
        logger.info(f"Ensured {description} exists: {path}")
        return path
    except OSError as e:
        logger.error(f"Failed to create {description} at {path}: {e}")
        raise OSError(f"Cannot create {description} at {path}: {e}")


def is_pyinstaller():
    """
    Check if the application is running from a PyInstaller bundle.
    
    Returns:
        bool: True if running from PyInstaller, False otherwise
    """
    return getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS')


def get_application_root():
    """
    Get the application root directory.
    
    For PyInstaller executables, this returns the directory containing the executable.
    For regular Python scripts, this returns the script's directory.
    
    Returns:
        Path: Application root directory
    """
    if is_pyinstaller():
        # PyInstaller: Use the directory containing the executable
        return Path(sys.executable).parent
    else:
        # Regular Python: Use the directory containing this file's parent directory
        return Path(__file__).parent.parent.parent


def setup_persistent_directories(config_class=None):
    """
    Set up all persistent directories needed by the application.
    
    Args:
        config_class: Configuration class to update (optional)
        
    Returns:
        dict: Dictionary containing all created directory paths
    """
    directories = {}
    
    try:
        # Create all necessary directories
        directories['uploads'] = ensure_directory_exists(
            get_uploads_directory(),
            "uploads directory"
        )
        
        directories['logs'] = ensure_directory_exists(
            get_logs_directory(),
            "logs directory"
        )
        
        directories['data'] = ensure_directory_exists(
            get_data_directory(),
            "data directory"
        )
        
        directories['config'] = ensure_directory_exists(
            get_config_directory(),
            "config directory"
        )
        
        # Create subdirectories for uploads
        directories['fixtures'] = ensure_directory_exists(
            directories['uploads'] / "fixtures",
            "fixtures upload directory"
        )
        
        directories['zips'] = ensure_directory_exists(
            directories['uploads'] / "zips",
            "zip files upload directory"
        )
        
        directories['temp'] = ensure_directory_exists(
            directories['uploads'] / "temp",
            "temporary files directory"
        )
        
        logger.info("Successfully set up all persistent directories")
        logger.info(f"Application running from PyInstaller: {is_pyinstaller()}")
        logger.info(f"Base persistent directory: {get_platform_persistent_dir()}")
        
        return directories
        
    except Exception as e:
        logger.error(f"Failed to setup persistent directories: {e}")
        raise


def cleanup_temp_directory(temp_dir=None):
    """
    Clean up temporary files in the temp directory.
    
    Args:
        temp_dir (Path, optional): Temp directory to clean. Defaults to get_uploads_directory() / "temp"
    """
    if temp_dir is None:
        temp_dir = get_uploads_directory() / "temp"
    
    temp_path = Path(temp_dir)
    if not temp_path.exists():
        return
    
    try:
        import shutil
        import time
        
        # Remove files older than 24 hours
        current_time = time.time()
        cleanup_count = 0
        
        for file_path in temp_path.rglob('*'):
            if file_path.is_file():
                try:
                    file_age = current_time - file_path.stat().st_mtime
                    if file_age > 86400:  # 24 hours in seconds
                        file_path.unlink()
                        cleanup_count += 1
                except OSError:
                    pass  # Skip files we can't delete
        
        if cleanup_count > 0:
            logger.info(f"Cleaned up {cleanup_count} old temporary files")
            
    except Exception as e:
        logger.warning(f"Failed to cleanup temp directory: {e}")


# Environment variable names for configuration
ENV_VARS = {
    'uploads': 'MBETTER_UPLOADS_DIR',
    'logs': 'MBETTER_LOGS_DIR', 
    'data': 'MBETTER_DATA_DIR'
}

# Default directory structure
DEFAULT_STRUCTURE = {
    'uploads': ['fixtures', 'zips', 'temp'],
    'logs': [],
    'data': []
}