# -*- coding: utf-8 -*-
"""通用小组件：资产卡片、类型徽章、标签 chips、空状态、分页。

被网格视图、列表视图、详情面板共享，集中定义避免重复。
"""
from __future__ import annotations

from PySide6.QtCore import Qt, Signal
from PySide6.QtGui import QPixmap
from PySide6.QtWidgets import (
    QFrame, QHBoxLayout, QLabel, QPushButton, QVBoxLayout, QWidget,
)

from .. import thumbnail as thumb_mod
from ..models import Asset
from .theme import (
    BG_CARD,
    BG_HOVER,
    BG_INPUT,
    BG_PANEL,
    BORDER,
    BORDER_LIGHT,
    FG,
    FG_DIM,
    FG_FAINT,
    RADIUS,
)


# ---------------------------------------------------------------------------
# 资产卡片（网格视图用）
# ---------------------------------------------------------------------------
class AssetCard(QFrame):
    """网格视图中的一个资产卡片：缩略图/类型图标 + 标题 + 元信息 + 类型色条。"""

    selected = Signal(int)
    doubleClicked = Signal(int)

    CARD_H = 172
    CARD_W = 150

    def __init__(self, asset: Asset, thumb_root=None, parent=None):
        super().__init__(parent)
        self.asset = asset
        self.thumb_root = thumb_root
        self.setFrameShape(QFrame.Shape.StyledPanel)
        self.setObjectName("Card")
        self.setFixedSize(self.CARD_W, self.CARD_H)
        self.setCursor(Qt.CursorShape.PointingHandCursor)
        self._apply_style("normal")
        self._init_ui()

    def _init_ui(self):
        meta = self.asset.type_meta

        # 类型色条（左侧竖条，快速识别类型）
        bar = QWidget(self)
        bar.setGeometry(0, 0, 3, self.CARD_H)
        bar.setStyleSheet(
            f"background: {meta.color}; border-top-left-radius: {RADIUS}px;"
            f" border-bottom-left-radius: {RADIUS}px;"
        )

        # 缩略图区域
        self.thumb = QLabel(self)
        self.thumb.setGeometry(5, 5, 140, 94)
        self.thumb.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self._render_thumb()

        # 类型图标 + 标题
        icon_lbl = QLabel(meta.icon, self)
        icon_lbl.setGeometry(6, 105, 22, 18)
        icon_lbl.setAlignment(Qt.AlignmentFlag.AlignCenter)

        self.title = QLabel(self.asset.title or "(无标题)", self)
        self.title.setGeometry(32, 105, 114, 18)
        self.title.setStyleSheet(f"color: {FG}; font-weight: 600; font-size: 12px;")
        self.title.setToolTip(self.asset.title)
        self._ellipsize(self.title, 114)

        # 文件信息行
        self.meta = QLabel(self._meta_text(), self)
        self.meta.setGeometry(6, 127, 138, 16)
        self.meta.setStyleSheet(f"color: {FG_FAINT}; font-size: 10px;")
        self._ellipsize(self.meta, 138)

        # 标签行
        if self.asset.tags:
            t = QLabel(" · ".join(self.asset.tags[:3]), self)
            t.setGeometry(6, 145, 138, 14)
            t.setStyleSheet(f"color: {FG_DIM}; font-size: 10px;")
            self._ellipsize(t, 138)

        # 页序角标
        if self.asset.page_index is not None:
            tag = QLabel(f"#{self.asset.page_index}", self)
            tag.setGeometry(104, 8, 36, 15)
            tag.setAlignment(Qt.AlignmentFlag.AlignCenter)
            tag.setStyleSheet(
                "background: rgba(0,0,0,150); color: white;"
                " border-radius: 4px; font-size: 9px;"
            )

    def _render_thumb(self):
        path = thumb_mod.thumb_path(self.asset.id, self.thumb_root) if self.thumb_root else None
        if path and path.exists():
            pix = QPixmap(str(path))
            if not pix.isNull():
                self.thumb.setPixmap(pix.scaled(
                    140, 94, Qt.AspectRatioMode.KeepAspectRatio,
                    Qt.TransformationMode.SmoothTransformation,
                ))
        else:
            self.thumb.setText(self.asset.type_meta.icon)
            self.thumb.setStyleSheet(
                f"background: {BG_INPUT}; color: {self.asset.type_meta.color};"
                f" border-radius: 6px; border: 1px solid {BORDER}; font-size: 38px;"
            )

    def _meta_text(self) -> str:
        if self.asset.is_text:
            n = len(self.asset.content or "")
            return f"{n} 字" if n else "文本资产"
        info = thumb_mod.describe_file(self.asset.file_path) if self.asset.file_path else {}
        parts = [v for k, v in (
            ("size", info.get("size")), ("dimensions", info.get("dimensions")),
            ("duration", info.get("duration")),
        ) if v]
        if not parts and self.asset.file_path:
            parts.append(self.asset.type_meta.label)
        return " · ".join(parts) if parts else self.asset.type_meta.label

    def _ellipsize(self, label: QLabel, max_w: int):
        fm = label.fontMetrics()
        txt = label.text()
        if fm.horizontalAdvance(txt) <= max_w:
            return
        i = len(txt)
        while i > 0 and fm.horizontalAdvance(txt[:i] + "…") > max_w:
            i -= 1
        label.setText(txt[:i].rstrip() + "…")

    def _apply_style(self, mode: str):
        if mode == "hover":
            bg, bd = BG_HOVER, BORDER_LIGHT
        elif mode == "selected":
            bg, bd = "#3B5A8A", "#4A90D9"
        else:
            bg, bd = BG_CARD, BORDER
        self.setStyleSheet(
            f"QFrame#Card {{ background: {bg}; border: 1px solid {bd};"
            f" border-radius: {RADIUS}px; }}"
        )

    def _tip(self) -> str:
        lines = [self.asset.title, self.asset.type_meta.label]
        if self.asset.description:
            lines.append(thumb_mod.text_preview(self.asset.description, 80))
        if self.asset.tags:
            lines.append("标签: " + ", ".join(self.asset.tags))
        return "\n".join(lines)

    def enterEvent(self, e):  # noqa: N802
        self._apply_style("hover")
        self.setToolTip(self._tip())
        super().enterEvent(e)

    def leaveEvent(self, e):  # noqa: N802
        self._apply_style("normal")
        super().leaveEvent(e)

    def mousePressEvent(self, e):
        if e.button() == Qt.MouseButton.LeftButton:
            self.selected.emit(self.asset.id)
        super().mousePressEvent(e)

    def mouseDoubleClickEvent(self, e):
        self.doubleClicked.emit(self.asset.id)
        super().mouseDoubleClickEvent(e)

    def refresh_thumb(self):
        """缩略图生成完成后调用，重新渲染。"""
        if not self.thumb.text() or self.thumb.text() == self.asset.type_meta.icon:
            self._render_thumb()


