#include "mainwindow.h"
#include <qembycore.h>
#include "views/public/loginview.h"
#include "views/media/playerview.h" 
#include "views/user/homeview.h"
#include "components/searchcompleterpopup.h"
#include "components/searchhistorypopup.h"
#include "managers/thememanager.h" 
#include "managers/searchhistorymanager.h"
#include "managers/traymanager.h"  
#include "config/configstore.h"    
#include "config/config_keys.h"    
#include "utils/contextmenuutils.h"
#include <services/manager/servermanager.h>
#include <QStackedWidget>
#include <QDebug>
#include <QApplication>
#include <QGuiApplication>
#include <QAbstractItemView>
#include <QFile>
#include <QTimer>
#include <QElapsedTimer>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QAction>
#include <QCompleter>
#include <QFrame>
#include <QStringListModel>
#include <QPropertyAnimation>
#include <QScreen>
#include <QGraphicsOpacityEffect>
#include <services/auth/authservice.h>
#include "components/themetransitionwidget.h"
#include "components/moderntoast.h" 
#include <QEasingCurve>
#include <QFocusEvent>
#include <QLineF>
#include <QtMath>
#include <QKeyEvent>
#include <QMouseEvent>
#include <QDialog>

#include <QWKWidgets/widgetwindowagent.h>
#include <widgetframe/windowbar.h>
#include <widgetframe/windowbutton.h>

static inline void emulateLeaveEvent(QWidget *widget) {
    Q_ASSERT(widget);
    if (!widget) return;
    QTimer::singleShot(0, widget, [widget]() {
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
        const QScreen *screen = widget->screen();
#else
        const QScreen *screen = widget->windowHandle()->screen();
#endif
        const QPoint globalPos = QCursor::pos(screen);
        if (!QRect(widget->mapToGlobal(QPoint{0, 0}), widget->size()).contains(globalPos)) {
            QCoreApplication::postEvent(widget, new QEvent(QEvent::Leave));
            if (widget->testAttribute(Qt::WA_Hover)) {
                const QPoint localPos = widget->mapFromGlobal(globalPos);
                const QPoint scenePos = widget->window()->mapFromGlobal(globalPos);
                static constexpr const auto oldPos = QPoint{};
                const Qt::KeyboardModifiers modifiers = QGuiApplication::keyboardModifiers();
#if (QT_VERSION >= QT_VERSION_CHECK(6, 4, 0))
                const auto event = new QHoverEvent(QEvent::HoverLeave, scenePos, globalPos, oldPos, modifiers);
                Q_UNUSED(localPos);
#elif (QT_VERSION >= QT_VERSION_CHECK(6, 3, 0))
                const auto event =  new QHoverEvent(QEvent::HoverLeave, localPos, globalPos, oldPos, modifiers);
                Q_UNUSED(scenePos);
#else
                const auto event =  new QHoverEvent(QEvent::HoverLeave, localPos, oldPos, modifiers);
                Q_UNUSED(scenePos);
#endif
                QCoreApplication::postEvent(widget, event);
            }
        }
    });
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    m_core = new QEmbyCore(this);

    
    m_trayManager = new TrayManager(this);
    connect(m_trayManager, &TrayManager::showMainRequested, this, [this]() {
        showNormal();
        activateWindow();

        
        
        if (m_wasPausedByTray) {
            m_wasPausedByTray = false;
            QTimer::singleShot(500, this, [this]() {
                if (auto *player = m_homeView->activePlayerView()) {
                    player->resumePlayback();
                }
            });
        }
    });
    connect(m_trayManager, &TrayManager::quitRequested, this, [this]() {
        m_realQuit = true; 
        
        if (auto *player = m_homeView->activePlayerView()) {
            player->stopAndReport();
            
            QElapsedTimer wait;
            wait.start();
            while (wait.elapsed() < 500) {
                QCoreApplication::processEvents(QEventLoop::AllEvents, 50);
            }
        }
        if(m_core && m_core->authService()) {
            m_core->authService()->logout();
        }
        qApp->quit(); 
    });
    

    
    m_backClickTimer.invalidate();

#if (defined(Q_OS_MACOS) || defined(Q_OS_MAC)) && \
    (QT_VERSION >= QT_VERSION_CHECK(6, 9, 0))
    setWindowFlag(Qt::ExpandedClientAreaHint, true);
    setWindowFlag(Qt::NoTitleBarBackgroundHint, true);
    setAttribute(Qt::WA_ContentsMarginsRespectsSafeArea, false);
#endif

    auto agent = new QWK::WidgetWindowAgent(this);
    agent->setup(this);
#if defined(Q_OS_MACOS) || defined(Q_OS_MAC)
    agent->setWindowAttribute("no-system-buttons", false);
#endif

    QPalette pal = palette();
    pal.setColor(QPalette::Window, QColor(241, 245, 249)); 
    setPalette(pal);
    setAutoFillBackground(true);

    
    auto titleLabel = new QLabel(qApp->applicationName());
    titleLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop); 
    titleLabel->setObjectName(QStringLiteral("win-title-label"));
    titleLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
    titleLabel->setContentsMargins(0, 5, 0, 0);

    auto iconButton = new QWK::WindowButton();
    iconButton->setObjectName(QStringLiteral("icon-button"));
    iconButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    iconButton->setIconNormal(qApp->windowIcon());
    iconButton->setIconSize(QSize(16, 16));

    auto themeButton = new QWK::WindowButton();
    themeButton->setCheckable(true);
    themeButton->setObjectName(QStringLiteral("theme-button"));
    themeButton->setProperty("system-button", true);
    themeButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    themeButton->setIconNormal(QIcon(":/svg/moon.svg"));
    themeButton->setIconSize(QSize(15, 15));
    themeButton->setChecked(true);

    auto minButton = new QWK::WindowButton();
    minButton->setObjectName(QStringLiteral("min-button"));
    minButton->setProperty("system-button", true);
    minButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

    auto maxButton = new QWK::WindowButton();
    maxButton->setCheckable(true);
    maxButton->setObjectName(QStringLiteral("max-button"));
    maxButton->setProperty("system-button", true);
    maxButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

    auto closeButton = new QWK::WindowButton();
    closeButton->setObjectName(QStringLiteral("close-button"));
    closeButton->setProperty("system-button", true);
    closeButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);

    auto backButton = new QWK::WindowButton();
    backButton->setObjectName(QStringLiteral("back-button"));
    backButton->setProperty("system-button", true);
    backButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    backButton->setShortcut(QKeySequence::Back);
    backButton->hide();

    auto homeButton = new QWK::WindowButton();
    homeButton->setObjectName(QStringLiteral("home-button"));
    homeButton->setProperty("system-button", true);
    homeButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    homeButton->hide();

    auto favButton = new QWK::WindowButton();
    favButton->setObjectName(QStringLiteral("fav-button"));
    favButton->setProperty("system-button", true);
    favButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
    favButton->hide();

    
    
    
    connect(backButton, &QWK::WindowButton::clicked, this, [this]() {
        if (m_viewStack->currentWidget() == m_homeView) {
            if (m_homeView->canNavigateBack()) {
                
                m_homeView->navigateBack();
                m_backClickTimer.invalidate(); 
            } else if (m_homeView->canGoHome()) {
                
                m_homeView->goHome();
                m_backClickTimer.invalidate();
            } else {
                
                if (m_backClickTimer.isValid() && m_backClickTimer.elapsed() < 2000) {
                    
                    m_backClickTimer.invalidate(); 
                    navigateToLogin(); 
                } else {
                    
                    m_backClickTimer.start();
                    ModernToast::showMessage(tr("Press Back again to logout"));
                }
            }
        }
    });

    connect(homeButton, &QWK::WindowButton::clicked, this, [this]() {
        if (m_viewStack->currentWidget() == m_homeView) {
            
            if (!m_homeView->canGoHome()) {
                ModernToast::showMessage(tr("Refreshing Home..."), 1000);
            }
            m_homeView->goHome();
        }
    });

    connect(favButton, &QWK::WindowButton::clicked, this, [this]() {
        if (m_viewStack->currentWidget() == m_homeView) {
            
            if (!m_homeView->canGoFav()) {
                ModernToast::showMessage(tr("Refreshing Favorites..."), 1000);
            }
            m_homeView->goFav();
        }
    });

    auto windowBar = new QWK::WindowBar();
