from __future__ import annotations
from PySide6.QtGui import QColor, QPainter, QPalette
from PySide6.QtWidgets import QStyledItemDelegate, QStyleOptionViewItem, QStyle
from PySide6.QtCore import QModelIndex, Qt


def _state_selected_flag():
    """Повертає коректний флаг 'selected' для різних версій PySide6.

    Важливо: **не** конвертуємо у int.
    У різних збірках PySide6 це може бути QStyle.StateFlag або QStyle.State,
    і вони коректно працюють у бітових операціях без приведення типів.
    """
    if hasattr(QStyle, "StateFlag") and hasattr(QStyle.StateFlag, "State_Selected"):
        return QStyle.StateFlag.State_Selected
    return getattr(QStyle, "State_Selected", 0)


def _state_mouseover_flag():
    """Повертає коректний флаг 'mouseover' для різних версій PySide6."""
    if hasattr(QStyle, "StateFlag") and hasattr(QStyle.StateFlag, "State_MouseOver"):
        return QStyle.StateFlag.State_MouseOver
    return getattr(QStyle, "State_MouseOver", 0)

def text_color_for_bg(bg: QColor) -> QColor:
    """Return readable text color for a given background color (used for selected rows)."""
    if not bg.isValid():
        return QColor("#374151")  # dark gray
    h, s, v, a = bg.getHsv()
    # green-ish backgrounds
    if 80 <= h <= 160 and s >= 15:
        return QColor("#0F5132")  # dark green
    # yellow-ish / amber backgrounds
    if 30 <= h < 80 and s >= 15:
        return QColor("#7C2D12")  # dark orange
    # white / gray / other
    return QColor("#374151")  # dark gray

class SelectionAwareTextDelegate(QStyledItemDelegate):
    """Ensure selected table rows keep readable colored text instead of default white."""
    def paint(self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex) -> None:
        opt = QStyleOptionViewItem(option)
        if opt.state & _state_selected_flag():
            bg = opt.palette.highlight().color()
            c = text_color_for_bg(bg)
            opt.palette.setColor(QPalette.ColorRole.Text, c)
            opt.palette.setColor(QPalette.ColorRole.HighlightedText, c)
        super().paint(painter, opt, index)

# Backward/forward compatible alias (some modules import the older name)
SelectionAwareTextColorDelegate = SelectionAwareTextDelegate


class ProjectStatusColorDelegate(QStyledItemDelegate):
    """Фарбування рядків у таблиці проєктів та м'яка заміна синього selection."""

    ROLE_BG_KEY = int(Qt.UserRole) + 10  # str: 'green'/'yellow'/'gray'/'white'

    def __init__(self, parent=None):
        super().__init__(parent)
        # Row index currently hovered by the mouse; used to darken the whole row.
        self._hover_row = -1

    def set_hover_row(self, row: int) -> None:
        self._hover_row = int(row) if row is not None else -1

    def _base_colors(self, key: str):
        key = (key or "").lower().strip()

        # Пастельні фони
        if key == "green":
            bg = QColor(210, 242, 220)
            fg_sel = QColor("#0F5132")  # темно-зелений
        elif key == "yellow":
            bg = QColor(255, 245, 205)
            fg_sel = QColor("#7C2D12")  # темно-оранжевий
        elif key == "red":
            bg = QColor(252, 232, 232)
            fg_sel = QColor("#7F1D1D")  # темно-червоний
        elif key == "gray":
            bg = QColor(235, 235, 235)
            fg_sel = QColor("#374151")  # темно-сірий
        else:
            bg = QColor(255, 255, 255)
            fg_sel = QColor("#374151")

        fg = QColor("#374151")
        return bg, fg, fg_sel

    def paint(self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex) -> None:
        opt = QStyleOptionViewItem(option)
        selected = bool(opt.state & _state_selected_flag())
        hovered_row = (self._hover_row == index.row())
        hovered_cell = bool(opt.state & _state_mouseover_flag())

        key = index.data(self.ROLE_BG_KEY) or "white"
        bg, fg, fg_sel = self._base_colors(str(key))

        if selected:
            # такий самий колір, але темніший/контрастніший
            bg = bg.darker(115)
            fg = fg_sel
        elif hovered_row or hovered_cell:
            # При наведенні — робимо фон більш контрастним. Бажано для *всього рядка*.
            bg = bg.darker(110)

        # Повністю замінюємо системний синій selection і примусово малюємо фон.
        # Важливо: деякі стилі ігнорують Base/Highlight для QTableView::item,
        # тому ми ще й заливаємо прямокутник вручну.
        opt.palette.setColor(QPalette.ColorRole.Base, bg)
        opt.palette.setColor(QPalette.ColorRole.Highlight, bg)
        opt.palette.setColor(QPalette.ColorRole.Text, fg)
        opt.palette.setColor(QPalette.ColorRole.HighlightedText, fg)

        painter.save()
        painter.fillRect(opt.rect, bg)
        painter.restore()

        # Щоб стиль не домалював поверх нашого фону свій highlight.
        if selected:
            try:
                opt.state = opt.state & ~_state_selected_flag()
            except Exception:
                pass

        super().paint(painter, opt, index)

class RowTintDelegate(QStyledItemDelegate):
    ROLE_BG_KEY = int(Qt.UserRole) + 11
    def __init__(self, parent=None):
        super().__init__(parent)
        self._hover_row = -1
    def set_hover_row(self, row: int) -> None:
        self._hover_row = row
    def _base(self, key: str):
        key=(key or 'white').lower()
        if key=='green':
            return QColor(210,242,220), QColor('#0F5132')
        if key=='yellow':
            return QColor(255,245,205), QColor('#7C2D12')
        if key=='red':
            return QColor(252,232,232), QColor('#7F1D1D')
        if key=='gray':
            return QColor(235,235,235), QColor('#374151')
        if key=='blue':
            return QColor(219, 234, 254), QColor('#1E3A8A')
        return QColor(255,255,255), QColor('#374151')
    def paint(self, painter, option, index):
        opt = QStyleOptionViewItem(option)
        selected = bool(opt.state & _state_selected_flag())
        hovered = self._hover_row == index.row() or bool(opt.state & _state_mouseover_flag())
        bg, fg = self._base(index.data(self.ROLE_BG_KEY) or 'white')
        if selected:
            bg = bg.darker(115)
        elif hovered:
            bg = bg.darker(108)
        painter.save(); painter.fillRect(opt.rect, bg); painter.restore()
        opt.palette.setColor(QPalette.ColorRole.Base, bg)
        opt.palette.setColor(QPalette.ColorRole.Highlight, bg)
        opt.palette.setColor(QPalette.ColorRole.Text, fg)
        opt.palette.setColor(QPalette.ColorRole.HighlightedText, fg)
        try:
            if selected:
                opt.state = opt.state & ~_state_selected_flag()
        except Exception:
            pass
        super().paint(painter, opt, index)
