"""Shared utility functions for the Research Library."""

import hashlib
import os
import subprocess
import sys
from pathlib import Path

from flask import jsonify
from loguru import logger

from ...config.paths import get_library_directory
from ...security.path_validator import PathValidator


def get_url_hash(url: str) -> str:
    """
    Generate a SHA256 hash of a URL.

    Args:
        url: The URL to hash

    Returns:
        The SHA256 hash of the URL
    """
    return hashlib.sha256(url.lower().encode()).hexdigest()


def get_library_storage_path(username: str) -> Path:
    """
    Get the storage path for a user's library.

    Uses the settings system which respects environment variable overrides:
    - research_library.storage_path: Base path for library storage
    - research_library.shared_library: If true, all users share the same directory

    Args:
        username: The username

    Returns:
        Path to the library storage directory
    """
    from ...utilities.db_utils import get_settings_manager

    settings = get_settings_manager()

    # Get the base path from settings (uses centralized path, respects LDR_DATA_DIR)
    base_path = Path(
        settings.get_setting(
            "research_library.storage_path",
            str(get_library_directory()),
        )
    ).expanduser()

    # Check if shared library mode is enabled
    shared_library = settings.get_setting(
        "research_library.shared_library", False
    )

    if shared_library:
        # Shared mode: all users use the same directory
        base_path.mkdir(parents=True, exist_ok=True)
        return base_path
    else:
        # Default: user isolation with subdirectories
        user_dir = base_path / username
        user_dir.mkdir(parents=True, exist_ok=True)
        return user_dir


def open_file_location(file_path: str) -> bool:
    """
    Open the file location in the system file manager.

    Args:
        file_path: Path to the file

    Returns:
        True if successful, False otherwise
    """
    try:
        # Validate path is safe (blocks system dirs, path traversal)
        validated = PathValidator.validate_local_filesystem_path(file_path)
        folder = str(validated.parent)
        if sys.platform == "win32":
            os.startfile(folder)
        elif sys.platform == "darwin":  # macOS
            result = subprocess.run(
                ["open", folder], capture_output=True, text=True, shell=False
            )
            if result.returncode != 0:
                logger.error(f"Failed to open folder on macOS: {result.stderr}")
                return False
        else:  # Linux
            result = subprocess.run(
                ["xdg-open", folder],
                capture_output=True,
                text=True,
                shell=False,
            )
            if result.returncode != 0:
                logger.error(f"Failed to open folder on Linux: {result.stderr}")
                return False
        return True
    except Exception:
        logger.exception("Failed to open file location")
        return False


def get_relative_library_path(absolute_path: str, username: str) -> str:
    """
    Get the relative path from the library root.

    Args:
        absolute_path: The absolute file path
        username: The username

    Returns:
        The relative path from the library root
    """
    try:
        library_root = get_library_storage_path(username)
        return str(Path(absolute_path).relative_to(library_root))
    except ValueError:
        # Path is not relative to library root
        return Path(absolute_path).name


def get_absolute_library_path(relative_path: str, username: str) -> Path:
    """
    Get the absolute path from a relative library path.

    Args:
        relative_path: The relative path from library root
        username: The username

    Returns:
        The absolute path
    """
    library_root = get_library_storage_path(username)
    return library_root / relative_path


def get_absolute_path_from_settings(relative_path: str) -> Path:
    """
    Get absolute path using settings manager for library root.

    Args:
        relative_path: The relative path from library root

    Returns:
        The absolute path
    """
    from ...utilities.db_utils import get_settings_manager

    settings = get_settings_manager()
    library_root = Path(
        settings.get_setting(
            "research_library.storage_path",
            str(get_library_directory()),
        )
    ).expanduser()

    if not relative_path:
        return library_root

    return library_root / relative_path


def handle_api_error(operation: str, error: Exception, status_code: int = 500):
    """
    Handle API errors consistently - log internally, return generic message to user.

    This prevents information exposure by logging full error details internally
    while returning a generic message to the user.

    Args:
        operation: Description of the operation that failed (for logging)
        error: The exception that occurred
        status_code: HTTP status code to return (default: 500)

    Returns:
        Flask JSON response tuple (response, status_code)
    """
    # Log the full error internally with stack trace
    logger.exception(f"Error during {operation}")

    # Return generic message to user (no internal details exposed)
    return jsonify(
        {
            "success": False,
            "error": "An internal error occurred. Please try again or contact support.",
        }
    ), status_code
