"""标准对话框（QMessageBox / QInputDialog / QFileDialog）与当前主题一致。"""
from __future__ import annotations

from PyQt6.QtCore import Qt
from PyQt6.QtGui import QTextOption
from PyQt6.QtWidgets import (
    QFileDialog,
    QInputDialog,
    QMessageBox,
    QWidget,
    QDialog,
    QLabel,
    QSizePolicy,
)

import ui.theme as theme


def stylesheet() -> str:
    t = theme.current()
    bg = t["menu_bg"]
    fg = t["menu_color"]
    border = t["menu_border"]
    hover = t["menu_selected"]
    inp = t["search_bg"]
    inp_b = t["search_border"]
    focus = t["search_focus"]
    return f"""
        QMessageBox {{
            background-color: {bg};
            color: {fg};
        }}
        QMessageBox QLabel {{
            color: {fg};
            background: transparent;
            min-width: 0px;
        }}
        QMessageBox QLabel#qt_msgbox_label {{
            min-width: 200px;
            max-width: 560px;
        }}
        QMessageBox QLabel#qt_msgboxex_icon_label {{
            min-width: 28px;
            max-width: 28px;
        }}
        QMessageBox QPushButton {{
            min-width: 64px;
            padding: 6px 14px;
            border: 1px solid {border};
            border-radius: 5px;
            background: {inp};
            color: {fg};
        }}
        QMessageBox QPushButton:hover {{
            background: {hover};
        }}
        QMessageBox QPushButton:default {{
            border-color: {focus};
        }}
        QInputDialog {{
            background-color: {bg};
            color: {fg};
        }}
        QInputDialog QLabel {{
            color: {fg};
            background: transparent;
        }}
        QInputDialog QLineEdit {{
            background: {inp};
            border: 1px solid {inp_b};
            border-radius: 5px;
            padding: 6px 8px;
            color: {fg};
            min-width: 260px;
        }}
        QInputDialog QLineEdit:focus {{
            border-color: {focus};
        }}
        QInputDialog QPushButton {{
            min-width: 72px;
            padding: 6px 14px;
            border: 1px solid {border};
            border-radius: 5px;
            background: {inp};
            color: {fg};
        }}
        QInputDialog QPushButton:hover {{
            background: {hover};
        }}
        QFileDialog {{
            background-color: {bg};
            color: {fg};
        }}
        QFileDialog QLabel {{
            color: {fg};
            background: transparent;
        }}
        QFileDialog QLineEdit, QFileDialog QComboBox {{
            background: {inp};
            border: 1px solid {inp_b};
            border-radius: 4px;
            padding: 4px 6px;
            color: {fg};
        }}
        QFileDialog QLineEdit:focus, QFileDialog QComboBox:focus {{
            border-color: {focus};
        }}
        QFileDialog QTreeView, QFileDialog QListView, QFileDialog QTableView {{
            background: {inp};
            border: 1px solid {inp_b};
            border-radius: 4px;
            color: {fg};
            outline: none;
        }}
        QFileDialog QTreeView::item:selected, QFileDialog QListView::item:selected {{
            background: {hover};
        }}
        QFileDialog QPushButton {{
            min-width: 72px;
            padding: 6px 12px;
            border: 1px solid {border};
            border-radius: 5px;
            background: {inp};
            color: {fg};
        }}
        QFileDialog QPushButton:hover {{
            background: {hover};
        }}
        QFileDialog QComboBox QAbstractItemView {{
            background: {bg};
            color: {fg};
            border: 1px solid {border};
        }}
    """


def _apply(w: QWidget | None) -> None:
    if w is not None:
        w.setStyleSheet(stylesheet())


def _prepare_qmessagebox(msg: QMessageBox) -> None:
    """让提示框按内容换行并自适应宽高（避免固定宽度截断文字）。"""
    lbl = msg.findChild(QLabel, "qt_msgbox_label")
    if lbl is not None:
        lbl.setWordWrap(True)
        lbl.setTextFormat(Qt.TextFormat.PlainText)
        # 无空格长中文也能在边界处断行，而不是整段挤在一行被裁切
        try:
            lbl.setWordWrapMode(QTextOption.WrapMode.WrapAnywhere)
        except AttributeError:
            pass
        lbl.setMinimumWidth(200)
        lbl.setMaximumWidth(560)
        lbl.setSizePolicy(
            QSizePolicy.Policy.Preferred,
            QSizePolicy.Policy.MinimumExpanding,
        )
    lay = msg.layout()
    if lay is not None:
        lay.activate()
    msg.setSizePolicy(
        QSizePolicy.Policy.Preferred,
        QSizePolicy.Policy.Preferred,
    )
    msg.setMinimumSize(0, 0)
    msg.adjustSize()


def question(
    parent: QWidget | None,
    title: str,
    text: str,
    *,
    buttons: QMessageBox.StandardButton = (
        QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
    ),
    default_button: QMessageBox.StandardButton | None = None,
    icon: QMessageBox.Icon = QMessageBox.Icon.Question,
) -> QMessageBox.StandardButton:
    msg = QMessageBox(parent)
    msg.setWindowTitle(title)
    msg.setText(text)
    msg.setIcon(icon)
    msg.setStandardButtons(buttons)
    if default_button is not None:
        msg.setDefaultButton(default_button)
    _apply(msg)
    _prepare_qmessagebox(msg)
    return QMessageBox.StandardButton(msg.exec())


def warning(parent: QWidget | None, title: str, text: str) -> None:
    msg = QMessageBox(parent)
    msg.setWindowTitle(title)
    msg.setText(text)
    msg.setIcon(QMessageBox.Icon.Warning)
    msg.setStandardButtons(QMessageBox.StandardButton.Ok)
    _apply(msg)
    _prepare_qmessagebox(msg)
    msg.exec()


def information(parent: QWidget | None, title: str, text: str) -> None:
    msg = QMessageBox(parent)
    msg.setWindowTitle(title)
    msg.setText(text)
    msg.setIcon(QMessageBox.Icon.Information)
    msg.setStandardButtons(QMessageBox.StandardButton.Ok)
    _apply(msg)
    _prepare_qmessagebox(msg)
    msg.exec()


def get_text(
    parent: QWidget | None,
    title: str,
    label: str,
    text: str = "",
) -> tuple[str, bool]:
    d = QInputDialog(parent)
    d.setWindowTitle(title)
    d.setLabelText(label)
    d.setTextValue(text)
    _apply(d)
    ok = d.exec() == QDialog.DialogCode.Accepted
    return d.textValue(), ok


def get_open_file_name(
    parent: QWidget | None,
    caption: str,
    directory: str,
    filter_str: str,
) -> tuple[str, str]:
    fd = QFileDialog(parent, caption, directory, filter_str)
    fd.setOption(QFileDialog.Option.DontUseNativeDialog, True)
    fd.setFileMode(QFileDialog.FileMode.ExistingFile)
    _apply(fd)
    if fd.exec() == QDialog.DialogCode.Accepted:
        files = fd.selectedFiles()
        if files:
            return files[0], fd.selectedNameFilter()
    return "", ""


def get_existing_directory(
    parent: QWidget | None,
    caption: str,
    directory: str = "",
) -> str:
    fd = QFileDialog(parent, caption, directory)
    fd.setOption(QFileDialog.Option.DontUseNativeDialog, True)
    fd.setFileMode(QFileDialog.FileMode.Directory)
    fd.setOption(QFileDialog.Option.ShowDirsOnly, True)
    _apply(fd)
    if fd.exec() == QDialog.DialogCode.Accepted:
        files = fd.selectedFiles()
        if files:
            return files[0]
    return ""