#if defined(Q_OS_MACOS) || defined(Q_OS_MAC)
    windowBar->layout()->setContentsMargins(80, 0, 0, 0);
#endif
    windowBar->setIconButton(iconButton);
    windowBar->setPinButton(themeButton);
#if !defined(Q_OS_MACOS) && !defined(Q_OS_MAC)
    windowBar->setMinButton(minButton);
    windowBar->setMaxButton(maxButton);
    windowBar->setCloseButton(closeButton);
#else
    minButton->setParent(windowBar);
    maxButton->setParent(windowBar);
    closeButton->setParent(windowBar);
    minButton->hide();
    maxButton->hide();
    closeButton->hide();
#endif
    windowBar->setTitleLabel(titleLabel);
#if !defined(Q_OS_MACOS) && !defined(Q_OS_MAC)
    windowBar->setBackButton(backButton);
    windowBar->setHomeButton(homeButton);
    windowBar->setFavButton(favButton);
#endif
    titleLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
    windowBar->setHostWidget(this);

    auto *centerContainer = new QWidget(windowBar);
    auto *centerLayout = new QHBoxLayout(centerContainer);
#if defined(Q_OS_MACOS) || defined(Q_OS_MAC)
    centerLayout->setContentsMargins(0, 1, 0, 1);
#else
    centerLayout->setContentsMargins(0, 0, 0, 0);
#endif
    centerLayout->setSpacing(0);

    
    auto *globalSearchBox = new QLineEdit(centerContainer);
    m_globalSearchBox = globalSearchBox;
    globalSearchBox->setObjectName("titlebar-search");
    globalSearchBox->setPlaceholderText(tr("Search..."));
#if defined(Q_OS_MACOS) || defined(Q_OS_MAC)
    globalSearchBox->setFixedSize(380, 30);
#else
    globalSearchBox->setFixedSize(380, 32); 
