// ============================================================================
//  mainwindow.cpp —— Day3 下午版实现（上午版 + QSS 双主题）
//  与 ../calculator_mainwindow/mainwindow.cpp 的差异全部集中在本文件的 QSS 部分
//  （见 kLightQss / kDarkQss / applyStyle / onToggleTheme / 视图菜单多一项），
//  菜单/停靠窗/状态栏/历史/自测的计算用例部分一字未改。
// ============================================================================
#include "mainwindow.h"
#include "calculatordesigner.h"

#include <QAction>
#include <QApplication>
#include <QDebug>
#include <QDockWidget>
#include <QFile>
#include <QKeySequence>
#include <QListWidget>
#include <QListWidgetItem>
#include <QMenu>
#include <QMenuBar>
#include <QMessageBox>
#include <QStatusBar>

// ---- QSS：从外部 .qss 资源文件加载（themes/light.qss / themes/dark.qss）----
// 教学要点（QSS 最佳实践）：把样式抽成独立 .qss 文件用 QFile 读取，而非硬编码
// C++ 字符串——① 样式与逻辑彻底分离（设计师可独立编辑 .qss）；② 开发期改 .qss
// 重跑即生效，不必改 C++ 重编译；③ 多主题物理分文件，编辑器对 .qss 有语法高亮。
// 资源路径 :/themes/*.qss 由 themes.qrc（AUTORCC）编译进可执行文件。
namespace {

// 从嵌入资源读取样式表。读取失败返回空串（setStyleSheet 空串即清空样式）。
QString loadQss(const QString& resourcePath) {
    QFile f(resourcePath);
    if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qWarning() << "无法打开样式资源" << resourcePath;
        return {};
    }
    return QString::fromUtf8(f.readAll());
}

}  // namespace

MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) {
    setWindowTitle(QStringLiteral("计算器（QMainWindow + QSS 版）"));

    m_calc = new CalculatorDesigner(this);
    setCentralWidget(m_calc);

    buildMenu();
    buildDock();
    buildStatusBar();

    connect(m_calc, &CalculatorDesigner::evaluated, this, &MainWindow::onEvaluated);

    applyStyle(false);   // 默认浅色主题
}

MainWindow::~MainWindow() = default;

void MainWindow::buildMenu() {
    QMenu* fileMenu = menuBar()->addMenu(QStringLiteral("文件(&F)"));
    m_actQuit = fileMenu->addAction(QStringLiteral("退出(&Q)"));
    m_actQuit->setShortcut(QKeySequence(QStringLiteral("Ctrl+Q")));
    connect(m_actQuit, &QAction::triggered, this, &QWidget::close);

    QMenu* editMenu = menuBar()->addMenu(QStringLiteral("编辑(&E)"));
    m_actClearHistory = editMenu->addAction(QStringLiteral("清空历史(&C)"));
    connect(m_actClearHistory, &QAction::triggered, this, &MainWindow::onClearHistory);

    QMenu* viewMenu = menuBar()->addMenu(QStringLiteral("视图(&V)"));
    m_actToggleHistory = viewMenu->addAction(QStringLiteral("显示历史(&H)"));
    m_actToggleHistory->setCheckable(true);
    m_actToggleHistory->setChecked(true);
    connect(m_actToggleHistory, &QAction::toggled, this, &MainWindow::onToggleHistoryVisible);

    // 【下午版新增】深色主题切换：checkable，勾上=深色
    m_actToggleTheme = viewMenu->addAction(QStringLiteral("深色主题(&D)"));
    m_actToggleTheme->setCheckable(true);
    m_actToggleTheme->setChecked(false);
    connect(m_actToggleTheme, &QAction::toggled, this, &MainWindow::onToggleTheme);

    QMenu* helpMenu = menuBar()->addMenu(QStringLiteral("帮助(&H)"));
    m_actAbout = helpMenu->addAction(QStringLiteral("关于(&A)"));
    connect(m_actAbout, &QAction::triggered, this, &MainWindow::onAbout);
}

void MainWindow::buildDock() {
    m_history = new QListWidget(this);
    m_history->setAlternatingRowColors(true);
    m_dock = new QDockWidget(QStringLiteral("历史"), this);
    m_dock->setObjectName(QStringLiteral("historyDock"));
    m_dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea);
    m_dock->setWidget(m_history);
    addDockWidget(Qt::RightDockWidgetArea, m_dock);
    connect(m_history, &QListWidget::itemDoubleClicked, this, &MainWindow::onHistoryDoubleClicked);
}

void MainWindow::buildStatusBar() {
    statusBar()->showMessage(QStringLiteral("就绪"));
}

void MainWindow::refreshStatus(const QString& msg) {
    statusBar()->showMessage(msg, 3000);
}

// 【下午版新增】主题切换：用 qApp->setStyleSheet 全局生效（影响所有窗口及其子部件）。
// 注意 QSS 级联——qApp 级样式会被 widget 级 setStyleSheet 覆盖；本例只用 qApp 级，
// 避免和未来某控件局部样式打架（Day3 下午坑卡：setStyleSheet 级联失控）。
void MainWindow::applyStyle(bool dark) {
    m_dark = dark;
    const QString path = dark ? QStringLiteral(":/themes/dark.qss")
                              : QStringLiteral(":/themes/light.qss");
    qApp->setStyleSheet(loadQss(path));
}

