#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Core functionality for Qt Modern Style.

This module provides all the main functions for applying styles,
loading resources, and managing icons.
"""

import os
import sys
from pathlib import Path
from typing import Optional, List, Union

# Get the package directory
_PACKAGE_DIR = Path(__file__).parent.absolute()
_ICONS_DIR = _PACKAGE_DIR / "icons"
_BASE_ICONS_DIR = _ICONS_DIR / "base"
_ASSETS_ICONS_DIR = _ICONS_DIR / "assets"
_STYLESHEET_PATH = _PACKAGE_DIR / "styles.qss"

# Cache for the stylesheet content
_stylesheet_cache: Optional[str] = None

# Track if resources have been loaded
_resources_loaded = False


def get_package_dir() -> Path:
    """
    Get the path to the package directory.

    Returns:
        Path: Path to the qt_modern_style package directory.

    Example:
        >>> import qt_modern_style
        >>> pkg_dir = qt_modern_style.get_package_dir()
        >>> print(pkg_dir)
    """
    return _PACKAGE_DIR


def get_stylesheet_path() -> Path:
    """
    Get the path to the stylesheet file.

    Returns:
        Path: Path to the styles.qss file.

    Example:
        >>> import qt_modern_style
        >>> qss_path = qt_modern_style.get_stylesheet_path()
        >>> print(qss_path)
    """
    return _STYLESHEET_PATH


def get_stylesheet() -> str:
    """
    Get the stylesheet content as a string.

    The stylesheet is cached after the first read for better performance.

    Returns:
        str: The complete stylesheet content.

    Example:
        >>> import qt_modern_style
        >>> stylesheet = qt_modern_style.get_stylesheet()
        >>> app.setStyleSheet(stylesheet)
    """
    global _stylesheet_cache

    if _stylesheet_cache is None:
        with open(_STYLESHEET_PATH, "r", encoding="utf-8") as f:
            _stylesheet_cache = f.read()

    return _stylesheet_cache


def _get_qt_module():
    """
    Detect and return the available Qt module.

    Returns:
        module: The Qt module (PyQt5, PyQt6, PySide2, or PySide6).

    Raises:
        ImportError: If no Qt binding is found.
    """
    # Check if any Qt module is already imported
    for module_name in ["PyQt6", "PyQt5", "PySide6", "PySide2"]:
        if module_name in sys.modules:
            return sys.modules[module_name]

    # Try to import in order of preference
    for module_name in ["PyQt6", "PyQt5", "PySide6", "PySide2"]:
        try:
            return __import__(module_name)
        except ImportError:
            continue

    raise ImportError(
        "No Qt binding found. Please install one of: "
        "PyQt5, PyQt6, PySide2, or PySide6"
    )


def load_resources() -> bool:
    """
    Load the Qt resource files (icons) into the application.

    This function compiles and registers the .qrc resource files,
    making icons available via the Qt resource system (e.g., ":/BASE/base/icon.svg").

    Returns:
        bool: True if resources were loaded successfully, False otherwise.

    Note:
        This function is called automatically when using apply() or get_icon().
        You only need to call it manually if you want to use the resource system
        directly without using the helper functions.

    Example:
        >>> import qt_modern_style
        >>> qt_modern_style.load_resources()
        >>> # Now you can use resources like ":/BASE/base/settings.svg"
    """
    global _resources_loaded

    if _resources_loaded:
        return True

    try:
        # Import the compiled resources module
        from . import resources_rc

        _resources_loaded = True
        return True
    except ImportError:
        # Resources module not compiled, try to compile it
        try:
            _compile_resources()
            from . import resources_rc

            _resources_loaded = True
            return True
        except Exception as e:
            print(f"Warning: Could not load Qt resources: {e}")
            return False


def _compile_resources():
    """
    Compile the .qrc files to Python resource modules.

    This is a helper function that attempts to compile resources using
    the appropriate Qt tool.
    """
    try:
        qt_module = _get_qt_module()
        module_name = qt_module.__name__

        # Determine the resource compiler command
        if module_name in ["PyQt5", "PyQt6"]:
            import subprocess

            rcc_name = "pyrcc5" if module_name == "PyQt5" else "pyside6-rcc"

            # For PyQt, we use pyrcc5 or pyrcc6
            try:
                if module_name == "PyQt5":
                    from PyQt5 import pyrcc_main

                    pyrcc_main.processResourceFile(
                        [str(_ICONS_DIR / "resources.qrc")],
                        str(_PACKAGE_DIR / "resources_rc.py"),
                        False,
                    )
                else:
                    # PyQt6 doesn't have pyrcc, need to use rcc directly
                    pass
            except ImportError:
                pass

        elif module_name in ["PySide2", "PySide6"]:
            # PySide has built-in resource compilation
            pass

    except Exception:
        pass


def apply(app, load_icons: bool = True) -> None:
    """
    Apply the modern style to a Qt application.

    This function sets the stylesheet and optionally loads the icon resources.

    Args:
        app: The QApplication instance.
        load_icons: Whether to load icon resources. Defaults to True.

    Example:
        >>> from PyQt5.QtWidgets import QApplication
        >>> import qt_modern_style
        >>>
        >>> app = QApplication([])
        >>> qt_modern_style.apply(app)
        >>>
        >>> # Your application code here
        >>> app.exec_()
    """
    # Load resources if requested
    if load_icons:
        load_resources()

    # Apply the stylesheet
    stylesheet = get_stylesheet()
    app.setStyleSheet(stylesheet)


def get_icon_path(icon_name: str, category: str = "base") -> Optional[Path]:
    """
    Get the file path to an icon.

    Args:
        icon_name: The name of the icon (with or without .svg extension).
        category: The icon category ("base" or "assets"). Defaults to "base".

    Returns:
        Path: The path to the icon file, or None if not found.

    Example:
        >>> import qt_modern_style
        >>> path = qt_modern_style.get_icon_path("settings")
        >>> print(path)
        >>> # /path/to/qt_modern_style/icons/base/settings.svg
    """
    # Ensure .svg extension
    if not icon_name.endswith(".svg"):
        icon_name = f"{icon_name}.svg"

    # Determine the icon directory
    if category == "assets":
        icon_dir = _ASSETS_ICONS_DIR
    else:
        icon_dir = _BASE_ICONS_DIR

    icon_path = icon_dir / icon_name

    if icon_path.exists():
        return icon_path

    # Try the other category if not found
    other_dir = _ASSETS_ICONS_DIR if category == "base" else _BASE_ICONS_DIR
    other_path = other_dir / icon_name

    if other_path.exists():
        return other_path

    return None


def get_icon(icon_name: str, category: str = "base"):
    """
    Get a QIcon for the specified icon name.

    Args:
        icon_name: The name of the icon (with or without .svg extension).
        category: The icon category ("base" or "assets"). Defaults to "base".

    Returns:
        QIcon: A QIcon object, or an empty QIcon if the icon is not found.

    Example:
        >>> from PyQt5.QtWidgets import QPushButton
        >>> import qt_modern_style
        >>>
        >>> button = QPushButton()
        >>> button.setIcon(qt_modern_style.get_icon("save"))
    """
    qt_module = _get_qt_module()

    # Import QIcon from the appropriate module
    if qt_module.__name__ == "PyQt5":
        from PyQt5.QtGui import QIcon
    elif qt_module.__name__ == "PyQt6":
        from PyQt6.QtGui import QIcon
    elif qt_module.__name__ == "PySide2":
        from PySide2.QtGui import QIcon
    elif qt_module.__name__ == "PySide6":
        from PySide6.QtGui import QIcon
    else:
        raise ImportError("Unsupported Qt binding")

    # Get the icon path
    icon_path = get_icon_path(icon_name, category)

    if icon_path:
        return QIcon(str(icon_path))

    # Return empty icon if not found
    return QIcon()


def list_base_icons() -> List[str]:
    """
    List all available base icons.

    Returns:
        List[str]: A list of icon names (without .svg extension).

    Example:
        >>> import qt_modern_style
        >>> base_icons = qt_modern_style.list_base_icons()
        >>> print(len(base_icons))
    """
    icons = []
    if _BASE_ICONS_DIR.exists():
        for file in _BASE_ICONS_DIR.iterdir():
            if file.suffix.lower() == ".svg":
                icons.append(file.stem)
    return sorted(icons)


def list_asset_icons() -> List[str]:
    """
    List all available asset icons.

    Returns:
        List[str]: A list of icon names (without .svg extension).

    Example:
        >>> import qt_modern_style
        >>> asset_icons = qt_modern_style.list_asset_icons()
        >>> print(asset_icons)
    """
    icons = []
    if _ASSETS_ICONS_DIR.exists():
        for file in _ASSETS_ICONS_DIR.iterdir():
            if file.suffix.lower() == ".svg":
                icons.append(file.stem)
    return sorted(icons)


def list_icons() -> List[str]:
    """
    List all available icons (both base and asset icons).

    Returns:
        List[str]: A sorted list of all icon names (without .svg extension).

    Example:
        >>> import qt_modern_style
        >>> all_icons = qt_modern_style.list_icons()
        >>> print(f"Total icons: {len(all_icons)}")
        >>> for icon in all_icons[:10]:
        ...     print(icon)
    """
    base_icons = set(list_base_icons())
    asset_icons = set(list_asset_icons())
    return sorted(base_icons | asset_icons)