#endif
    globalSearchBox->setClearButtonEnabled(true);
    
    auto *searchAction = new QAction(QIcon(":/svg/light/search.svg"), tr("Search"), this);
    globalSearchBox->addAction(searchAction, QLineEdit::LeadingPosition);
    globalSearchBox->hide();

    auto *macCenteredTitleLabel = new QLabel(centerContainer);
    macCenteredTitleLabel->setObjectName("mac-title-label");
    macCenteredTitleLabel->setAlignment(Qt::AlignCenter);
    macCenteredTitleLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
    macCenteredTitleLabel->hide();

    connect(globalSearchBox, &QLineEdit::returnPressed, this, [this]() {
        if (!m_globalSearchBox) {
            qWarning() << "Global search submit ignored: search box was destroyed";
            return;
        }
        submitGlobalSearch(m_globalSearchBox->text());
    });

#if defined(Q_OS_MACOS) || defined(Q_OS_MAC)
    auto *macTitlebarNavSpacer = new QWidget(centerContainer);
    macTitlebarNavSpacer->setObjectName("mac-titlebar-nav-spacer");
    macTitlebarNavSpacer->setFixedWidth(150);
    macTitlebarNavSpacer->hide();

    auto *macTitlebarNav = new QWidget(centerContainer);
    macTitlebarNav->setObjectName("mac-titlebar-nav");
    auto *macTitlebarNavLayout = new QHBoxLayout(macTitlebarNav);
    macTitlebarNavLayout->setContentsMargins(0, 0, 0, 0);
    macTitlebarNavLayout->setSpacing(0);
    macTitlebarNavLayout->addWidget(backButton);
    macTitlebarNavLayout->addWidget(homeButton);
    macTitlebarNavLayout->addWidget(favButton);
    macTitlebarNav->setFixedWidth(150);
    macTitlebarNav->hide();

    centerLayout->addWidget(macTitlebarNavSpacer);
#endif
    centerLayout->addStretch();
    centerLayout->addWidget(globalSearchBox, 0, Qt::AlignVCenter); 
    centerLayout->addWidget(macCenteredTitleLabel, 0, Qt::AlignVCenter);
    centerLayout->addStretch();
#if defined(Q_OS_MACOS) || defined(Q_OS_MAC)
    centerLayout->addWidget(macTitlebarNav);
#endif
    centerContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
    windowBar->setCenterWidget(centerContainer);

    agent->setTitleBar(windowBar);

    agent->setHitTestVisible(themeButton, true);
    agent->setHitTestVisible(backButton, true);
    agent->setHitTestVisible(homeButton, true);
    agent->setHitTestVisible(favButton, true);
    agent->setHitTestVisible(globalSearchBox, true); 
    agent->setSystemButton(QWK::WindowAgentBase::WindowIcon, iconButton);
#if !defined(Q_OS_MACOS) && !defined(Q_OS_MAC)
    agent->setSystemButton(QWK::WindowAgentBase::Minimize, minButton);
    agent->setSystemButton(QWK::WindowAgentBase::Maximize, maxButton);
    agent->setSystemButton(QWK::WindowAgentBase::Close, closeButton);
#endif
#if defined(Q_OS_MAC)
    agent->setSystemButtonAreaCallback([](const QSize &size) {
        return QRect(QPoint(0, 0), QSize(80, size.height()));
    });