# ---------------------------------------------------------------------------
# 类型徽章 + 标签 chips
# ---------------------------------------------------------------------------
def type_badge_label(asset: Asset, parent=None) -> QLabel:
    """带颜色的类型徽标（详情面板、表格用）。"""
    meta = asset.type_meta
    lbl = QLabel(f"{meta.icon} {meta.label}", parent)
    lbl.setStyleSheet(
        f"background: {meta.color}33; color: {meta.color};"
        f" border: 1px solid {meta.color}66; border-radius: 10px;"
        f" padding: 2px 10px; font-size: 11px; font-weight: 600;"
    )
    lbl.setFixedHeight(22)
    lbl.setAlignment(Qt.AlignmentFlag.AlignCenter)
    return lbl


def make_tag_chips(tags: list[str], color_fn=None, parent=None) -> QWidget:
    """标签 chips（横向排列）。"""
    wrap = QWidget(parent)
    lay = QHBoxLayout(wrap)
    lay.setContentsMargins(0, 0, 0, 0)
    lay.setSpacing(6)
    for t in tags:
        color = color_fn(t) if color_fn else "#4A90D9"
        chip = QLabel(f"#{t}", wrap)
        chip.setStyleSheet(
            f"background: {color}22; color: {color};"
            f" border: 1px solid {color}55; border-radius: 9px;"
            f" padding: 2px 8px; font-size: 11px;"
        )
        lay.addWidget(chip)
    if not tags:
        lay.addWidget(QLabel("—", wrap))
    lay.addStretch(1)
    return wrap


# ---------------------------------------------------------------------------
# 空状态
# ---------------------------------------------------------------------------
class EmptyState(QWidget):
    """列表为空时的占位视图。"""

    def __init__(self, icon: str = "📭", title: str = "还没有资产",
                 hint: str = "点击「导入资产」添加漫画页、设定图或剧本", parent=None):
        super().__init__(parent)
        box = QWidget(self)
        box.setStyleSheet(
            f"background: {BG_PANEL}; border: 1px dashed {BORDER_LIGHT};"
            f" border-radius: 12px;"
        )
        lay = QVBoxLayout(box)
        lay.setContentsMargins(32, 48, 32, 48)

        ic = QLabel(icon, box)
        ic.setAlignment(Qt.AlignmentFlag.AlignCenter)
        ic.setStyleSheet("font-size: 52px;")

        t = QLabel(title, box)
        t.setAlignment(Qt.AlignmentFlag.AlignCenter)
        t.setStyleSheet(f"color: {FG}; font-size: 16px; font-weight: 600;")

        h = QLabel(hint, box)
        h.setAlignment(Qt.AlignmentFlag.AlignCenter)
        h.setWordWrap(True)
        h.setStyleSheet(f"color: {FG_DIM}; font-size: 12px;")

        lay.addWidget(ic, 0, Qt.AlignmentFlag.AlignCenter)
        lay.addWidget(t, 0, Qt.AlignmentFlag.AlignCenter)
        lay.addWidget(h, 0, Qt.AlignmentFlag.AlignCenter)

        outer = QVBoxLayout(self)
        outer.setContentsMargins(0, 0, 0, 0)
        outer.addWidget(box, 1)


# ---------------------------------------------------------------------------
# 分页
# ---------------------------------------------------------------------------
class Pager(QWidget):
    """上一页 / 下一页 + 页码范围指示。"""

    prev_clicked = Signal()
    next_clicked = Signal()

    def __init__(self, parent=None):
        super().__init__(parent)
        lay = QHBoxLayout(self)
        lay.setContentsMargins(0, 0, 0, 0)
        lay.setSpacing(8)

        self.btn_prev = QPushButton("‹ 上一页")
        self.btn_prev.setObjectName("Ghost")
        self.btn_prev.clicked.connect(self.prev_clicked.emit)

        self.lbl = QLabel("—")
        self.lbl.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.lbl.setStyleSheet(f"color: {FG_DIM}; font-size: 12px;")

        self.btn_next = QPushButton("下一页 ›")
        self.btn_next.setObjectName("Ghost")
        self.btn_next.clicked.connect(self.next_clicked.emit)

        lay.addWidget(self.btn_prev)
        lay.addWidget(self.lbl, 1)
        lay.addWidget(self.btn_next)

    def update_info(self, offset: int, limit: int, total: int):
        end = min(offset + limit, total)
        self.lbl.setText(f"{offset + 1} – {end} / 共 {total} 项")
        self.btn_prev.setEnabled(offset > 0)
        self.btn_next.setEnabled(end < total)
