# BMLibrarian Lite - Biomedical Literature Research Tool
# Copyright (C) 2024-2025 Dr Horst Herb
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

"""
Dynamic stylesheet generator with DPI-aware font-relative dimensions.

Provides utilities for generating Qt stylesheets with dimensions that
automatically scale based on system font settings.
"""

from typing import Dict, Optional
from .dpi_scale import FontScale, get_font_scale, FONT_FAMILY_MONOSPACE


class StylesheetGenerator:
    """
    Generate DPI-aware stylesheets with font-relative dimensions.

    All stylesheets generated by this class use dimensions calculated
    from system font metrics to ensure consistent appearance across
    different DPI settings.
    """

    def __init__(self, scale: Optional[Dict] = None):
        """
        Initialize stylesheet generator.

        Args:
            scale: Optional custom scale dictionary. If None, uses system font scale.
        """
        self.scale = scale if scale is not None else get_font_scale()
        self._s = self.scale  # Shorthand for templates

    def button_stylesheet(
        self,
        bg_color: str = "#2196F3",
        text_color: str = "white",
        hover_color: str = "#1976D2",
        disabled_bg: str = "#CCC",
        disabled_text: str = "#666",
        font_size_key: str = 'font_medium',
        padding_key: str = 'padding_small',
        radius_key: str = 'radius_small'
    ) -> str:
        """Generate button stylesheet with scaled dimensions."""
        s = self._s
        return f"""
            QPushButton {{
                background-color: {bg_color};
                color: {text_color};
                border-radius: {s[radius_key]}px;
                padding: {s[padding_key]}px;
                font-size: {s[font_size_key]}pt;
                font-weight: bold;
            }}
            QPushButton:hover {{
                background-color: {hover_color};
            }}
            QPushButton:disabled {{
                background-color: {disabled_bg};
                color: {disabled_text};
            }}
        """

    def input_stylesheet(
        self,
        font_size_key: str = 'font_medium',
        padding_key: str = 'padding_small',
        radius_key: str = 'radius_small',
        border_color: str = "#CCC",
        focus_color: str = "#2196F3"
    ) -> str:
        """Generate text input stylesheet with scaled dimensions."""
        s = self._s
        return f"""
            QTextEdit, QLineEdit {{
                border: 1px solid {border_color};
                border-radius: {s[radius_key]}px;
                padding: {s[padding_key]}px;
                font-size: {s[font_size_key]}pt;
            }}
            QTextEdit:focus, QLineEdit:focus {{
                border: 1px solid {focus_color};
            }}
        """

    def label_stylesheet(
        self,
        font_size_key: str = 'font_normal',
        color: str = "#333",
        bold: bool = False
    ) -> str:
        """Generate label stylesheet with scaled font."""
        s = self._s
        weight = "bold" if bold else "normal"
        return f"""
            QLabel {{
                font-size: {s[font_size_key]}pt;
                color: {color};
                font-weight: {weight};
            }}
        """

    def header_stylesheet(
        self,
        font_size_key: str = 'font_large',
        bg_color: str = "#E0E0E0",
        text_color: str = "#000",
        padding_h_key: str = 'padding_medium',
        padding_v_key: str = 'padding_small'
    ) -> str:
        """Generate header stylesheet with scaled dimensions."""
        s = self._s
        return f"""
            QLabel {{
                background-color: {bg_color};
                color: {text_color};
                padding: {s[padding_v_key]}px {s[padding_h_key]}px;
                font-weight: bold;
                font-size: {s[font_size_key]}pt;
            }}
        """

    def card_stylesheet(
        self,
        bg_color: str = "#FFFFFF",
        border_color: str = "#CCC",
        radius_key: str = 'radius_medium',
        padding_key: str = 'padding_medium'
    ) -> str:
        """Generate card/panel stylesheet with scaled dimensions."""
        s = self._s
        return f"""
            QFrame {{
                background-color: {bg_color};
                border: 1px solid {border_color};
                border-radius: {s[radius_key]}px;
                padding: {s[padding_key]}px;
            }}
        """

    def combo_stylesheet(
        self,
        font_size_key: str = 'font_small',
        padding_key: str = 'padding_small'
    ) -> str:
        """Generate combobox stylesheet with scaled dimensions."""
        s = self._s
        return f"""
            QComboBox {{
                font-size: {s[font_size_key]}pt;
                padding: {s[padding_key]}px;
            }}
        """

    def text_edit_stylesheet(
        self,
        bg_color: str = "#FAFAFA",
        text_color: str = "#212121",
        border_color: str = "#E0E0E0",
        focus_color: str = "#2196F3",
        radius_key: str = 'radius_small',
        padding_key: str = 'padding_small'
    ) -> str:
        """
        Generate QPlainTextEdit/QTextEdit stylesheet with scaled dimensions.

        Args:
            bg_color: Background color
            text_color: Text color
            border_color: Border color
            focus_color: Border color when focused
            radius_key: Scale key for border radius
            padding_key: Scale key for padding

        Returns:
            Formatted stylesheet string
        """
        s = self._s
        return f"""
            QPlainTextEdit, QTextEdit {{
                background-color: {bg_color};
                color: {text_color};
                border: 1px solid {border_color};
                border-radius: {s[radius_key]}px;
                padding: {s[padding_key]}px;
            }}
            QPlainTextEdit:focus, QTextEdit:focus {{
                border: 1px solid {focus_color};
            }}
        """

    def code_text_stylesheet(
        self,
        bg_color: str = "#f8f8f8",
        text_color: str = "#333",
        border_color: str = "#E0E0E0",
        focus_color: str = "#2196F3",
        radius_key: str = 'radius_small',
        padding_key: str = 'padding_small',
        font_size_key: str = 'font_small'
    ) -> str:
        """
        Generate monospace QPlainTextEdit stylesheet for code/JSON display.

        Uses cross-platform monospace fonts for consistent appearance.

        Args:
            bg_color: Background color
            text_color: Text color
            border_color: Border color
            focus_color: Border color when focused
            radius_key: Scale key for border radius
            padding_key: Scale key for padding
            font_size_key: Scale key for font size

        Returns:
            Formatted stylesheet string with monospace font
        """
        s = self._s
        return f"""
            QPlainTextEdit {{
                font-family: {FONT_FAMILY_MONOSPACE};
                font-size: {s[font_size_key]}pt;
                background-color: {bg_color};
                color: {text_color};
                border: 1px solid {border_color};
                border-radius: {s[radius_key]}px;
                padding: {s[padding_key]}px;
            }}
            QPlainTextEdit:focus {{
                border: 1px solid {focus_color};
            }}
        """

    def drag_handle_stylesheet(
        self,
        color: str = "#888",
        hover_color: str = "#444",
        font_size_key: str = 'font_medium',
        padding_key: str = 'padding_tiny'
    ) -> str:
        """Generate drag handle stylesheet with scaled dimensions.

        Args:
            color: Normal color for the handle
            hover_color: Color when hovered
            font_size_key: Scale key for font size
            padding_key: Scale key for padding

        Returns:
            Formatted stylesheet string
        """
        s = self._s
        return f"""
            QLabel {{
                color: {color};
                font-size: {s[font_size_key]}pt;
                padding: {s[padding_key]}px;
            }}
            QLabel:hover {{
                color: {hover_color};
            }}
        """

    def drop_indicator_stylesheet(
        self,
        color: str = "#2196F3",
        radius_key: str = 'radius_small'
    ) -> str:
        """Generate drop indicator stylesheet with scaled dimensions.

        Args:
            color: Background color for the indicator
            radius_key: Scale key for border radius

        Returns:
            Formatted stylesheet string
        """
        s = self._s
        return f"""
            QFrame {{
                background-color: {color};
                border-radius: {s[radius_key]}px;
            }}
        """

    def draggable_item_stylesheet(
        self,
        dragging_opacity: float = 0.5
    ) -> str:
        """Generate draggable item stylesheet.

        Args:
            dragging_opacity: Opacity when item is being dragged (0.0-1.0)

        Returns:
            Formatted stylesheet string for dragging state
        """
        # Note: Qt stylesheet doesn't support opacity directly on QFrame,
        # but we can use background-color with alpha
        return f"""
            QFrame {{
                background-color: rgba(200, 200, 200, {int(dragging_opacity * 255)});
            }}
        """

    def custom(self, template: str) -> str:
        """
        Generate custom stylesheet with access to all scale values.

        Args:
            template: String template with {scale_key} placeholders

        Returns:
            Formatted stylesheet with scale values substituted

        Example:
            >>> gen = StylesheetGenerator()
            >>> gen.custom('''
            ...     QWidget {{
            ...         font-size: {font_medium}pt;
            ...         padding: {padding_large}px;
            ...     }}
            ... ''')
        """
        return template.format(**self._s)

    def generate(self) -> str:
        """
        Generate a complete application stylesheet.

        Combines common styles for buttons, inputs, labels, and other
        widgets into a single stylesheet suitable for application-wide use.

        Returns:
            Complete stylesheet string for the application
        """
        s = self._s
        return f"""
            /* Base application styles */
            QMainWindow, QWidget {{
                font-size: {s['font_normal']}pt;
            }}

            /* Buttons */
            QPushButton {{
                background-color: #2196F3;
                color: white;
                border-radius: {s['radius_small']}px;
                padding: {s['padding_small']}px {s['padding_medium']}px;
                font-size: {s['font_normal']}pt;
                font-weight: bold;
                border: none;
            }}
            QPushButton:hover {{
                background-color: #1976D2;
            }}
            QPushButton:pressed {{
                background-color: #0D47A1;
            }}
            QPushButton:disabled {{
                background-color: #BDBDBD;
                color: #757575;
            }}

            /* Text inputs */
            QLineEdit, QTextEdit, QPlainTextEdit {{
                border: 1px solid #BDBDBD;
                border-radius: {s['radius_small']}px;
                padding: {s['padding_small']}px;
                font-size: {s['font_normal']}pt;
                background-color: white;
            }}
            QLineEdit:focus, QTextEdit:focus, QPlainTextEdit:focus {{
                border: 1px solid #2196F3;
            }}

            /* Labels */
            QLabel {{
                font-size: {s['font_normal']}pt;
            }}

            /* Group boxes */
            QGroupBox {{
                font-weight: bold;
                font-size: {s['font_normal']}pt;
                border: 1px solid #E0E0E0;
                border-radius: {s['radius_small']}px;
                margin-top: {s['spacing_large']}px;
                padding-top: {s['padding_medium']}px;
            }}
            QGroupBox::title {{
                subcontrol-origin: margin;
                left: {s['padding_medium']}px;
                padding: 0 {s['padding_small']}px;
            }}

            /* Combo boxes */
            QComboBox {{
                font-size: {s['font_normal']}pt;
                padding: {s['padding_small']}px;
                border: 1px solid #BDBDBD;
                border-radius: {s['radius_small']}px;
            }}

            /* Spin boxes */
            QSpinBox, QDoubleSpinBox {{
                font-size: {s['font_normal']}pt;
                padding: {s['padding_small']}px;
                border: 1px solid #BDBDBD;
                border-radius: {s['radius_small']}px;
            }}

            /* Progress bars */
            QProgressBar {{
                border: 1px solid #BDBDBD;
                border-radius: {s['radius_small']}px;
                text-align: center;
                font-size: {s['font_small']}pt;
            }}
            QProgressBar::chunk {{
                background-color: #2196F3;
                border-radius: {s['radius_small']}px;
            }}

            /* Tab widgets */
            QTabWidget::pane {{
                border: 1px solid #E0E0E0;
                border-radius: {s['radius_small']}px;
            }}
            QTabBar::tab {{
                font-size: {s['font_normal']}pt;
                padding: {s['padding_small']}px {s['padding_medium']}px;
                border: 1px solid #E0E0E0;
                border-bottom: none;
                border-top-left-radius: {s['radius_small']}px;
                border-top-right-radius: {s['radius_small']}px;
            }}
            QTabBar::tab:selected {{
                background-color: white;
            }}
            QTabBar::tab:!selected {{
                background-color: #F5F5F5;
            }}

            /* Scroll areas */
            QScrollArea {{
                border: none;
            }}

            /* Status bar */
            QStatusBar {{
                font-size: {s['font_small']}pt;
            }}
        """


