# -*- coding: utf-8 -*-
# gui/components/button.py

from PySide6.QtWidgets import QPushButton, QSizePolicy
from PySide6.QtCore import Slot, QSize
from PySide6.QtGui import QIcon
from gui.theme_bus import theme_bus
from gui.containers.s_container import SContainer  # Импортируем кастомный контейнер
from gui.styles import APP_STYLES
 
class Button(SContainer):
    """Навигационная кнопка на основе кастомного контейнера SContainer."""
    
    def __init__(self, text: str, index: int = 0, **kwargs):
        # Извлекаем параметры для передачи в SContainer
        width_percent = kwargs.get("width_percent", None)
        height_percent = kwargs.get("height_percent", None)
        margin = kwargs.get("margin", [0, 2, 0, 2])
        style = kwargs.get("style", None)
        active_style = kwargs.get("active_style", None)
        is_active = kwargs.get("is_active", None)
        content_fit = kwargs.get("content_fit", True)
        parent = kwargs.get("parent", None)

        # Вызываем конструктор SContainer с параметрами
        super().__init__(
            width_percent=width_percent,
            height_percent=height_percent,
            margin=margin,
            style=style,
            active_style=active_style,
            is_active=is_active,
            content_fit=content_fit,
            parent=parent,
        )
        
        self.index = index
        self._theme = "dark"
        self._is_active = False
        self._style_key_normal = None
        self._style_key_active = None
        
        # Создаем кнопку
        self._button = QPushButton(text)
        self._button.setProperty("widget_index", index)
        
        # Добавляем кнопку в layout контейнера
        super().add_widget(self._button)
        
        # Настраиваем кнопку для заполнения всего доступного пространства
        self._button.setSizePolicy(
            QSizePolicy.Policy.Expanding,
            QSizePolicy.Policy.Expanding
        )
        
        # Флаг для отслеживания первого обновления
        self._initial_update_done = False
        
        if style is not None:
            self._style_key_normal = style
            self._style_key_active = active_style or style
        if is_active is not None:
            self._is_active = bool(is_active)

        self._theme = "dark" if self.palette().window().color().lightness() < 128 else "light"
        self.style()
        theme_bus.theme_changed.connect(self.set_theme)

        # Иконка (опционально): путь к PNG + размер иконки внутри кнопки.
        # Размер иконки — это свойство QPushButton (QSize), а не layout-геометрия;
        # правило 6.7 (запрет fixed-size) распространяется на разметку, не на иконки.
        icon_path = kwargs.get("icon_path", None)
        icon_size = kwargs.get("icon_size", 16)
        if icon_path:
            self._button.setIcon(QIcon(str(icon_path)))
            self._button.setIconSize(QSize(int(icon_size), int(icon_size)))

    def style(
        self,
        style_key: str | None = None,
        active_key: str | None = None,
        is_active: bool | None = None,
    ):
        """Короткий метод применения стиля. Можно задать ключи и активность явно."""
        if style_key is not None:
            self._style_key_normal = style_key
            self._style_key_active = active_key or style_key

        if is_active is not None:
            self._is_active = bool(is_active)

        if self._style_key_normal is not None:
            active_key = self._style_key_active or self._style_key_normal
            key = active_key if self._is_active else self._style_key_normal
            themed = f"{key}_{self._theme.upper()}"
            if themed in APP_STYLES:
                key = themed
            self._button.setStyleSheet(APP_STYLES.get(key, ""))
            return

        if self._theme == "light":
            if self._is_active and "STANDARD_BUTTON_LIGHT_THEME_ACTIVE" in APP_STYLES:
                self._button.setStyleSheet(APP_STYLES["STANDARD_BUTTON_LIGHT_THEME_ACTIVE"])
            else:
                self._button.setStyleSheet(APP_STYLES["STANDARD_BUTTON_LIGHT_THEME"])
            return

        if self._is_active:
            self._button.setStyleSheet(APP_STYLES["STANDARD_BUTTON_DARK_THEME_ACTIVE"])
        else:
            self._button.setStyleSheet(APP_STYLES["STANDARD_BUTTON_DARK_THEME"])

    @Slot(str)
    def set_theme(self, theme: str):
        """Внешний слот: принимает 'dark' или 'light'."""
        theme = (theme or "").strip().lower()
        if theme not in ("dark", "light"):
            return # игнорируем ошибочные значения

        if self._theme == theme:
            return

        self._theme = theme
        self.style()
    
    # Делегируем clicked сигнал и другие методы внутренней кнопке
    @property
    def clicked(self):
        return self._button.clicked

    @property
    def toggled(self):
        return self._button.toggled

    def click(self):
        self._button.click()

    def set_text(self, text: str):
        self._button.setText(text)

    def get_text(self) -> str:
        return self._button.text()

    def set_tooltip(self, text: str):
        self._button.setToolTip(text)

    def get_tooltip(self) -> str:
        return self._button.toolTip()

    def set_checkable(self, checkable: bool):
        self._button.setCheckable(checkable)

    def set_checked(self, checked: bool):
        self._button.setChecked(checked)

    def is_checked(self) -> bool:
        return self._button.isChecked()

    def set_enabled(self, enabled: bool):
        self._button.setEnabled(enabled)
        super().setEnabled(enabled)

    def set_min_width(self, width: int) -> None:
        self._button.setMinimumWidth(width)
        super().setMinimumWidth(width)

    def set_min_height(self, height: int) -> None:
        self._button.setMinimumHeight(height)
        super().setMinimumHeight(height)

    def set_max_width(self, width: int) -> None:
        self._button.setMaximumWidth(width)
        super().setMaximumWidth(width)

    def set_max_height(self, height: int) -> None:
        self._button.setMaximumHeight(height)
        super().setMaximumHeight(height)

    def set_fixed_size(self, width: int, height: int) -> None:
        self._button.setMinimumSize(width, height)
        self._button.setMaximumSize(width, height)
        super().setMinimumSize(width, height)
        super().setMaximumSize(width, height)

    def set_font(self, font):
        self._button.setFont(font)

    def set_property(self, name: str, value):
        super().setProperty(name, value)
        self._button.setProperty(name, value)

    def set_size_policy(self, horizontal, vertical) -> None:
        self._button.setSizePolicy(horizontal, vertical)
        super().setSizePolicy(horizontal, vertical)

    # Переопределяем add_widget, чтобы предотвратить добавление других виджетов
    def add_widget(self, widget, alignment=None):
        raise NotImplementedError("Button может содержать только одну кнопку")






