#include "wizardwrapper.h"
#include "wordwizard.h"
#include "dconfigmanager.h"
#include "dbwrapper.h"
#include "private/eaiexecutor.h"
#include "private/welcomedialog.h"
#include "private/wizarddpushbutton.h"
#include "esystemcontext.h"
#include <report/followalongpoint.h>
#include <report/eventlogutil.h>
#ifdef COMPILE_ON_V25
#include "ddeshellwayland.h"
#endif
#include <QHBoxLayout>
#include <QMenu>
#include <QGraphicsDropShadowEffect>
#include <QScreen>
#include <QDBusInterface>
#include <QDataStream>
#include <QCryptographicHash>
#include <QTimer>

#include <DStyle>
#include <DDialog>
#include <DPlatformWindowHandle>
#include <DFontSizeManager>

#include <QLoggingCategory>
Q_DECLARE_LOGGING_CATEGORY(logWordWizard)

DGUI_USE_NAMESPACE
DWIDGET_USE_NAMESPACE
using namespace uos_ai;

WizardWrapper::WizardWrapper(QWidget *parent) : DBlurEffectWidget(parent)
{
    initUI();
    initConnect();
    initAnimation();

    m_customFunctionListHash = calculateCustomFunctionListHash();
}

WizardWrapper &WizardWrapper::instance() {
    static WizardWrapper instance;
    return instance;
}

void WizardWrapper::initUI()
{
    this->setFixedSize(32, 32);
    this->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint);
#ifdef COMPILE_ON_V20
    if (ESystemContext::isWayland())
        this->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus);
#endif
    this->setAttribute(Qt::WA_AlwaysShowToolTips);
    this->setAttribute(Qt::WA_TranslucentBackground);
    DPlatformWindowHandle handle(this, this);
    handle.setWindowRadius(8);
    this->setObjectName("selectionwidget");
    installEventFilter(this);

    m_iconBtn = new DIconButton(this);
    m_iconBtn->setFixedSize(QSize(20, 20));
    m_iconBtn->setIcon(QIcon::fromTheme("uos-ai-assistant"));
    m_iconBtn->setIconSize(QSize(20, 20));
    m_iconBtn->installEventFilter(this);

    m_lineSep = new DWidget(this);
    m_lineSep->setFixedSize(1, 15);
    m_lineSep->setAutoFillBackground(true);

    m_lineSep1 = new DWidget(this);
    m_lineSep1->setFixedSize(1, 12);
    m_lineSep1->setAutoFillBackground(true);

    m_lineSep2 = new DWidget(this);
    m_lineSep2->setFixedSize(1, 12);
    m_lineSep2->setAutoFillBackground(true);

    m_lineSepSpace = new DWidget(this);
    m_lineSepSpace->setFixedSize(5, 15);

    m_moreBtn = new WizardDPushButton(this);
    m_moreBtn->setFlat(true);
    m_moreBtn->setIcon(QIcon::fromTheme("uos-ai-assistant_more"));
    m_moreBtn->setIconSize(QSize(20, 20));
    m_moreBtn->setFixedHeight(24);
    m_moreBtn->installEventFilter(this);

    m_closeBtn = new WizardDPushButton(this);
    m_closeBtn->setFlat(true);
    m_closeBtn->setIcon(QIcon::fromTheme("uos-ai-assistant_close"));
    m_closeBtn->setIconSize(QSize(20, 20));
    m_closeBtn->setFixedHeight(24);
    m_closeBtn->installEventFilter(this);

    m_disableMenu = new DMenu(tr("Disable"));
    m_disableInAppAction = new QAction(tr("Disable in This Application"));
    m_disableGlobalAction = new QAction(tr("Disable Globally"));
    m_disableMenu->addAction(m_disableInAppAction);
    m_disableMenu->addAction(m_disableGlobalAction);
    m_disableMenu->installEventFilter(this);
    m_customSettings = new QAction(tr("Custom Settings"));

    m_moreMenu = new DMenu(this);
    m_moreMenu->setMinimumWidth(92);
    m_moreMenu->installEventFilter(this);

    QHBoxLayout *scribeWordsLayout = new QHBoxLayout;
    scribeWordsLayout->setSpacing(2);
    scribeWordsLayout->setAlignment(Qt::AlignCenter);
    scribeWordsLayout->setContentsMargins(6, 0, 6, 0);
    this->setLayout(scribeWordsLayout);

    updateCustomFunctions();
    
    setButtonHidden(true);

    onUpdateSystemTheme(DGuiApplicationHelper::instance()->themeType());
}