#endif

    auto *mainContainer = new QWidget(this);
    mainContainer->setObjectName(QStringLiteral("main-window-content"));
    auto *mainLayout = new QVBoxLayout(mainContainer);
    mainLayout->setContentsMargins(0, 0, 0, 0);
    mainLayout->setSpacing(0);
    mainLayout->addWidget(windowBar, 0);

    m_viewStack = new QStackedWidget(mainContainer);
    m_viewStack->setObjectName("main-view-stack"); 
    m_viewStack->setPalette(pal);
    m_viewStack->setAutoFillBackground(true);
    mainLayout->addWidget(m_viewStack, 1);
    setCentralWidget(mainContainer);

    m_loginView = new LoginView(m_core, this);
    m_homeView = new HomeView(m_core, this);
    setupGlobalSearchHistory();

    m_viewStack->addWidget(m_loginView);
    m_viewStack->addWidget(m_homeView);

    
    connect(m_viewStack, &QStackedWidget::currentChanged, this, [this](int index) {
        QWidget *currentView = m_viewStack->widget(index);
        if (!currentView) return;

        bool showSearch = currentView->property("showGlobalSearch").toBool();
        if (m_globalSearchBox) {
            m_globalSearchBox->setVisible(showSearch);
        } else {
            qWarning() << "Global search box missing during view change"
                       << "index:" << index
                       << "view:" << currentView;
        }
        if (!showSearch) {
            hideGlobalSearchTransientUi();
        }
        
        auto back = findChild<QWK::WindowButton*>("back-button");
        auto icon = findChild<QWK::WindowButton*>("icon-button");
        auto home = findChild<QWK::WindowButton*>("home-button");
        auto fav = findChild<QWK::WindowButton*>("fav-button");
        auto title = findChild<QLabel*>("win-title-label");
        auto macTitle = findChild<QLabel*>("mac-title-label");
        auto macNav = findChild<QWidget*>("mac-titlebar-nav");
        auto macNavSpacer = findChild<QWidget*>("mac-titlebar-nav-spacer");
        
        
        if (currentView == m_homeView) {
            if (back) {
                back->setVisible(true);
                
                back->setEnabled(true); 
            }
            if (icon) icon->setVisible(false);
            if (home)
            {
                home->setVisible(true);
                
                home->setEnabled(true); 
            }
            if (fav)
            {
                fav->setVisible(true);
                
                fav->setEnabled(true); 
            }
        } else {
            
            bool showBack = currentView->property("showGlobalBack").toBool();
            if (back) {
                back->setVisible(showBack);
                back->setEnabled(true); 
            }
            if (icon) icon->setVisible(!showBack);
            bool showHome = currentView->property("showGlobalHome").toBool();
            if (home)
            {
                home->setVisible(showHome);
                home->setEnabled(true);
            }
            bool showFav = currentView->property("showGlobalFav").toBool();
            if (fav)
            {
                fav->setVisible(showFav);
                fav->setEnabled(true);
            }
        }

        QVariant customTitle = currentView->property("viewTitle");
        if (customTitle.isValid()) {
            if (title) {
                title->setText(customTitle.toString());
            }
            if (macTitle) {
                macTitle->setText(customTitle.toString());
            }
        }

#if defined(Q_OS_MACOS) || defined(Q_OS_MAC)
        const bool useCenteredLoginTitle = (currentView == m_loginView);
        const bool showMacTitlebarNav = (currentView == m_homeView);
        if (icon) {
            icon->setVisible(false);
        }
        if (title) {
            title->setVisible(false);
        }
        if (macTitle) {
            macTitle->setVisible(useCenteredLoginTitle);
        }
        if (macNav) {
            macNav->setVisible(showMacTitlebarNav);
        }
        if (macNavSpacer) {
            macNavSpacer->setVisible(showMacTitlebarNav);
        }
#else
        if (macTitle) {
            macTitle->hide();
        }
#endif
    });

    
    connect(m_homeView, &HomeView::immersiveStateChanged, this, [windowBar, agent](bool isImmersive) {
        windowBar->setVisible(!isImmersive);
#if defined(Q_OS_MACOS) || defined(Q_OS_MAC)
        if (!isImmersive) {
            agent->setWindowAttribute("no-system-buttons", false);
        }
#else
        Q_UNUSED(agent);
#endif
    });

    connect(m_homeView, &HomeView::playerChromeVisibilityChanged, this,
            [this, agent](bool visible) {
#if defined(Q_OS_MACOS) || defined(Q_OS_MAC)
                if (m_homeView && m_homeView->activePlayerView()) {
                    agent->setWindowAttribute("no-system-buttons", !visible);
                }
#else
                Q_UNUSED(visible);
                Q_UNUSED(agent);
#endif
            });

    
    connect(m_homeView, &HomeView::canNavigateBackChanged, this, [this](bool canBack) {
        
        
        
        
        
    });

    connect(m_homeView, &HomeView::homeContentSwitched, this, [this] () {
        
        
        
        
        
        
        
    });

    connect(m_loginView, &LoginView::loginCompleted, this, &MainWindow::navigateToHome);
    connect(m_homeView, &HomeView::logoutRequested, this, &MainWindow::navigateToLogin);


    connect(windowBar, &QWK::WindowBar::pinRequested, this, [this, themeButton](bool checked) {
        themeButton->setChecked(checked);

        hideGlobalSearchTransientUi();

        
        QString newMode = checked ? "dark" : "light";
        
        themeButton->blockSignals(true);
        if (checked) {
            themeButton->setIconNormal(QIcon(":/svg/moon.svg"));
        } else {
            themeButton->setIconNormal(QIcon(":/svg/sun.svg"));
        }
        themeButton->blockSignals(false);

        
        bool reduceAnimations = ConfigStore::instance()->get<bool>(ConfigKeys::UiAnimations, false);
        if (reduceAnimations) {
            m_themeAnimating = true;
            ConfigStore::instance()->set(ConfigKeys::ThemeMode, newMode);
            m_themeAnimating = false;
            return;
        }

        
        QPixmap snapshot = this->grab();

        
        QPoint center = themeButton->mapTo(this, themeButton->rect().center());

        
        auto transition = new ThemeTransitionWidget(snapshot, center, this);
        transition->setGeometry(this->rect());
        transition->raise(); 
        transition->show();

        
        int maxRadius = qMax(
                            qMax(QLineF(center, QPoint(0, 0)).length(), QLineF(center, QPoint(width(), 0)).length()),
                            qMax(QLineF(center, QPoint(0, height())).length(), QLineF(center, QPoint(width(), height())).length())
                            ) + 10; 

        
        m_themeAnimating = true; 
        ConfigStore::instance()->set(ConfigKeys::ThemeMode, newMode);
        m_themeAnimating = false;

        
        auto anim = new QPropertyAnimation(transition, "radius", transition);
        anim->setDuration(450); 
        anim->setStartValue(0);
        anim->setEndValue(maxRadius);
        
        anim->setEasingCurve(QEasingCurve::InOutCubic);

        
        connect(anim, &QPropertyAnimation::finished, transition, &QObject::deleteLater);
        anim->start(QAbstractAnimation::DeleteWhenStopped);
    });

    connect(windowBar, &QWK::WindowBar::minimizeRequested, this, [this]() {
        hideGlobalSearchTransientUi();
        showMinimized();
    });
    connect(windowBar, &QWK::WindowBar::maximizeRequested, this, [this, maxButton](bool max) {
        if (max) {
            showMaximized();
        } else {
            showNormal();
            
            QRect screenGeo = screen()->availableGeometry();
            int w = 1280, h = 800;
            setGeometry(
                screenGeo.x() + (screenGeo.width() - w) / 2,
                screenGeo.y() + (screenGeo.height() - h) / 2,
                w, h);
        }
        emulateLeaveEvent(maxButton);
    });
    
    
    connect(windowBar, &QWK::WindowBar::closeRequested, this, &QWidget::close);

    
    QString savedThemeMode = ConfigStore::instance()->get<QString>(ConfigKeys::ThemeMode, "system");
    ThemeManager::instance()->applyThemeMode(savedThemeMode);
    
    bool isDark = ThemeManager::instance()->isDarkMode();
    themeButton->setChecked(isDark);
    themeButton->setIconNormal(isDark ? QIcon(":/svg/moon.svg") : QIcon(":/svg/sun.svg"));

    
    connect(ConfigStore::instance(), &ConfigStore::valueChanged, this,
            [this, themeButton](const QString &key, const QVariant &newValue) {
        
        if (key == ConfigKeys::FontSize) {
            
            ThemeManager::instance()->setTheme(ThemeManager::instance()->currentTheme());
            return;
        }

        
        if (key != ConfigKeys::ThemeMode) return;
        QString mode = newValue.toString();
        hideGlobalSearchTransientUi();

        
        if (m_themeAnimating) {
            ThemeManager::instance()->applyThemeMode(mode);
            bool dark = ThemeManager::instance()->isDarkMode();
            themeButton->blockSignals(true);
            themeButton->setChecked(dark);
            themeButton->setIconNormal(dark ? QIcon(":/svg/moon.svg") : QIcon(":/svg/sun.svg"));
            themeButton->blockSignals(false);
            return;
        }

        
        bool reduceAnimations = ConfigStore::instance()->get<bool>(ConfigKeys::UiAnimations, false);
        if (!reduceAnimations) {
            
            QPixmap snapshot = this->grab();
            QPoint center = this->rect().center(); 

            
            ThemeManager::instance()->applyThemeMode(mode);
            bool dark = ThemeManager::instance()->isDarkMode();
            themeButton->blockSignals(true);
            themeButton->setChecked(dark);
            themeButton->setIconNormal(dark ? QIcon(":/svg/moon.svg") : QIcon(":/svg/sun.svg"));
            themeButton->blockSignals(false);

            
            auto transition = new ThemeTransitionWidget(snapshot, center, this);
            transition->setGeometry(this->rect());
            transition->raise();
            transition->show();

            int maxRadius = qMax(
                qMax(QLineF(center, QPoint(0, 0)).length(), QLineF(center, QPoint(width(), 0)).length()),
                qMax(QLineF(center, QPoint(0, height())).length(), QLineF(center, QPoint(width(), height())).length())
            ) + 10;

            
            auto anim = new QPropertyAnimation(transition, "radius", transition);
            anim->setDuration(450);
            anim->setStartValue(0);
            anim->setEndValue(maxRadius);
            anim->setEasingCurve(QEasingCurve::InOutCubic);
            connect(anim, &QPropertyAnimation::finished, transition, &QObject::deleteLater);
            anim->start(QAbstractAnimation::DeleteWhenStopped);
        } else {
            
            ThemeManager::instance()->applyThemeMode(mode);
            bool dark = ThemeManager::instance()->isDarkMode();
            themeButton->blockSignals(true);
            themeButton->setChecked(dark);
            themeButton->setIconNormal(dark ? QIcon(":/svg/moon.svg") : QIcon(":/svg/sun.svg"));
            themeButton->blockSignals(false);
        }
    });

    
    minButton->hide();
    maxButton->hide();
    m_viewStack->setCurrentWidget(m_loginView);