void MainWindow::onToggleTheme(bool dark) {
    applyStyle(dark);
    refreshStatus(dark ? QStringLiteral("已切换深色主题") : QStringLiteral("已切换浅色主题"));
}

void MainWindow::onAbout() {
    QMessageBox::about(this, QStringLiteral("关于"),
        QStringLiteral(
            "<b>计算器（QMainWindow + QSS 版）</b><br><br>"
            "Day3 下午教学参考实现：在上午版基础上加 QSS 双主题美化——"
            "数字/运算/等号/括号/清空退格按键分色，:hover/:pressed 视觉反馈，"
            "深/浅主题切换。<br><br>"
            "对应教案 OUTLINE_4DAY.md Day3 下午。"));
}

void MainWindow::onClearHistory() {
    m_history->clear();
    refreshStatus(QStringLiteral("已清空历史"));
}

void MainWindow::onToggleHistoryVisible(bool checked) {
    m_dock->setVisible(checked);
}

void MainWindow::onEvaluated(const QString& expr, const QString& result) {
    m_history->addItem(expr + QStringLiteral(" = ") + result);
    refreshStatus(QStringLiteral("结果: ") + result);
}

void MainWindow::onHistoryDoubleClicked(QListWidgetItem* item) {
    const QString text = item->text();
    const int idx = text.lastIndexOf(QStringLiteral(" = "));
    if (idx < 0) return;
    m_calc->loadExpression(text.left(idx));
    refreshStatus(QStringLiteral("已回填表达式"));
}

// ------------------------------------------------------------ 自测 ----
bool MainWindow::runSelfTest() {
    auto expect = [](const char* label, bool cond) -> bool {
        if (!cond) { qCritical() << "自测失败：" << label; return false; }
        qInfo() << "自测通过：" << label; return true;
    };
    auto expectEq = [](const char* label, const QString& actual, const QString& expected) -> bool {
        if (actual != expected) {
            qCritical() << "自测失败：" << label << "实际=" << actual << "预期=" << expected;
            return false;
        }
        qInfo() << "自测通过：" << label << "=>" << actual;
        return true;
    };

    // —— 计算用例与上午版一致（验证加 QSS 后行为不变）——
    m_calc->onClear();
    m_calc->onDigit(7); m_calc->onOperator(QLatin1Char('+')); m_calc->onDigit(3); m_calc->onEquals();
    if (!expectEq("7 + 3 =", m_calc->displayText(), QStringLiteral("10"))) return false;
    if (!expect("历史追加第 1 条", m_history->count() == 1)) return false;

    m_calc->onClear();
    m_calc->onDigit(6); m_calc->onOperator(QLatin1Char('/')); m_calc->onDigit(0); m_calc->onEquals();
    if (!expectEq("6 ÷ 0 =", m_calc->displayText(), QStringLiteral("Error"))) return false;
    if (!expect("除零 Error 不进历史", m_history->count() == 1)) return false;

    m_calc->onClear();
    m_calc->onDigit(2); m_calc->onOperator(QLatin1Char('+'));
    m_calc->onDigit(3); m_calc->onOperator(QLatin1Char('*'));
    m_calc->onDigit(4); m_calc->onEquals();
    if (!expectEq("2 + 3 × 4 =", m_calc->displayText(), QStringLiteral("14"))) return false;

    m_calc->onClear();
    m_calc->onLeftParen();
    m_calc->onDigit(2); m_calc->onOperator(QLatin1Char('+')); m_calc->onDigit(3);
    m_calc->onRightParen();
    m_calc->onOperator(QLatin1Char('*'));
    m_calc->onDigit(4); m_calc->onEquals();
    if (!expectEq("(2 + 3) × 4 =", m_calc->displayText(), QStringLiteral("20"))) return false;

    // —— 【下午版新增】主题切换确实改变全局 styleSheet ——
    applyStyle(true);
    if (!expect("深色主题 styleSheet 非空", !qApp->styleSheet().isEmpty())) return false;
    if (!expect("深色主题 styleSheet 含深色标识",
                qApp->styleSheet().contains(QStringLiteral("#2b2b2b")))) return false;
    applyStyle(false);
    if (!expect("浅色主题 styleSheet 含浅色标识",
                qApp->styleSheet().contains(QStringLiteral("#f5f5f5")))) return false;
    if (!expect("主题状态 m_dark 已回浅", !m_dark)) return false;

    // —— 历史双击回填 + 清空（与上午版一致）——
    m_calc->onClear();
    m_calc->onLeftParen();
    m_calc->onDigit(1); m_calc->onOperator(QLatin1Char('+')); m_calc->onDigit(2);
    m_calc->onEquals();
    QListWidgetItem* last = m_history->item(m_history->count() - 1);
    if (!expectEq("最后一条历史", last->text(), QStringLiteral("(1+2) = 3"))) return false;
    onHistoryDoubleClicked(last);
    if (!expectEq("双击回填表达式区", m_calc->expressionText(), QStringLiteral("(1+2)"))) return false;
    onClearHistory();
    if (!expect("清空历史后 count==0", m_history->count() == 0)) return false;

    if (!expect("关于 action 已创建", m_actAbout != nullptr)) return false;
    if (!expect("主题 action 已创建", m_actToggleTheme != nullptr)) return false;

    return true;
}