void WizardWrapper::initConnect()
{
    connect(m_iconBtn, &DIconButton::clicked, this, &WizardWrapper::onIconBtnClicked);
    connect(m_moreMenu, &QMenu::triggered, this, &WizardWrapper::onMoreMenuTriggered);
    connect(m_moreBtn, &WizardDPushButton::clicked, this, &WizardWrapper::showMenu);
    
    //避免随航检测到mouseRelease事件后又弹出
    connect(m_closeBtn, &WizardDPushButton::clicked, this, [&] {
        QTimer::singleShot(1, this, &WizardWrapper::onCloseWidget);
    });

    connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &WizardWrapper::onUpdateSystemTheme);

    connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::fontChanged, this, [this]() {
        if (m_isExtend) {
            QTimer::singleShot(0, this, [this]() {
                int calculatedWidth = this->calculateWidth();
                this->setFixedWidth(calculatedWidth);
            });
        }
    });
}

void WizardWrapper::paintEvent(QPaintEvent *event)
{
    QStyleOption opt;
    opt.initFrom(this);
    QPainter painter(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);

    DPalette parentPb = DGuiApplicationHelper::instance()->applicationPalette();
    QColor backgroundColor = parentPb.color(DPalette::Normal, DPalette::NColorTypes);
    QRect rect = this->rect();

    painter.setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing);
    painter.setBrush(backgroundColor);
    painter.setPen(Qt::NoPen);
    painter.drawRect(rect);
}

bool WizardWrapper::eventFilter(QObject *watched, QEvent *event)
{
    // 显示工具栏逻辑
    if (event->type() == QEvent::Enter) {
        m_mouseInside = true;
        if (watched == m_iconBtn && !m_isExtend) {
            QTimer::singleShot(500, this, [ = ]{
                expandWrapper();
            });
        }
    } else if (event->type() == QEvent::Leave && watched != m_iconBtn) {
        m_mouseInside = false;
    }

    // 拖动逻辑
    bool isDraggableWidget = false;
    if (!ESystemContext::isTreeland() && m_isExtend) {
        if (watched == m_iconBtn || watched == m_moreBtn || watched == m_closeBtn) {
            isDraggableWidget = true;
        } else {
            for (WizardDPushButton *btn : m_functionButtons) {
                if (watched == btn) {
                    isDraggableWidget = true;
                    break;
                }
            }
        }
        
        if (isDraggableWidget) {
            if (event->type() == QEvent::Enter) {
                this->setCursor(Qt::CursorShape::ArrowCursor);
            } else if (event->type() == QEvent::Leave) {
                this->setCursor(Qt::CursorShape::OpenHandCursor);
            }
        }
    }

    return DBlurEffectWidget::eventFilter(watched, event);
}

void WizardWrapper::mousePressEvent(QMouseEvent *event)
{
//    qDebug() << event;
    if (!ESystemContext::isTreeland() && m_isExtend) {
        if (event->button() == Qt::LeftButton) {
            this->setCursor(Qt::CursorShape::ClosedHandCursor);
            m_dragging = true;
            m_dragStartPos = event->globalPos() - frameGeometry().topLeft();
            return;
        }
    }

    DBlurEffectWidget::mousePressEvent(event);
}

void WizardWrapper::mouseMoveEvent(QMouseEvent *event)
{
//    qDebug() << event;
    if (!ESystemContext::isTreeland() && m_isExtend) {
        if (m_dragging) {
            this->setCursor(Qt::CursorShape::ClosedHandCursor);
            this->move(event->globalPos() - m_dragStartPos);
            return;
        }
    }

    DBlurEffectWidget::mouseMoveEvent(event);
}