#if defined(Q_OS_MACOS) || defined(Q_OS_MAC)
    iconButton->hide();
    titleLabel->hide();
    macCenteredTitleLabel->setText(m_loginView->property("viewTitle").toString());
    macCenteredTitleLabel->show();
    if (macTitlebarNav) {
        macTitlebarNav->hide();
    }
    if (macTitlebarNavSpacer) {
        macTitlebarNavSpacer->hide();
    }
#endif
    setMinimumSize(900, 600);
    setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
    const QString startupWindowState = ConfigStore::instance()->get<QString>(
        ConfigKeys::StartupWindowState, "normal");
    if (startupWindowState == "maximized") {
        setWindowState(windowState() | Qt::WindowMaximized);
    } else {
        resize(m_defaultWidth, m_defaultHeight);
    }

    
    
    
    qApp->installEventFilter(this);
    connect(qApp, &QGuiApplication::applicationStateChanged, this,
            [this](Qt::ApplicationState state) {
                if (state != Qt::ApplicationActive) {
                    hideGlobalSearchTransientUi();
                }
            });
}

MainWindow::~MainWindow() {}

void MainWindow::setupGlobalSearchHistory()
{
    if (!m_globalSearchBox) {
        return;
    }

    m_globalSearchModel = new QStringListModel(this);
    m_globalSearchCompleter = new QCompleter(m_globalSearchModel, this);
    m_globalSearchCompleter->setCaseSensitivity(Qt::CaseInsensitive);
    m_globalSearchCompleter->setFilterMode(Qt::MatchContains);
    m_globalSearchCompleter->setCompletionMode(QCompleter::PopupCompletion);
    m_globalSearchCompleter->setMaxVisibleItems(8);
    m_globalSearchCompleter->setPopup(new SearchCompleterPopup());
    if (auto *popup = qobject_cast<SearchCompleterPopup *>(
            m_globalSearchCompleter->popup())) {
        popup->setMaxVisibleRows(m_globalSearchCompleter->maxVisibleItems());
    }
    m_globalSearchBox->setCompleter(m_globalSearchCompleter);

    m_globalSearchHistoryPopup = new SearchHistoryPopup(this);
    connect(m_globalSearchHistoryPopup, &SearchHistoryPopup::termActivated, this,
            [this](const QString &term) {
                if (!m_globalSearchBox) {
                    qWarning() << "History term ignored: search box was destroyed";
                    return;
                }
                m_globalSearchBox->setText(term);
                submitGlobalSearch(term);
            });
    connect(m_globalSearchHistoryPopup, &SearchHistoryPopup::clearHistoryRequested, this,
            [this]() {
                SearchHistoryManager::instance()->clearHistory(currentSearchServerId());
            });
    connect(m_globalSearchHistoryPopup, &SearchHistoryPopup::removeHistoryTermRequested,
            this, [this](const QString &term) {
                SearchHistoryManager::instance()->removeHistoryTerm(
                    currentSearchServerId(), term);
            });

    connect(m_globalSearchBox.data(), &QLineEdit::textEdited, this,
            [this](const QString &text) {
                updateGlobalSearchCompleter(text);
                hideGlobalSearchTransientUi();
            });

    connect(SearchHistoryManager::instance(), &SearchHistoryManager::historyChanged,
            this, [this](const QString &serverId) {
                if (serverId == currentSearchServerId()) {
                    updateGlobalSearchCompleter(m_globalSearchBox
                                                    ? m_globalSearchBox->text()
                                                    : QString());
                }
            });
    connect(SearchHistoryManager::instance(), &SearchHistoryManager::enabledChanged,
            this, [this](bool enabled) {
                Q_UNUSED(enabled);
                updateGlobalSearchCompleter(m_globalSearchBox
                                                ? m_globalSearchBox->text()
                                                : QString());
                hideGlobalSearchTransientUi();
            });
    connect(SearchHistoryManager::instance(),
            &SearchHistoryManager::autocompleteEnabledChanged, this,
            [this](bool ) {
                updateGlobalSearchCompleter(m_globalSearchBox
                                                ? m_globalSearchBox->text()
                                                : QString());
            });

    if (m_core && m_core->serverManager()) {
        connect(m_core->serverManager(), &ServerManager::activeServerChanged, this,
                [this](const ServerProfile &profile) {
                    Q_UNUSED(profile);
                    updateGlobalSearchCompleter(m_globalSearchBox
                                                    ? m_globalSearchBox->text()
                                                    : QString());
                    hideGlobalSearchTransientUi();
                });
    }

    updateGlobalSearchCompleter();
}