# Convenience functions for common stylesheet patterns

def get_stylesheet_generator(scale: Optional[Dict] = None) -> StylesheetGenerator:
    """
    Get a StylesheetGenerator instance.

    Args:
        scale: Optional custom scale dictionary

    Returns:
        StylesheetGenerator instance
    """
    return StylesheetGenerator(scale)


def apply_button_style(
    widget,
    bg_color: str = "#2196F3",
    text_color: str = "white",
    hover_color: str = "#1976D2"
) -> None:
    """
    Apply DPI-aware button stylesheet to a widget.

    Args:
        widget: Qt widget to style
        bg_color: Background color
        text_color: Text color
        hover_color: Hover background color
    """
    gen = StylesheetGenerator()
    widget.setStyleSheet(gen.button_stylesheet(bg_color, text_color, hover_color))


def apply_input_style(widget) -> None:
    """
    Apply DPI-aware input stylesheet to a widget.

    Args:
        widget: Qt text input widget to style
    """
    gen = StylesheetGenerator()
    widget.setStyleSheet(gen.input_stylesheet())


def apply_header_style(
    widget,
    bg_color: str = "#E0E0E0",
    text_color: str = "#000"
) -> None:
    """
    Apply DPI-aware header stylesheet to a widget.

    Args:
        widget: Qt label widget to style as header
        bg_color: Background color
        text_color: Text color
    """
    gen = StylesheetGenerator()
    widget.setStyleSheet(gen.header_stylesheet(bg_color=bg_color, text_color=text_color))
