# -*- coding: utf-8 -*-
# gui/components/label.py
"""Стандартный компонент метки."""

from PySide6.QtWidgets import QLabel, QSizePolicy
from PySide6.QtCore import Qt, Slot

from gui.containers.s_container import SContainer
from gui.styles import APP_STYLES
from gui.theme_bus import theme_bus


class Label(SContainer):
    """Стандартная метка с выбором стиля по теме внутри SContainer."""

    _ALIGN_MAP = {
        "top": Qt.AlignmentFlag.AlignTop,
        "bottom": Qt.AlignmentFlag.AlignBottom,
        "left": Qt.AlignmentFlag.AlignLeft,
        "right": Qt.AlignmentFlag.AlignRight,
        "hcenter": Qt.AlignmentFlag.AlignHCenter,
        "vcenter": Qt.AlignmentFlag.AlignVCenter,
        "center": Qt.AlignmentFlag.AlignCenter,
    }

    def __init__(self, text: str = "", **kwargs):
        width_percent = kwargs.get("width_percent", None)
        height_percent = kwargs.get("height_percent", None)
        margin = kwargs.get("margin", 0)
        alignment = kwargs.get("alignment", Qt.AlignCenter)
        style = kwargs.get("style", "WIDGET_LABEL")
        active_style = kwargs.get("active_style", None)
        is_active = kwargs.get("is_active", None)
        content_fit = kwargs.get("content_fit", True)
        word_wrap = kwargs.get("word_wrap", False)
        parent = kwargs.get("parent", None)

        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._theme = "dark"
        self._is_active: bool = False
        self._base_style_key = style
        self._style_key_normal = None
        self._style_key_active = None

        self._label = QLabel(text)
        self._apply_alignment(alignment)
        if word_wrap:
            self._label.setWordWrap(True)
            self._label.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred)
        else:
            self._label.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
        super().add_widget(self._label)

        if active_style is not None:
            self._style_key_normal = style
            self._style_key_active = active_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)

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

        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._label.setStyleSheet(APP_STYLES.get(key, ""))
            return

        base_key = self._base_style_key
        key = base_key

        if self._theme == "light":
            if self._is_active and f"{base_key}_LIGHT_ACTIVE" in APP_STYLES:
                key = f"{base_key}_LIGHT_ACTIVE"
            elif f"{base_key}_LIGHT" in APP_STYLES:
                key = f"{base_key}_LIGHT"
        else:
            if self._is_active and f"{base_key}_DARK_ACTIVE" in APP_STYLES:
                key = f"{base_key}_DARK_ACTIVE"
            elif f"{base_key}_DARK" in APP_STYLES:
                key = f"{base_key}_DARK"

        self._label.setStyleSheet(APP_STYLES.get(key, ""))

    @Slot(str)
    def set_theme(self, theme: str) -> None:
        """Внешний слот: принимает 'dark' или 'light'."""
        theme = (theme or "").strip().lower()
        if theme not in ("dark", "light"):
            return
        if self._theme == theme:
            return
        self._theme = theme
        self.style()

    def set_text(self, text: str) -> None:
        self._label.setText(text)

    def set_pixmap(self, pixmap) -> None:
        self._label.setPixmap(pixmap)

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

    def _apply_alignment(self, alignment) -> None:
        """Внутренний метод применения alignment с поддержкой строк."""
        if isinstance(alignment, str):
            key = alignment.strip().lower()
            alignment = self._ALIGN_MAP.get(key)
            if alignment is None:
                raise ValueError(f"Unknown alignment '{key}'. Allowed: {list(self._ALIGN_MAP.keys())}")
        self._label.setAlignment(alignment)

    def set_alignment(self, alignment: str | Qt.Alignment) -> None:
        """Установить выравнивание текста (строка или Qt.Alignment)."""
        self._apply_alignment(alignment)

    def set_word_wrap(self, enabled: bool) -> None:
        """Включить / выключить перенос текста по словам."""
        self._label.setWordWrap(enabled)
        if enabled:
            self._label.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred)

    def set_enabled(self, enabled: bool) -> None:
        self._label.setEnabled(enabled)
        super().setEnabled(enabled)

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

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

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

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

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

    def set_tooltip(self, text: str) -> None:
        self._label.setToolTip(text)

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

    def add_widget(self, widget, alignment=None):
        raise NotImplementedError("Label can contain only one QLabel")






# ---------------------------------------------------------------------------
# Module workflow notes
# ---------------------------------------------------------------------------
#
# 1) Назначение модуля:
#    Стандартная текстовая метка в SContainer с поддержкой
#    централизованных стилей APP_STYLES, темизации и строкового
#    выравнивания.
#
# 2) Зависимости модуля:
#    Импорты: QLabel, QSizePolicy (PySide6.QtWidgets),
#             Qt, Slot (PySide6.QtCore),
#             SContainer (gui.containers.s_container),
#             APP_STYLES (gui.styles),
#             theme_bus (gui.theme_bus)
#    Хост-класс / базовый класс: SContainer
#    Внешние библиотеки: PySide6 (обязательна)
#
# 3) Экспорт:
#    Класс Label — публичный виджет метки.
#    Методы: style(), set_theme(), set_text(), get_text(),
#            set_alignment(), set_enabled(),
#            set_min/max_width/height(), set_fixed_size(),
#            set_tooltip(), set_size_policy().
#
# 4) Состояние (поля):
#    _theme: str                 — текущая тема
#    _is_active: bool            — признак активного состояния
#    _base_style_key: str        — базовый ключ стиля ("WIDGET_LABEL")
#    _style_key_normal: str|None — явный нормальный стиль
#    _style_key_active: str|None — явный активный стиль
#    _label: QLabel              — внутренний виджет метки
#    _ALIGN_MAP: dict            — маппинг строк → Qt.Alignment
#
# 5) Последовательность действий и вызовов:
#    __init__(text="", **kwargs)
#      -> извлечение параметров из kwargs
#      -> super().__init__(...)
#      -> QLabel(text) -> _apply_alignment -> setSizePolicy
#      -> super().add_widget(_label)
#      -> style() -> theme_bus.theme_changed.connect(set_theme)
#    _apply_alignment(alignment)
#      -> если str → маппинг через _ALIGN_MAP → _label.setAlignment()
#      -> если Qt.Alignment → прямое применение
#      -> ValueError при невалидной строке
#
# 6) Побочные эффекты:
#    - Устанавливает stylesheet на QLabel.
#    - Подключается к theme_bus.theme_changed.
#
# 7) Границы ответственности:
#    Модуль НЕ поддерживает rich-text/HTML самостоятельно (хотя QLabel
#    может). НЕ обрабатывает клики. add_widget() заблокирован.
#
# 8) Обработка ошибок:
#    add_widget() бросает NotImplementedError.
#    _apply_alignment() бросает ValueError при невалидной строке.
#    set_theme() молча игнорирует невалидные значения.
#
# 9) Инварианты и контракты:
#    - Контейнер содержит ровно один QLabel.
#    - _theme ∈ {"dark", "light"}.
#    - Стиль: явный ключ → base_key + суффикс.
#
# 10) Правило сопровождения:
#     Для новых стилей — добавлять в APP_STYLES с суффиксами
#     _DARK/_LIGHT + _ACTIVE. __init__ принимает **kwargs —
#     при добавлении новых параметров обновлять извлечение.