void MainWindow::hideGlobalSearchTransientUi()
{
    if (m_globalSearchHistoryPopup) {
        const bool immediateHide =
            QGuiApplication::applicationState() != Qt::ApplicationActive ||
            !isVisible() || isMinimized() || !isActiveWindow();
        m_globalSearchHistoryPopup->dismiss(immediateHide);
    }
    if (m_globalSearchCompleter && m_globalSearchCompleter->popup()) {
        m_globalSearchCompleter->popup()->hide();
    }
}

void MainWindow::updateGlobalSearchCompleter(const QString &text)
{
    if (!m_globalSearchModel || !m_globalSearchCompleter || !m_globalSearchBox) {
        return;
    }

    const QStringList suggestions =
        SearchHistoryManager::instance()->completionSuggestions(
            currentSearchServerId(), text, 8);
    m_globalSearchModel->setStringList(suggestions);

    if (!SearchHistoryManager::instance()->isAutocompleteEnabled() ||
        text.trimmed().isEmpty() ||
        suggestions.isEmpty() || !m_globalSearchBox->hasFocus()) {
        if (m_globalSearchCompleter->popup()) {
            m_globalSearchCompleter->popup()->hide();
        }
        return;
    }

    if (auto *popup = qobject_cast<SearchCompleterPopup *>(
            m_globalSearchCompleter->popup())) {
        popup->setHighlightText(text);
        popup->syncWidthToAnchor(m_globalSearchBox.data());
    }

    m_globalSearchCompleter->setCompletionPrefix(text);
    if (auto *popup = qobject_cast<SearchCompleterPopup *>(
            m_globalSearchCompleter->popup())) {
        m_globalSearchCompleter->complete(
            popup->popupRectForAnchor(m_globalSearchBox.data()));
        return;
    }

    m_globalSearchCompleter->complete();
}

void MainWindow::showGlobalSearchHistoryPopup(const QString &filterText)
{
    if (!m_globalSearchBox || !m_globalSearchHistoryPopup ||
        !SearchHistoryManager::instance()->isEnabled()) {
        return;
    }

    if (!isVisible() || isMinimized() || !m_globalSearchBox->isVisible() ||
        !m_globalSearchBox->hasFocus() ||
        QGuiApplication::applicationState() != Qt::ApplicationActive ||
        !isActiveWindow()) {
        hideGlobalSearchTransientUi();
        return;
    }

    const QString serverId = currentSearchServerId();
    const auto historyEntries =
        SearchHistoryManager::instance()->historyEntries(serverId, filterText);

    m_globalSearchHistoryPopup->setEntries(historyEntries);
    if (!m_globalSearchHistoryPopup->hasContent()) {
        hideGlobalSearchTransientUi();
        return;
    }

    m_globalSearchHistoryPopup->dismiss(true);
    if (m_globalSearchCompleter && m_globalSearchCompleter->popup()) {
        m_globalSearchCompleter->popup()->hide();
    }
    m_globalSearchHistoryPopup->showBelow(m_globalSearchBox.data());
}

