from __future__ import annotations
from typing import Callable, Optional

from PySide6.QtCore import Qt, QEvent
from PySide6.QtWidgets import (
    QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton,
    QTableWidget, QTableWidgetItem, QLineEdit, QHeaderView, QAbstractItemView,
    QMessageBox,
)

from mi100.repository import Repo
from mi100.ui.delegates import RowTintDelegate


class VoiceActorsPage(QWidget):
    def __init__(self, repo: Repo, open_right_panel: Callable[[QWidget, str], None]):
        super().__init__()
        self.repo = repo
        self.open_right_panel = open_right_panel
        self._debtors_only = False
        self._build_ui()
        self.refresh()

    def _build_ui(self):
        root = QVBoxLayout(self)
        root.setContentsMargins(12, 12, 12, 12)
        root.setSpacing(10)

        header = QHBoxLayout()

        self.search = QLineEdit()
        self.search.setPlaceholderText("Пошук підрядника")
        self.search.textChanged.connect(lambda _=None: self.refresh())
        header.addWidget(self.search, 1)

        self.btn_toggle_debtors = QPushButton("Показати неоплачених")
        self.btn_toggle_debtors.setObjectName("Primary")
        self.btn_toggle_debtors.clicked.connect(self._toggle_debtors)
        header.addWidget(self.btn_toggle_debtors)

        self.btn_add = QPushButton("＋")
        self.btn_add.setFixedSize(32, 32)
        self.btn_add.setObjectName("Primary")
        f = self.btn_add.font()
        f.setPointSize(max(12, f.pointSize()))
        self.btn_add.setFont(f)
        self.btn_add.clicked.connect(self._create_voice_actor)
        header.addWidget(self.btn_add)

        root.addLayout(header)

        self.table = QTableWidget()
        self.table.setColumnCount(4)
        self.table.setHorizontalHeaderLabels(["Ім'я", "Телефон", "Email", "Борг"])
        self.table.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(3, QHeaderView.ResizeToContents)
        self.table.verticalHeader().setVisible(False)
        self.table.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
        self.table.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
        self.table.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)

        self._row_delegate = RowTintDelegate(self.table)
        self.table.setItemDelegate(self._row_delegate)
        self.table.setMouseTracking(True)
        self.table.cellEntered.connect(self._on_hover_cell)
        self.table.viewport().installEventFilter(self)
        self.table.cellClicked.connect(self._on_clicked)

        root.addWidget(self.table, 1)
        self._apply_debtors_button_style()

    def eventFilter(self, obj, event):
        if obj is self.table.viewport() and event.type() == QEvent.Type.Leave:
            self._row_delegate.set_hover_row(-1)
            self.table.viewport().update()
        return super().eventFilter(obj, event)

    def _on_hover_cell(self, row: int, _col: int):
        self._row_delegate.set_hover_row(row)
        self.table.viewport().update()

    def _apply_debtors_button_style(self) -> None:
        if self._debtors_only:
            self.btn_toggle_debtors.setText("Показати всіх")
            self.btn_toggle_debtors.setStyleSheet(
                "QPushButton{background:#FFF5CD;border:1px solid #E6D39A;border-radius:4px;padding:6px 10px;}"
                "QPushButton:hover{background:#F2E8BC;}"
            )
        else:
            self.btn_toggle_debtors.setText("Показати неоплачених")
            self.btn_toggle_debtors.setStyleSheet("")

    def _toggle_debtors(self):
        self._debtors_only = not self._debtors_only
        self._apply_debtors_button_style()
        self.refresh()

    def refresh(self, select_voice_actor_id: int | None = None):
        rows = list(self.repo.list_voice_actors(include_inactive=True))

        def field(row, key, default=""):
            try:
                value = row[key]
            except Exception:
                value = default
            return default if value is None else value

        q = (self.search.text().strip().lower() if hasattr(self, "search") and self.search is not None else "")
        if q:
            filtered = []
            for va in rows:
                hay = " ".join([
                    str(field(va, "display_name", "")),
                    str(field(va, "first_name", "")),
                    str(field(va, "last_name", "")),
                    str(field(va, "phone", "")),
                    str(field(va, "email", "")),
                ]).lower()
                if q in hay:
                    filtered.append(va)
            rows = filtered

        def debt_of(va):
            try:
                return int(field(va, "debt_to_actor", 0) or 0)
            except Exception:
                return 0

        if self._debtors_only:
            rows = [va for va in rows if debt_of(va) > 0]
        else:
            rows = sorted(
                rows,
                key=lambda va: (0 if debt_of(va) > 0 else 1, str(field(va, "display_name", "")).lower())
            )

        self.table.setRowCount(len(rows))
        for r, va in enumerate(rows):
            vid = int(field(va, "id", 0))
            debt = debt_of(va)
            vals = [
                str(field(va, "display_name", "") or f"ID {vid}"),
                str(field(va, "phone", "")),
                str(field(va, "email", "")),
                str(va.get('debt_display') or debt),
            ]
            for c, text in enumerate(vals):
                it = QTableWidgetItem(text)
                if c == 0:
                    it.setData(Qt.UserRole, vid)
                if c == 3:
                    it.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
                key = "green" if debt > 0 else "white"
                it.setData(RowTintDelegate.ROLE_BG_KEY, key)
                self.table.setItem(r, c, it)

            if debt > 0 and self.table.item(r, 3):
                f = self.table.item(r, 3).font()
                f.setBold(True)
                self.table.item(r, 3).setFont(f)

        self.table.resizeRowsToContents()

        if select_voice_actor_id is not None:
            for r in range(self.table.rowCount()):
                item = self.table.item(r, 0)
                if item and int(item.data(Qt.UserRole) or 0) == int(select_voice_actor_id):
                    self.table.selectRow(r)
                    break

    def _selected_voice_actor_id(self) -> Optional[int]:
        items = self.table.selectedItems()
        if not items:
            return None
        vid = items[0].data(Qt.UserRole)
        return int(vid) if vid else None

    def _on_clicked(self, row: int, col: int):
        item = self.table.item(row, 0)
        if not item:
            return
        vid = item.data(Qt.UserRole)
        if vid:
            self._open_voice_actor(int(vid))

    def _open_voice_actor(self, voice_actor_id: int):
        from mi100.ui.voice_actor_detail import VoiceActorDetail

        view = VoiceActorDetail(
            repo=self.repo,
            voice_actor_id=voice_actor_id,
            on_saved=self._on_voice_actor_saved,
            on_deleted=self._on_voice_actor_deleted,
        )
        self.open_right_panel(view, view.ed_name.text() if hasattr(view, "ed_name") else "")

    def _create_voice_actor(self):
        from mi100.ui.voice_actor_detail import VoiceActorDetail

        view = VoiceActorDetail(
            repo=self.repo,
            voice_actor_id=None,
            on_saved=self._on_voice_actor_saved,
            on_deleted=self._on_voice_actor_deleted,
        )
        self.open_right_panel(view, "")

    def _on_voice_actor_saved(self, voice_actor_id: int):
        self.refresh(select_voice_actor_id=voice_actor_id)

    def _on_voice_actor_deleted(self, voice_actor_id: int):
        self.refresh()