"""
Centralized path configuration for Local Deep Research.
Handles database location using platformdirs for proper user data storage.
"""

import hashlib
import os
from pathlib import Path

import platformdirs
from loguru import logger


def get_data_directory() -> Path:
    """
    Get the appropriate data directory for storing application data.
    Uses platformdirs to get platform-specific user data directory.

    Environment variable:
        LDR_DATA_DIR: Override the default data directory location.
                     All subdirectories (research_outputs, cache, logs, database)
                     will be created under this directory.

    Returns:
        Path to data directory
    """
    # Check for explicit override via environment variable
    custom_path = os.getenv("LDR_DATA_DIR")
    if custom_path:
        data_dir = Path(custom_path)
        logger.debug(
            f"Using custom data directory from LDR_DATA_DIR: {data_dir}"
        )
        return data_dir

    # Use platformdirs for platform-specific user data directory
    # Windows: C:\Users\Username\AppData\Local\local-deep-research
    # macOS: ~/Library/Application Support/local-deep-research
    # Linux: ~/.local/share/local-deep-research
    data_dir = Path(platformdirs.user_data_dir("local-deep-research"))
    # Log only the directory pattern, not the full path which may contain username
    logger.debug(
        f"Using platformdirs data directory pattern: .../{data_dir.name}"
    )

    return data_dir


def get_research_outputs_directory() -> Path:
    """
    Get the directory for storing research outputs (reports, etc.).

    Returns:
        Path to research outputs directory
    """
    # Use subdirectory of main data directory
    data_dir = get_data_directory()
    outputs_dir = data_dir / "research_outputs"
    outputs_dir.mkdir(parents=True, exist_ok=True)

    logger.debug(f"Using research outputs directory: {outputs_dir}")
    return outputs_dir


def get_journal_data_directory() -> Path:
    """Get the directory for downloaded journal quality data files.

    Contains openalex_sources.json.gz, doaj_journals.json, and the
    compiled journal_reference.db. Fetched on first use from
    OpenAlex and DOAJ APIs.

    Returns:
        Path to journal data directory
    """
    data_dir = get_data_directory()
    journal_dir = data_dir / "journal_data"
    journal_dir.mkdir(parents=True, exist_ok=True)
    return journal_dir


def get_cache_directory() -> Path:
    """
    Get the directory for storing cache files (search cache, etc.).

    Returns:
        Path to cache directory
    """
    # Use subdirectory of main data directory
    data_dir = get_data_directory()
    cache_dir = data_dir / "cache"
    cache_dir.mkdir(parents=True, exist_ok=True)

    logger.debug(f"Using cache directory: {cache_dir}")
    return cache_dir


def get_logs_directory() -> Path:
    """
    Get the directory for storing log files.

    Returns:
        Path to logs directory
    """
    # Use subdirectory of main data directory
    data_dir = get_data_directory()
    logs_dir = data_dir / "logs"
    logs_dir.mkdir(parents=True, exist_ok=True)

    logger.debug(f"Using logs directory: {logs_dir}")
    return logs_dir


def get_encrypted_database_path() -> Path:
    """Get the path to the encrypted databases directory.

    Returns:
        Path to the encrypted databases directory
    """
    data_dir = get_data_directory()
    encrypted_db_path = data_dir / "encrypted_databases"
    encrypted_db_path.mkdir(parents=True, exist_ok=True)
    return encrypted_db_path


def get_user_database_filename(username: str) -> str:
    """Get the database filename for a specific user.

    Args:
        username: The username to generate a filename for

    Returns:
        The database filename (not full path) for the user
    """
    # Use username hash to avoid filesystem issues with special characters
    username_hash = hashlib.sha256(username.encode()).hexdigest()[:16]
    return f"ldr_user_{username_hash}.db"


def get_library_directory() -> Path:
    """
    Get the directory for storing library files (documents, PDFs, etc.).

    Returns:
        Path to library directory
    """
    # Use subdirectory of main data directory
    data_dir = get_data_directory()
    library_dir = data_dir / "library"
    library_dir.mkdir(parents=True, exist_ok=True)

    logger.debug(f"Using library directory: {library_dir}")
    return library_dir


def get_config_directory() -> Path:
    """
    Get the directory for storing configuration files.

    Returns:
        Path to config directory
    """
    # Use subdirectory of main data directory
    data_dir = get_data_directory()
    config_dir = data_dir / "config"
    config_dir.mkdir(parents=True, exist_ok=True)

    logger.debug(f"Using config directory: {config_dir}")
    return config_dir


def get_models_directory() -> Path:
    """
    Get the directory for storing downloaded models.

    Returns:
        Path to models directory
    """
    # Use subdirectory of main data directory
    data_dir = get_data_directory()
    models_dir = data_dir / "models"
    models_dir.mkdir(parents=True, exist_ok=True)

    logger.debug(f"Using models directory: {models_dir}")
    return models_dir


def get_backup_directory() -> Path:
    """Get the base backup directory for all users."""
    data_dir = get_data_directory()
    backup_dir = data_dir / "encrypted_databases" / "backups"
    backup_dir.mkdir(parents=True, exist_ok=True)
    return backup_dir


def get_user_backup_directory(username: str) -> Path:
    """Get backup directory for a specific user."""
    username_hash = hashlib.sha256(username.encode()).hexdigest()[:16]
    user_backup_dir = get_backup_directory() / username_hash
    user_backup_dir.mkdir(parents=True, exist_ok=True, mode=0o700)
    # Enforce 0o700 regardless of umask (mkdir mode is umask-masked)
    user_backup_dir.chmod(0o700)
    return user_backup_dir


# Convenience functions for backward compatibility
def get_data_dir() -> str:
    """Get data directory as string for backward compatibility."""
    return str(get_data_directory())
