"""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


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 (env vars will override if set)
    base_path = Path(
        settings.get_setting(
            "research_library.storage_path",
            str(Path.home() / "Documents" / "LocalDeepResearch" / "Library"),
        )
    ).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:
        folder = str(Path(file_path).parent)
        if sys.platform == "win32":
            os.startfile(folder)
        elif sys.platform == "darwin":  # macOS
            result = subprocess.run(
                ["open", folder], capture_output=True, text=True
            )
            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
            )
            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",
            "~/.local-deep-research/library",
        )
    ).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