void WizardWrapper::mouseReleaseEvent(QMouseEvent *event)
{
//    qDebug() << event;
    if (!ESystemContext::isTreeland() && m_isExtend) {
        if (event->button() == Qt::LeftButton) {
            m_dragging = false;
            this->setCursor(Qt::CursorShape::OpenHandCursor);
            return;
        }
    }

    DBlurEffectWidget::mouseReleaseEvent(event);
}

#ifdef COMPILE_ON_QT6
void WizardWrapper::enterEvent(QEnterEvent *event)
#else
void WizardWrapper::enterEvent(QEvent *event)
#endif
{
//    qDebug() << event;
    if (!ESystemContext::isTreeland() && m_isExtend) {
        this->setCursor(Qt::CursorShape::OpenHandCursor);
    }
    DBlurEffectWidget::enterEvent(event);
}

void WizardWrapper::leaveEvent(QEvent *event)
{
//    qDebug() << event;
    if (!ESystemContext::isTreeland() && m_isExtend) {
        this->setCursor(Qt::CursorShape::ArrowCursor);
    }
    DBlurEffectWidget::leaveEvent(event);
}

void WizardWrapper::onUpdateSystemTheme(const DGuiApplicationHelper::ColorType &themeType)
{
    if (themeType == DGuiApplicationHelper::LightType) {
        if(m_lineSep) {
            DPalette sepPalette = m_lineSep->palette();
            sepPalette.setColor(DPalette::Window, QColor(0, 0, 0, int(255 * 0.2)));
            m_lineSep->setPalette(sepPalette);
            m_lineSep1->setPalette(sepPalette);
            m_lineSep2->setPalette(sepPalette);
        }
    } else {
        if(m_lineSep) {
            DPalette sepPalette = m_lineSep->palette();
            sepPalette.setColor(DPalette::Window, QColor(255, 255, 255, int(255 * 0.2)));
            m_lineSep->setPalette(sepPalette);
            m_lineSep1->setPalette(sepPalette);
            m_lineSep2->setPalette(sepPalette);
        }
    }
    update();
}

void WizardWrapper::showScribeWordsAtCursorPosition(QRect screenRect, QPoint& point, bool isMouseRelease, bool isShortcut)
{
    checkAndUpdateLayout();
    
    m_screenRect = screenRect;
    m_cursorPos = point;
    if(isMouseRelease || isShortcut){
        if (isShortcut) {
            QList<QScreen *> screens = QGuiApplication::screens();
            for(QScreen *screen : screens) {
                if (screen->geometry().contains(m_cursorPos)) {
                    m_screenRect = screen->geometry();
                }
            }
            m_cursorPos = m_screenRect.center() - QPoint(this->rect().width() / 2, 0);
        }
        else {
            adjustShowPos(m_screenRect, m_cursorPos);
        }
        move(m_cursorPos);
        close();
        m_isVisible = false;
        showWizardWrapperWithAnimation();
    }
}

void WizardWrapper::initAnimation()
{
    m_animation = new QPropertyAnimation(this, "windowOpacity");
    m_animation->setDuration(300);
    m_animation->setStartValue(0.0);
    m_animation->setEndValue(1.0);
    m_animation->setEasingCurve(QEasingCurve::OutInQuad);
    return;
}

void WizardWrapper::showWizardWrapperWithAnimation()
{
    this->setWindowOpacity(0.0);
    this->show();
    m_isVisible = true;
    m_mouseInside = false;
#ifdef COMPILE_ON_V25
    if (ESystemContext::isTreeland()) {
        DDEShellWayland::get(windowHandle())->setAutoPlacement(1);
        DDEShellWayland::get(windowHandle())->setSkipDockPreview(true);
        DDEShellWayland::get(windowHandle())->setSkipMutiTaskView(true);
        DDEShellWayland::get(windowHandle())->setSkipSwitcher(true);
        DDEShellWayland::get(windowHandle())->setAcceptKeyboardFocus(false);
    }
#endif
    update();
    adjustSize();
    m_animation->start();
}

