// ============================================================================
//  mainwindow.cpp —— Day3 上午版实现
//  详见 mainwindow.h 顶部注释。本文件只做外壳组装，不含任何计算逻辑。
// ============================================================================
#include "mainwindow.h"
#include "calculatordesigner.h"

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

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

    // ★ 中心部件必须显式安放（Day3 上午坑卡：直接往 QMainWindow 上 addWidget
    //   布局行为不可预期）。CalculatorDesigner 是 QWidget，原样塞进去即可。
    m_calc = new CalculatorDesigner(this);
    setCentralWidget(m_calc);

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

    // 计算器求值成功 → 历史停靠窗追加一条（Day2 信号槽的复用：给已有部件
    // 加 evaluated 信号，外壳订阅它）。
    connect(m_calc, &CalculatorDesigner::evaluated, this, &MainWindow::onEvaluated);
}

MainWindow::~MainWindow() = default;

// ---- 菜单栏（纯代码 + 显式 connect，对照 mainwindow_showcase 的 .ui 自动连接）----
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);

    QMenu* helpMenu = menuBar()->addMenu(QStringLiteral("帮助(&H)"));
    m_actAbout = helpMenu->addAction(QStringLiteral("关于(&A)"));
    // ★ 显式 connect：忘了这一行，菜单显示正常、点了没反应（Day3 上午坑卡）。
    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"));   // 供 saveState/restoreState
    m_dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea);
    m_dock->setWidget(m_history);
    addDockWidget(Qt::RightDockWidgetArea, m_dock);
    // 双击历史条目 → 回填表达式（QListWidget 信号槽）
    connect(m_history, &QListWidget::itemDoubleClicked, this, &MainWindow::onHistoryDoubleClicked);
}

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

void MainWindow::refreshStatus(const QString& msg) {
    statusBar()->showMessage(msg, 3000);   // 临时提示，3 秒后恢复
}

// ---- 槽 ----
void MainWindow::onAbout() {
    // 标准对话框：QMessageBox::about 是模态的，exec() 内部阻塞等用户关闭。
    QMessageBox::about(this, QStringLiteral("关于"),
        QStringLiteral(
            "<b>计算器（QMainWindow 版）</b><br><br>"
            "Day3 上午教学参考实现：把 Day2 增强版计算器（表达式求值 + 括号）"
            "装进 QMainWindow，演示菜单栏 / 状态栏 / 历史停靠窗。<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) {
    // 条目文本形如 "expr = result"，取最后一个 " = " 左侧作为表达式回填。
    // 用 lastIndexOf 而非 indexOf：result 文本里一般不含 " = "，但用 lastIndexOf
    // 更稳妥（避免表达式里万一出现 " = "，实际上表达式不会含 =）。
    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;
    };

    // —— Day2 计算 9 组用例（验证升级外壳后计算行为不变）——
    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;
    if (!expectEq("历史条目文本", m_history->item(0)->text(), QStringLiteral("7+3 = 10"))) 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(4); m_calc->onDot(); m_calc->onDigit(5);
    m_calc->onOperator(QLatin1Char('+'));
    m_calc->onDigit(0); m_calc->onDot(); m_calc->onDigit(5);
    m_calc->onEquals();
    if (!expectEq("4.5 + 0.5 =", m_calc->displayText(), QStringLiteral("5"))) return false;

    m_calc->onClear();
    m_calc->onDigit(1); m_calc->onDigit(2); m_calc->onBackspace();
    if (!expectEq("12 退格", m_calc->displayText(), QStringLiteral("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("9"))) 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;

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

    m_calc->onClear();
    m_calc->onLeftParen();
    m_calc->onDigit(1); m_calc->onOperator(QLatin1Char('+')); m_calc->onDigit(2);
    m_calc->onEquals();
    if (!expectEq("(1 + 2 = 自动补全", m_calc->displayText(), QStringLiteral("3"))) return false;

    // 9 组用例里：第 4 组（12 退格）无 onEquals、第 2 组（6÷0）Error 不 emit，
    // 其余 7 次 onEquals 各进历史一条。
    if (!expect("历史累计 7 条", m_history->count() == 7)) return false;

    // —— Day3 新增：历史双击回填 ——
    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;

    // —— Day3 新增：清空历史 ——
    onClearHistory();
    if (!expect("清空历史后 count==0", m_history->count() == 0)) return false;

    // —— Day3 新增：关于 action 已创建并显式连接 ——
    // （QMessageBox::about 是模态弹窗，离屏下不真正触发，GUI 弹窗验证靠现场演示）
    if (!expect("关于 action 已创建", m_actAbout != nullptr)) return false;

    return true;
}