void MainWindow::submitGlobalSearch(const QString &query)
{
    if (!m_homeView || m_viewStack->currentWidget() != m_homeView) {
        return;
    }

    const QString trimmedQuery = query.trimmed();
    if (trimmedQuery.isEmpty()) {
        return;
    }

    hideGlobalSearchTransientUi();

    m_homeView->triggerSearch(trimmedQuery);
    if (m_globalSearchBox) {
        m_globalSearchBox->clear();
    }
    hideGlobalSearchTransientUi();
}

QString MainWindow::currentSearchServerId() const
{
    if (!m_core || !m_core->serverManager()) {
        return {};
    }
    return m_core->serverManager()->activeProfile().id;
}

void MainWindow::navigateToHome()
{
    if (m_viewTransitionInProgress) {
        qWarning() << "navigateToHome ignored: view transition already in progress";
        return;
    }
    if (m_viewStack && m_viewStack->currentWidget() == m_homeView) {
        return;
    }
    m_viewTransitionInProgress = true;

    
    m_homeView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    
    bool reduceAnimations = ConfigStore::instance()->get<bool>(ConfigKeys::UiAnimations, false);
    if (reduceAnimations) {
        setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
        setMinimumSize(900, 600);
#if !defined(Q_OS_MACOS) && !defined(Q_OS_MAC)
        if (auto* minBtn = findChild<QWidget*>("min-button")) minBtn->show();
        if (auto* maxBtn = findChild<QWidget*>("max-button")) maxBtn->show();
#endif

        m_loginView->setGraphicsEffect(nullptr);
        m_homeView->setGraphicsEffect(nullptr);
        m_viewStack->setCurrentWidget(m_homeView);
        m_viewTransitionInProgress = false;
        return;
    }

    setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
    setMinimumSize(900, 600);
#if !defined(Q_OS_MACOS) && !defined(Q_OS_MAC)
    if (auto* minBtn = findChild<QWidget*>("min-button")) minBtn->show();
    if (auto* maxBtn = findChild<QWidget*>("max-button")) maxBtn->show();
#endif

    m_loginView->setGraphicsEffect(nullptr);
    auto *homeOpacity = new QGraphicsOpacityEffect(m_homeView);
    homeOpacity->setOpacity(0.0);
    m_homeView->setGraphicsEffect(homeOpacity);
    m_viewStack->setCurrentWidget(m_homeView);

    auto *fadeIn = new QPropertyAnimation(homeOpacity, "opacity", this);
    fadeIn->setDuration(250);
    fadeIn->setStartValue(0.0);
    fadeIn->setEndValue(1.0);
    fadeIn->setEasingCurve(QEasingCurve::OutQuad);

    connect(fadeIn, &QPropertyAnimation::finished, this, [this]() {
        m_homeView->setGraphicsEffect(nullptr);
        m_viewTransitionInProgress = false;
    });
    fadeIn->start(QAbstractAnimation::DeleteWhenStopped);
}

void MainWindow::navigateToLogin() {
    if (m_viewTransitionInProgress) {
        qWarning() << "navigateToLogin ignored: view transition already in progress";
        return;
    }
    if (m_viewStack && m_viewStack->currentWidget() == m_loginView) {
        return;
    }
    m_viewTransitionInProgress = true;

    
    
    m_homeView->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);

    
    bool reduceAnimations = ConfigStore::instance()->get<bool>(ConfigKeys::UiAnimations, false);
    if (reduceAnimations) {
#if !defined(Q_OS_MACOS) && !defined(Q_OS_MAC)
        if (auto* m = findChild<QWidget*>("min-button")) m->hide();
        if (auto* x = findChild<QWidget*>("max-button")) x->hide();
#endif

        setMinimumSize(900, 600);
        setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);

        m_homeView->setGraphicsEffect(nullptr);
        m_loginView->setGraphicsEffect(nullptr);
        m_viewStack->setCurrentWidget(m_loginView);

        m_core->authService()->logout();
        m_viewTransitionInProgress = false;
        return;
    }

    setMinimumSize(900, 600);
    setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
#if !defined(Q_OS_MACOS) && !defined(Q_OS_MAC)
    if (auto* m = findChild<QWidget*>("min-button")) m->hide();
    if (auto* x = findChild<QWidget*>("max-button")) x->hide();
#endif

    m_homeView->setGraphicsEffect(nullptr);
    auto *loginOpacity = new QGraphicsOpacityEffect(m_loginView);
    loginOpacity->setOpacity(0.0);
    m_loginView->setGraphicsEffect(loginOpacity);
    m_viewStack->setCurrentWidget(m_loginView);

    auto *fadeIn = new QPropertyAnimation(loginOpacity, "opacity", this);
    fadeIn->setDuration(250);
    fadeIn->setStartValue(0.0);
    fadeIn->setEndValue(1.0);
    fadeIn->setEasingCurve(QEasingCurve::OutQuad);

    connect(fadeIn, &QPropertyAnimation::finished, this, [this]() {
        m_loginView->setGraphicsEffect(nullptr);
        m_core->authService()->logout();
        m_viewTransitionInProgress = false;
    });
    fadeIn->start(QAbstractAnimation::DeleteWhenStopped);
}

bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
    if (watched == qApp && event->type() == QEvent::ApplicationStateChange) {
        if (QGuiApplication::applicationState() != Qt::ApplicationActive) {
            hideGlobalSearchTransientUi();
        }
    }

    if (watched == this) {
        if (event->type() == QEvent::WindowDeactivate ||
            event->type() == QEvent::Move ||
            event->type() == QEvent::Resize ||
            event->type() == QEvent::Hide ||
            event->type() == QEvent::Close ||
            event->type() == QEvent::WindowStateChange) {
            hideGlobalSearchTransientUi();
        }
    }

    if (watched == m_globalSearchHistoryPopup && m_globalSearchHistoryPopup) {
        if (event->type() == QEvent::WindowDeactivate ||
            event->type() == QEvent::Hide ||
            event->type() == QEvent::Close) {
            hideGlobalSearchTransientUi();
        }
    }

    if (m_globalSearchBox && watched == m_globalSearchBox.data()) {
        if (event->type() == QEvent::FocusIn) {
            auto *focusEvent = static_cast<QFocusEvent *>(event);
            if (focusEvent->reason() != Qt::MouseFocusReason &&
                m_globalSearchBox->text().trimmed().isEmpty()) {
                QTimer::singleShot(0, this, [this]() {
                    showGlobalSearchHistoryPopup();
                });
            }
        } else if (event->type() == QEvent::MouseButtonPress) {
            if (m_globalSearchBox->text().trimmed().isEmpty()) {
                QTimer::singleShot(0, this, [this]() {
                    showGlobalSearchHistoryPopup();
                });
            }
        } else if (event->type() == QEvent::KeyPress) {
            auto *keyEvent = static_cast<QKeyEvent *>(event);
            if (keyEvent->key() == Qt::Key_Down) {
                showGlobalSearchHistoryPopup(m_globalSearchBox->text());
                return true;
            }
        } else if (event->type() == QEvent::Hide) {
            hideGlobalSearchTransientUi();
        }
    }

    if ((event->type() == QEvent::MouseButtonPress ||
         event->type() == QEvent::MouseButtonDblClick) &&
        m_globalSearchHistoryPopup && m_globalSearchHistoryPopup->isVisible() &&
        m_globalSearchBox) {
        auto *mouseEvent = static_cast<QMouseEvent *>(event);
        const QPoint globalPos = mouseEvent->globalPosition().toPoint();
        const QRect popupRect(m_globalSearchHistoryPopup->mapToGlobal(QPoint(0, 0)),
                              m_globalSearchHistoryPopup->size());
        const QRect searchRect(m_globalSearchBox->mapToGlobal(QPoint(0, 0)),
                               m_globalSearchBox->size());
        if (!popupRect.contains(globalPos) && !searchRect.contains(globalPos)) {
            hideGlobalSearchTransientUi();
        }
    }

    
    if (event->type() == QEvent::MouseButtonRelease) {
        auto *mouseEvent = static_cast<QMouseEvent *>(event);
        if (mouseEvent->button() == Qt::BackButton || mouseEvent->button() == Qt::XButton1) {
            
            
            if (auto *modal = QApplication::activeModalWidget()) {
                if (auto *dlg = qobject_cast<QDialog *>(modal)) {
                    dlg->reject();
                }
                return true;
            }
            auto back = findChild<QWK::WindowButton*>("back-button");
            
            if (back && back->isVisible()) {
                back->click(); 
                return true;   
            }
        }
    } else if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick) {
        auto *mouseEvent = static_cast<QMouseEvent *>(event);
        if (mouseEvent->button() == Qt::BackButton || mouseEvent->button() == Qt::XButton1) {
            auto back = findChild<QWK::WindowButton*>("back-button");
            if (back && back->isVisible()) {
                return true; 
            }
        }
    }

    if (ContextMenuUtils::showStyledTextContextMenu(watched, event)) {
        return true;
    }
    if (ContextMenuUtils::showStyledLabelContextMenu(watched, event)) {
        return true;
    }

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

void MainWindow::closeEvent(QCloseEvent *event)
{
    hideGlobalSearchTransientUi();

    
    bool useTray = ConfigStore::instance()->get<bool>(ConfigKeys::CloseToTray, false);

    
    if (!m_realQuit && useTray && QSystemTrayIcon::isSystemTrayAvailable()) {
        
        if (auto *player = m_homeView->activePlayerView()) {
            if (player->isMediaPlaying()) {
                player->pausePlayback();
                m_wasPausedByTray = true;
            }
        }

        hide();             
        event->ignore();    
    } else {
        
        if (auto *player = m_homeView->activePlayerView()) {
            player->stopAndReport();
            
            QElapsedTimer wait;
            wait.start();
            while (wait.elapsed() < 500) {
                QCoreApplication::processEvents(QEventLoop::AllEvents, 50);
            }
        }
        event->accept();    
    }
}