void WizardWrapper::onMoreMenuTriggered(const QAction *action)
{
    if (!WelcomeDialog::isAgreed()) {
        qCWarning(logWordWizard) << "Welcome dialog not agreed, closing wizard";
        this->close();
        m_isVisible = false;
        WelcomeDialog::instance(false)->exec();
        return;
    }

    int wizardtype = -1;
    bool isCustom = false;
    
    if (action == m_disableGlobalAction) {
        qCDebug(logWordWizard) << "Disable globally action triggered";
        wizardtype = WordWizard::WIZARD_TYPE_HIDDEN;
        isCustom = false;
    } else if (action == m_disableInAppAction) {
        qCDebug(logWordWizard) << "Disable in app action triggered";
        emit signalDisableInApp();
        return;
    } else if (action == m_customSettings) {
        qCDebug(logWordWizard) << "Custom settings action triggered";
        wizardtype = WordWizard::WIZARD_TYPE_CUSTOM;
        isCustom = false;
    } else {
        bool found = false;
        for (QAction *customAction : m_customActions) {
            if (customAction == action) {
                int functionIndex = action->property("functionIndex").toInt();
                const QList<CustomFunction> &customFunctions = WordWizard::kCustomFunctionList;
                if (functionIndex >= 0 && functionIndex < customFunctions.size()) {
                    const CustomFunction &func = customFunctions[functionIndex];
                    isCustom = func.isCustom;
                    if (isCustom) {
                        wizardtype = functionIndex;
                    } else {
                        wizardtype = func.defaultFunctionType;
                    }
                }
                found = true;
                break;
            }
        }
        
        if (!found) {
            qCWarning(logWordWizard) << "Unknown action triggered";
            return;
        }
    }
    
    emit signalFunctionTriggered(wizardtype, m_cursorPos + QPoint(this->rect().width() / 2, 0), isCustom);
}

void WizardWrapper::onButtonClicked()
{
    int wizardtype = -1;
    bool isCustom = false;
    int defaultFunctionType = -1;
    
    for (WizardDPushButton *btn : m_functionButtons) {
        if (sender() == btn) {
            int functionIndex = btn->property("functionIndex").toInt();
            isCustom = btn->property("isCustom").toBool();
            defaultFunctionType = btn->property("defaultFunctionType").toInt();
            if (isCustom) {
                wizardtype = functionIndex;
            } else {
                wizardtype = defaultFunctionType;
            }
            break;
        }
    }
    
    if (wizardtype == -1) {
        qCWarning(logWordWizard) << "Unknown button clicked";
        return;
    }
    
    // 检查是否需要同意协议（只有非自定义的搜索功能不需要协议）
    bool needAgreement = true;
    if (!isCustom && defaultFunctionType == WordWizard::WIZARD_TYPE_SEARCH) {
        needAgreement = false;
    }
    
    if (needAgreement && !WelcomeDialog::isAgreed()) {
        qCWarning(logWordWizard) << "Welcome dialog not agreed, closing wizard";
        this->close();
        m_isVisible = false;
        WelcomeDialog::instance(false)->exec();
        return;
    }

    emit signalRequestServer();
    emit signalFunctionTriggered(wizardtype, m_cursorPos + QPoint(this->rect().width() / 2, 0), isCustom);
}

void WizardWrapper::showMenu()
{
    emit signalRequestServer();
    adjustSize();
    m_moreMenu->exec(m_moreBtn->mapToGlobal(m_moreBtn->rect().bottomLeft() + QPoint(0, 5)));
    m_moreBtn->update();
}

void WizardWrapper::onCloseWidget()
{
    qCDebug(logWordWizard) << "Closing widget";
    this->close();
    m_isVisible = false;
    if (isFirstClose()) {
        qCInfo(logWordWizard) << "First time close, showing tips dialog";
        DDialog dialog("",tr("After selecting the text, press the Super+Space bar can also wake up the UOS AI FollowAlong."));
        dialog.setFixedWidth(380);
        dialog.setIcon(QIcon(":assets/images/tips.svg"));
        dialog.addButton(tr("Ok", "button"), true, DDialog::ButtonNormal);
        dialog.exec();
        DConfigManager::instance()->setValue(WORDWIZARD_GROUP, WORDWIZARD_ISFIRSTCLOSE, false);
    }
    emit signalCloseBtnClicked();
}