# ---------------------------------------------------------------------------
# Module workflow notes
# ---------------------------------------------------------------------------
#
# 1) Назначение модуля:
#    Навигационная/функциональная кнопка, реализованная как запечатанный
#    контейнер SContainer с одной внутренней QPushButton, поддерживающая
#    централизованные стили APP_STYLES и автоматическое переключение
#    тем (dark/light) через theme_bus.
#
# 2) Зависимости модуля:
#    Импорты: QPushButton, QSizePolicy (PySide6.QtWidgets),
#             Slot (PySide6.QtCore),
#             theme_bus (gui.theme_bus),
#             SContainer (gui.containers.s_container),
#             APP_STYLES (gui.styles)
#    Хост-класс / базовый класс: SContainer
#    Внешние библиотеки: PySide6 (обязательна)
#
# 3) Экспорт:
#    Класс Button — публичный виджет-кнопка.
#    Основные методы: style(), set_theme(), set_text(), get_text(),
#    set_tooltip(), set_checkable(), set_checked(), is_checked(),
#    set_enabled(), set_min_width/height(), set_max_width/height(),
#    set_fixed_size(), set_font(), set_property(), set_size_policy(),
#    click().
#    Свойства: clicked, toggled (делегируют к внутренней QPushButton).
#
# 4) Состояние (поля):
#    index: int                — числовой индекс кнопки (для идентификации в группе)
#    _theme: str               — текущая тема ("dark" | "light")
#    _is_active: bool          — признак активного состояния
#    _style_key_normal: str|None — ключ стиля нормального состояния
#    _style_key_active: str|None — ключ стиля активного состояния
#    _button: QPushButton      — внутренний виджет кнопки
#    _initial_update_done: bool — флаг первого обновления
#
# 5) Последовательность действий и вызовов:
#    __init__(text, index, **kwargs)
#      -> super().__init__(...) — инициализация SContainer
#      -> QPushButton(text) — создание внутренней кнопки
#      -> super().add_widget(_button) — добавление в layout контейнера
#      -> style() — первичное применение стиля из APP_STYLES
#      -> theme_bus.theme_changed.connect(set_theme)
#    style(style_key?, active_key?, is_active?)
#      -> выбор ключа на основе _is_active + _theme
#      -> _button.setStyleSheet(APP_STYLES[key])
#    set_theme(theme: str)
#      -> _theme = theme -> style() — перерисовка стиля
#    clicked / toggled (properties)
#      -> делегируют к _button.clicked / _button.toggled
#
# 6) Побочные эффекты:
#    - Устанавливает stylesheet на внутреннюю QPushButton.
#    - Подключается к глобальному сигналу theme_bus.theme_changed при создании.
#
# 7) Границы ответственности:
#    Модуль НЕ управляет layout хоста, НЕ хранит бизнес-логику,
#    НЕ регистрирует обработчики кликов (это делает потребитель).
#    add_widget() заблокирован — кнопка содержит только QPushButton.
#
# 8) Обработка ошибок:
#    add_widget() бросает NotImplementedError при попытке добавить
#    дополнительный виджет. set_theme() молча игнорирует невалидные
#    значения темы.
#
# 9) Инварианты и контракты:
#    - Контейнер всегда содержит ровно одну QPushButton.
#    - _theme ∈ {"dark", "light"}.
#    - Если _style_key_normal задан, стиль определяется им; иначе —
#      используется стандартная пара STANDARD_BUTTON_*_THEME(_ACTIVE).
#
# 10) Правило сопровождения:
#     При добавлении новой темы — расширить ветку в style().
#     Не добавлять дочерние виджеты внутрь Button.
#     Новые делегирующие методы дублировать на _button и super().