void WizardWrapper::onIconBtnClicked()
{
    if (m_isExtend) {
        this->close();
        m_isVisible = false;
        emit signalIconBtnClicked();
    } else {
        expandWrapper();
    }
}

void WizardWrapper::adjustShowPos(const QRect &screenRect, QPoint &pos)
{
    adjustSize();
    pos = pos - QPoint(this->rect().width() / 2, 0);

    QRect widgetRect(pos.x(), pos.y(), this->rect().width(), this->rect().height());
    if (screenRect.contains(widgetRect))
        return;
    if (screenRect.left() > widgetRect.left())
        pos.setX(screenRect.left());
    if (screenRect.top() > widgetRect.top())
        pos.setY(screenRect.top());
    if (screenRect.right() < widgetRect.right())
        pos.setX(screenRect.right() - widgetRect.width());
    if (screenRect.bottom() < widgetRect.bottom())
        pos.setY(widgetRect.top() - 2 * widgetRect.height());
}

void WizardWrapper::isShowHiddenAction(bool isShow)
{
    m_disableMenuAction->setVisible(isShow);
    m_disableInAppAction->setVisible(isShow);
    m_disableGlobalAction->setVisible(isShow);
}

bool WizardWrapper::isFirstClose()
{
    return DConfigManager::instance()->value(WORDWIZARD_GROUP, WORDWIZARD_ISFIRSTCLOSE).toBool();
}

void WizardWrapper::expandWrapper()
{
    if (!m_isExtend && this->geometry().contains(QCursor::pos())) {
        setButtonHidden(false);
        adjustShowPos(m_screenRect, m_cursorPos);
        move(m_cursorPos);
        this->show();
        this->adjustSize();
    }
}

void WizardWrapper::setButtonHidden(bool isHidden)
{
    QList<WizardDPushButton *> buttons = this->findChildren<WizardDPushButton *>();
    auto hLayout = this->findChild<QHBoxLayout *>();
    if (isHidden) {
        this->setFixedSize(32, 32);
        for (WizardDPushButton *button : buttons)
            button->hide();
        m_iconBtn->setFixedSize(QSize(20, 20));
        m_iconBtn->setIconSize(QSize(20, 20));
        m_lineSep->hide();
        m_lineSep1->hide();
        m_lineSep2->hide();
        m_lineSepSpace->hide();
        if (hLayout)
            hLayout->setContentsMargins(6, 0, 6, 0);
    } else {
        this->setMaximumWidth(QWIDGETSIZE_MAX);
        for (WizardDPushButton *button : buttons) {
            button->show();
            button->setHoverStatus(false);
        }

        for (WizardDPushButton *btn : m_functionButtons) {
            btn->show();
            btn->setHoverStatus(false);
        }

        if (!m_functionButtons.isEmpty()) {
            this->setFixedHeight(m_functionButtons.first()->height() + 6);
        } else {
            this->setFixedHeight(32);
        }
        
        m_iconBtn->setFixedSize(QSize(16, 16));
        m_iconBtn->setIconSize(QSize(16, 16));
        m_lineSep->show();
        m_lineSep1->show();
        m_lineSep2->show();
        m_lineSepSpace->show();
        if (hLayout)
            hLayout->setContentsMargins(9, 0, 6, 0);

        this->setFixedWidth(calculateWidth());

        // tid:1001600001 event:followalong
        ReportIns()->writeEvent(report::FollowalongPoint().assemblingData());
    }
    m_isExtend = !isHidden;
    adjustSize();
}

void WizardWrapper::createDynamicButtons()
{
    for (WizardDPushButton *btn : m_functionButtons) {
        btn->deleteLater();
    }
    m_functionButtons.clear();

    const QList<CustomFunction> &customFunctions = WordWizard::kCustomFunctionList;
    int buttonCount = 0;
    for (int i = 0; i < customFunctions.size() && buttonCount < 4; ++i) {
        const CustomFunction &func = customFunctions[i];
        if (func.isHidden)
            continue;

        QString buttonText;
        QString iconName;
        
        if (func.isCustom) {
            buttonText = func.name;
            iconName = "uos-ai-assistant_custom";
        } else {
            switch (func.defaultFunctionType) {
                case WordWizard::WIZARD_TYPE_SEARCH:
                    buttonText = tr("Search");
                    iconName = "uos-ai-assistant_ai_search";
                    break;
                case WordWizard::WIZARD_TYPE_EXPLAIN:
                    buttonText = tr("Explain");
                    iconName = "uos-ai-assistant_explain";
                    break;
                case WordWizard::WIZARD_TYPE_SUMMARIZE:
                    buttonText = tr("Summary");
                    iconName = "uos-ai-assistant_summarize";
                    break;
                case WordWizard::WIZARD_TYPE_TRANSLATE:
                    buttonText = tr("Translate");
                    iconName = "uos-ai-assistant_translation";
                    break;
                case WordWizard::WIZARD_TYPE_RENEW:
                    buttonText = tr("Continue Writing");
                    iconName = "uos-ai-assistant_renew";
                    break;
                case WordWizard::WIZARD_TYPE_EXTEND:
                    buttonText = tr("Expand");
                    iconName = "uos-ai-assistant_extend";
                    break;
                case WordWizard::WIZARD_TYPE_CORRECT:
                    buttonText = tr("Correct");
                    iconName = "uos-ai-assistant_correct";
                    break;
                case WordWizard::WIZARD_TYPE_POLISH:
                    buttonText = tr("Polish");
                    iconName = "uos-ai-assistant_polish";
                    break;
                default:
                    break;
            }
        }

        WizardDPushButton *btn = new WizardDPushButton(buttonText, this);
        btn->setIcon(QIcon::fromTheme(iconName));
        btn->setIconSize(QSize(16, 16));
        btn->setFlat(true);
        DFontSizeManager::instance()->bind(btn, DFontSizeManager::T7, QFont::Normal);
        btn->installEventFilter(this);

        btn->setProperty("functionIndex", i);
        btn->setProperty("isCustom", func.isCustom);
        btn->setProperty("defaultFunctionType", func.defaultFunctionType);
        
        m_functionButtons.append(btn);
        buttonCount++;
    }
}

void WizardWrapper::updateButtonsFromCustomFunctions()
{
    for (QAction *action : m_customActions) {
        m_moreMenu->removeAction(action);
        action->deleteLater();
    }
    m_customActions.clear();

    if (m_disableMenuAction) {
        m_moreMenu->removeAction(m_disableMenuAction);
    }
    m_moreMenu->removeAction(m_customSettings);
    QList<QAction*> actions = m_moreMenu->actions();
    for (QAction* action : actions) {
        if (action->isSeparator()) {
            m_moreMenu->removeAction(action);
        }
    }

    const QList<CustomFunction> &customFunctions = WordWizard::kCustomFunctionList;

    int buttonCount = 0;
    for (int i = 0; i < customFunctions.size(); ++i) {
        const CustomFunction &func = customFunctions[i];
        if (func.isHidden) {
            continue;
        }

        if (buttonCount < 4) {
            buttonCount++;
            continue;
        }

        QString actionText;
        if (func.isCustom) {
            actionText = func.name;
        } else {
            actionText = WordWizard::getDefaultSkillName(func.defaultFunctionType);
        }

        QFontMetrics fm(font());
        QString truncatedText = actionText;
        if (fm.horizontalAdvance(truncatedText) > 140) {
            while (fm.horizontalAdvance(truncatedText) > 140 && !truncatedText.isEmpty() && truncatedText.length() > 10) {
                truncatedText.chop(1);
            }
            truncatedText += "...";
        }

        QAction *action = new QAction(truncatedText, this);
        action->setProperty("functionIndex", i);
        m_customActions.append(action);
        m_moreMenu->addAction(action);
    }

    if (!m_customActions.isEmpty()) {
        m_moreMenu->addSeparator();
    }
    m_moreMenu->addAction(m_customSettings);
    m_disableMenuAction = m_moreMenu->addMenu(m_disableMenu);
}

void WizardWrapper::updateCustomFunctions()
{
    createDynamicButtons();
    for (WizardDPushButton *btn : m_functionButtons) {
        connect(btn, &WizardDPushButton::clicked, this, &WizardWrapper::onButtonClicked);
    }

    this->updateButtonsFromCustomFunctions();

    QHBoxLayout *layout = this->findChild<QHBoxLayout *>();
    if (layout) {
        while (layout->count() > 0) {
            QLayoutItem *item = layout->takeAt(0);
            if (item->widget()) {
                layout->removeWidget(item->widget());
            }
            delete item;
        }

        layout->addWidget(m_lineSep1);
        layout->addWidget(m_lineSep2);
        layout->addWidget(m_lineSepSpace);
        layout->addWidget(m_iconBtn);

        for (WizardDPushButton *btn : m_functionButtons) {
            layout->addWidget(btn);
        }
        
        layout->addWidget(m_lineSep);
        layout->addWidget(m_moreBtn);
        layout->addWidget(m_closeBtn);
        layout->addStretch();
    }

    QTimer::singleShot(0, this, [this]() {
        if (m_isExtend) {
            int calculatedWidth = this->calculateWidth();
            this->setFixedWidth(calculatedWidth);
        } else {
            this->adjustSize();
        }
    });
}

uint WizardWrapper::calculateCustomFunctionListHash() const
{
    const QList<CustomFunction> &customFunctions = WordWizard::kCustomFunctionList;

    QCryptographicHash hash(QCryptographicHash::Sha256);
    
    for (const CustomFunction &func : customFunctions) {
        hash.addData(func.name.toUtf8());
        hash.addData(func.prompt.toUtf8());
        hash.addData(QByteArray::number(func.isCustom ? 1 : 0));
        hash.addData(QByteArray::number(func.isHidden ? 1 : 0));
        hash.addData(QByteArray::number(func.defaultFunctionType));
    }

    QByteArray result = hash.result();
    return qFromBigEndian<uint>(reinterpret_cast<const uchar*>(result.constData()));
}

void WizardWrapper::checkAndUpdateLayout()
{
    uint currentHash = calculateCustomFunctionListHash();
    
    if (currentHash != m_customFunctionListHash) {
        qCDebug(logWordWizard) << "CustomFunction list changed, updating layout";
        m_customFunctionListHash = currentHash;

        updateCustomFunctions();
        // 如果是快捷键调起的，需要是展开状态
        setButtonHidden(!m_isExtend);
    }
}

int WizardWrapper::calculateWidth()
{
    for (WizardDPushButton *btn : m_functionButtons) {
        if (btn && btn->isVisible()) {
            btn->adjustSize();
        }
    }

    if (m_moreBtn) {
        m_moreBtn->adjustSize();
    }
    if (m_closeBtn) {
        m_closeBtn->adjustSize();
    }

    int totalWidth = 0;

    // 布局margins: 展开状态是 (9, 0, 6, 0)
    totalWidth += 9 + 6;

    totalWidth += 2;  // m_lineSep1
    totalWidth += 2;  // m_lineSep2  
    totalWidth += 5;  // m_lineSepSpace
    totalWidth += 16; // m_iconBtn (展开状态下是16px)

    int componentCount = 4;

    int visibleButtonCount = 0;
    for (int i = 0; i < m_functionButtons.size(); ++i) {
        WizardDPushButton *btn = m_functionButtons[i];
        if (!btn) {
            continue;
        }
        totalWidth += btn->width();
        componentCount++;
        visibleButtonCount++;
    }

    totalWidth += 2;  // m_lineSep
    componentCount++;

    totalWidth += m_moreBtn ? m_moreBtn->width() : 24;
    totalWidth += m_closeBtn ? m_closeBtn->width() : 24;
    componentCount += 2;

    totalWidth += (componentCount - 1) * 1;

    totalWidth += 6;

    return totalWidth;
}

