#include "windowcontroller.h"

#include <QApplication>
#include <QGuiApplication>
#include <QCursor>
#include <QLocale>
#include <QKeyEvent>
#include <QCloseEvent>
#include "cmainwnd.h"
class QApplicationPrivate;

#define WINDOW_MARGIN 8
#define SIDEBAR_WIDTH 402
#define WINMODE_WIDTH 1096
#define WINMODE_HEIGHT 688


#if defined(qApp)
#undef qApp
#endif
#define qApp (static_cast<QApplication *>(QCoreApplication::instance()))

WindowController::WindowController(QObject *parent)
{
    m_winMode = static_cast<WindowMode>(ConfigManager::getInstance()->getConfigValue("win-mode").toInt());
    m_isTopping = ConfigManager::getInstance()->getConfigValue("is-window-mode-topping").toBool();

    connect(this, &WindowController::winModeChanged, this, &WindowController::initWindowData);
    initDbusWathcer();

    // QML 窗口创建时即绑定 width/height；Wayland 不接受 0×0 几何，须在 load 前给出合法初值
    QScreen *screen = QGuiApplication::primaryScreen();
    if (screen && !screen->availableGeometry().isEmpty()) {
        m_currentScreen = screen;
        if (m_winMode == WINDOW_MODE_WINDOWMODE) {
            setWindowModePos();
        } else {
            setSideModePos();
        }
    } else {
        m_width = SIDEBAR_WIDTH;
        m_height = WINMODE_HEIGHT;
    }
}

void WindowController::setFilePathWithStart(const QString filePath)
{
    m_filePathWithStart = filePath;

    return;
}

void WindowController::onAppRestarted(const QString &message)
{
    KyInfo() << "====onAppRestarted====message" << message;
    if (m_mainWin == nullptr) {
        KyInfo() << "Error: Window ID is nullptr!" << message;
        return;
    }

    if (message == "running") {
        // 如果AI助手窗口被遮挡，则执行show操作，将窗口置于顶层
        if (!m_mainWin->isActive()) {
            showMainWindow();
        }

    } else {//当做文件路径处理
        if (!m_mainWin->isActive()) {
            showMainWindow();
        }

        QUrl url(message);
        Q_EMIT sendFile(url.path());
    }

    return;
}

void WindowController::clearWindowStyle(QObject *win)
{
    QWindow * curWin = qobject_cast<QWindow*>(win);

    if (curWin) {
        UkuiWindowHelper *winHelper = new UkuiWindowHelper(curWin);
        winHelper->removeTitleBar();
        winHelper->setSkipTaskBar(true);
    }

    return;
}

///
/// \brief WindowController::initScreenWathcer 监听屏幕分辨率变化
///
void WindowController::initScreenWathcer()
{
    KyInfo() << "initScreenWathcer start";
    m_currentScreen = getCurrentScreen();
    if (m_currentScreen == nullptr || m_currentScreen->availableGeometry().isEmpty()) {
        m_currentScreen = QGuiApplication::primaryScreen();
    }

    if (m_currentScreen == nullptr) {
        KyInfo() << "11111====m_currentScreen is nullptr====";
        return;
    }

    // 屏幕的分辨率或可用显示区域变化
    m_availableGeometryChangedConnection = connect(m_currentScreen, &QScreen::availableGeometryChanged, this, [this](const QRect &geometry) {
        KyInfo() << "22222====availableGeometryChanged====" << geometry;
        adjustForScreenChanged();
    });

    // 主屏变化
    connect(qApp, &QApplication::primaryScreenChanged, this, [this](QScreen *newPrimaryScreen) {
        if (newPrimaryScreen == nullptr || newPrimaryScreen->availableGeometry().isEmpty()) {
            KyInfo() << "33333====primaryScreen is null, ignore====";
            return;
        }

        KyInfo() << "33333====primaryScreenChanged====" << newPrimaryScreen->name() << newPrimaryScreen->availableGeometry();
        // 检查当前屏幕是否还存在于屏幕列表中
        QList<QScreen *> allScreens = QGuiApplication::screens();
        bool currentScreenExists = allScreens.contains(m_currentScreen);

        if (!currentScreenExists) {
            KyInfo() << "33333====The current screen has been removed====";
            m_currentScreen = getCurrentScreen();
            if (m_currentScreen == nullptr || m_currentScreen->availableGeometry().isEmpty()) {
                m_currentScreen = newPrimaryScreen;
            }
            KyInfo() << "33333====updated to the new current screen====" << m_currentScreen->name();
        } else {
            KyInfo() << "33333====The current screen still exists====" << m_currentScreen->name();
        }

        disconnect(m_availableGeometryChangedConnection);
        adjustForScreenChanged();

        m_availableGeometryChangedConnection = connect(m_currentScreen, &QScreen::availableGeometryChanged, this, [this](const QRect &geometry) {
            KyInfo() << "44444====availableGeometryChanged====" << geometry;
            adjustForScreenChanged();
        });
    });

    // 屏幕被添加
    connect(qApp, &QGuiApplication::screenAdded, this, [=](QScreen *screen){
        KyInfo() << "55555====screenAdded====ignore";
    });
    // 屏幕被移除
    connect(qApp, &QGuiApplication::screenRemoved, this, [=](QScreen *screen){
        KyInfo() << "66666====screenRemoved====";
        if (screen == nullptr || screen->availableGeometry().isEmpty()) {
            KyInfo() << "66666====screen is null, ignore=====";
            return;
        }

        // 检查当前屏幕是否还存在于屏幕列表中
        QList<QScreen *> allScreens = QGuiApplication::screens();
        bool currentScreenExists = allScreens.contains(m_currentScreen);

        if (currentScreenExists == false) {
           KyInfo() << "66666====The current screen has been removed====";
           m_currentScreen = QGuiApplication::primaryScreen();
           if (m_currentScreen == nullptr || m_currentScreen->availableGeometry().isEmpty()) {
               KyInfo() << "66666====get current screen failed, return====";
               return;
           }

           KyInfo() << "66666====updated to the new current screen====" << m_currentScreen->name();
        } else {
           KyInfo() << "66666====The current screen still exists====" << m_currentScreen->name();
        }

        disconnect(m_availableGeometryChangedConnection);
        adjustForScreenChanged();

        m_availableGeometryChangedConnection = connect(m_currentScreen, &QScreen::availableGeometryChanged, this, [this](const QRect &geometry) {
            KyInfo() << "77777====availableGeometryChanged====" << geometry;
            adjustForScreenChanged();
        });
    });

    // 窗口所在屏幕变化
    connect(this, &WindowController::currentScreenChanged, this, [this]() {
        if (m_currentScreen == nullptr || m_currentScreen->availableGeometry().isEmpty()) {
            KyInfo() << "88888====currentScreenChanged====new screen is null, ignore====";
            return;
        }

        KyInfo() << "88888====currentScreenChanged====" << m_currentScreen->name() << m_currentScreen->availableGeometry();
        disconnect(m_availableGeometryChangedConnection);
        m_availableGeometryChangedConnection = connect(m_currentScreen, &QScreen::availableGeometryChanged, this, [this](const QRect &geometry) {
            KyInfo() << "99999====availableGeometryChanged====" << geometry;
            adjustForScreenChanged();
        });
    });

    initWindowData(m_winMode);
    KyInfo() << "initScreenWathcer end";
}

QScreen *WindowController::getCurrentScreen()
{
#ifdef UKUI_WINDOWHELPER_SUPPORT
    if (m_winHelper != nullptr) {
        QScreen *screen = m_winHelper->getCurrentScreenBlocking();
        if (screen != nullptr && !screen->availableGeometry().isEmpty()) {
            return screen;
        }
    }
    // getCurrentScreenBlocking() 仅在 Wayland 可用；X11/UKUI 下隐藏窗口后再显示会返回 nullptr
    if (m_currentScreen != nullptr && !m_currentScreen->availableGeometry().isEmpty()) {
        return m_currentScreen;
    }
    return QGuiApplication::primaryScreen();
#else
    QScreen *screen = QGuiApplication::screenAt(QCursor::pos());
    return screen ? screen : QGuiApplication::primaryScreen();
#endif

}

void WindowController::setSideModePos()
{
    KyInfo() << "====setSideModePos====";
    if (m_currentScreen == nullptr) {
        KyInfo() << "m_currentScreen is nullptr, cannot set side mode pos";
        return;
    }

    QRect screenRect = m_currentScreen->availableGeometry();
    KyInfo() << "====currentScreen====name" << m_currentScreen->name();
    KyInfo() << "====availableGeometry====x:" << screenRect.x() << "y:" << screenRect.y()
             << "width:" << screenRect.width() << "height:" << screenRect.height()
             << "right:" << screenRect.right() << "top:" << screenRect.top();

    m_width = SIDEBAR_WIDTH;
    m_height = screenRect.height() - 2 * WINDOW_MARGIN;

    m_y = screenRect.top() + WINDOW_MARGIN;
    QString systemLang = QLocale::system().name();
    if (systemLang == "ug_CN" || systemLang == "ky_KG" || systemLang == "kk_KZ") {
        m_x = screenRect.x() + WINDOW_MARGIN;
    } else {
        m_x = screenRect.right() - SIDEBAR_WIDTH - WINDOW_MARGIN;
    }
    KyInfo() << "====setSideModePos====x:" << m_x << "y:" << m_y << "width:" << m_width << "height:" << m_height;
    Q_EMIT screenChanged();
}

void WindowController::setWindowModePos()
{
    //窗口在当前屏幕居中
    KyInfo() << "====setWindowModePos====";
    if (m_currentScreen == nullptr) {
        KyInfo() << "currentScreen is nullptr, cannot set window mode pos";
        return;
    }

    QRect screenRect = m_currentScreen->availableGeometry();
    KyInfo() << "====currentScreen====name" << m_currentScreen->name();
    KyInfo() << "====availableGeometry====x:" << screenRect.x() << "y:" << screenRect.y()
             << "width:" << screenRect.width() << "height:" << screenRect.height();

    m_width = WINMODE_WIDTH;
    m_height = WINMODE_HEIGHT;
    m_x = screenRect.x() + (screenRect.width() - WINMODE_WIDTH) / 2;
    m_y = screenRect.y() + (screenRect.height() - WINMODE_HEIGHT) / 2;
    KyInfo() << "====setWindowModePos====x:" << m_x << "y:" << m_y << "width:" << m_width << "height:" << m_height;
    Q_EMIT screenChanged();
}

void WindowController::adjustForScreenChanged()
{
    if (m_winMode == WINDOW_MODE_SIDEMODE) {
        setSideModePos();
    }
}

void WindowController::initDbusWathcer()
{
    m_dbusOperator = new KADBusOperator(this);
    connect(m_dbusOperator, &KADBusOperator::sigShowOrHideView, this, &WindowController::showOrHideWindow);

    return;
}

void WindowController::initWindowData(const WindowMode winMode)
{
    KyInfo() << "===initWindowData=====" << winMode;
    QScreen *currentScreen = getCurrentScreen();
    if (currentScreen == nullptr || currentScreen->availableGeometry().isEmpty()) {
        KyInfo() << "current screen is null, return";
        return;
    }

    if (m_currentScreen != currentScreen) {
        m_currentScreen = currentScreen;
        emit currentScreenChanged();
    }

    if (winMode == WINDOW_MODE_SIDEMODE) {
        setSideModePos();
    } else if (winMode == WINDOW_MODE_WINDOWMODE) {
        setWindowModePos();
    }

    return;
}

void WindowController::setWindow(QObject *win)
{
    KyInfo() << "setWindow start";
    m_mainWin = qobject_cast<QWindow*>(win);

    if (m_mainWin) {
        m_winHelper = new UkuiWindowHelper(m_mainWin);
        // 最大化按钮分屏功能
        m_maxBtnHoverDelayTimer = new QTimer(this);
        m_maxBtnHoverDelayTimer->setInterval(500);
        m_maxBtnHoverDelayTimer->setSingleShot(true);
        connect(m_maxBtnHoverDelayTimer, &QTimer::timeout, this, [this](){
            m_winHelper->showTileFlyout(m_winRect);
        });

        // 追踪窗口最大化状态，用于最小化后恢复时保持最大化
        connect(m_mainWin, &QWindow::visibilityChanged, this, [this](QWindow::Visibility visibility) {
            if (visibility == QWindow::Maximized) {
                m_wasMaximized = true;
            } else if (visibility == QWindow::Windowed) {
                m_wasMaximized = false;
            }
            // Minimized / Hidden 时不改变 m_wasMaximized，保留之前的状态
        });

        // 设置窗口支持拖拽
        UKUIWindowManager::instance()->registerWindow(m_mainWin);
        
        // 安装事件过滤器以捕获 Alt+F4
        m_mainWin->installEventFilter(this);
    }

    bool isMoveable = (m_winMode == WindowMode::WINDOW_MODE_WINDOWMODE) ? true : false;
    setWindowProperty(isMoveable, m_isTopping);

    KyInfo() << "setWindow end";
    return;
}

void WindowController::setWinMode(int newWinMode)
{
    WindowMode mode = static_cast<WindowMode>(newWinMode);
    if (m_winMode == mode) {
        return;
    }

    m_winMode = mode;
    ConfigManager::getInstance()->updateConfig("win-mode", m_winMode);
    emit winModeChanged(m_winMode);

    bool isMoveable = (mode == WindowMode::WINDOW_MODE_WINDOWMODE) ? true : false;
    setWindowProperty(isMoveable, m_isTopping);

    return;
}

void WindowController::showMainWindow()
{
    KyInfo() << "show main window";
    if (!m_mainWin) {
        KyInfo() << "ERROR: 无法获取窗口ID";

        return;
    }

    QScreen *currentScreen = getCurrentScreen();
    if (currentScreen == nullptr || currentScreen->availableGeometry().isEmpty()) {
        KyInfo() << "current screen is nullptr";
        return;
    }

    if (m_currentScreen != currentScreen) {
        m_currentScreen = currentScreen;
        emit currentScreenChanged();
    }

    if (m_winMode == WINDOW_MODE_SIDEMODE) {
        setSideModePos();
    } else if (m_winMode == WINDOW_MODE_WINDOWMODE && m_isFirstShow) {
        setWindowModePos();
        m_isFirstShow = false;
    }

    // 如果窗口之前处于最大化状态，恢复最大化；否则正常显示
    if (m_wasMaximized && m_mainWin->visibility() != QWindow::Maximized) {
        m_mainWin->setVisibility(QWindow::Maximized);
    } else {
        m_mainWin->show();
    }

    m_mainWin->raise();
    m_mainWin->requestActivate();
    KyInfo() << "show main window end";

    return;
}

///
/// \brief WindowController::showOrHideWindow 全局快捷键响应槽函数，用于实现按下快捷键时，
/// 唤出或隐藏窗口。
///
void WindowController::showOrHideWindow()
{
    if (!m_mainWin) {
        KyInfo() << "ERROR: 无法获取窗口ID";

        return;
    }

    KyInfo() << "----showorhidewindow---- 窗口是否激活？ isActive()" << m_mainWin->isActive();
    KyInfo() << "----showorhidewindow---- 窗口是否可见？  isVisible()" << m_mainWin->isVisible();
    KyInfo() << "----showorhidewindow---- 窗口Visiability  visibility()" << m_mainWin->visibility();

    if (m_mainWin->isVisible()) {
        // 主窗口最小化  或  主窗口不是当前活动窗口（失去焦点）时
        if (m_mainWin->visibility() == QWindow::Visibility::Minimized || !m_mainWin->isActive()) {
            showMainWindow();
        } else {
            // 检查是否有活动的模态窗口（QWidget或QML Window），有则不允许隐藏
            if (QApplication::activeModalWidget()) {
                KyInfo() << "====modal dialog is active, preventing hide====";
                return;
            }

            for (QWindow *w : QGuiApplication::topLevelWindows()) {
                if (w != m_mainWin && w->modality() != Qt::NonModal && w->isVisible()) {
                    KyInfo() << "----modal window is active, preventing hide----";
                    return;
                }
            }

            KyInfo() << "----hide----";
            m_mainWin->hide();
        }
    } else {
        showMainWindow();
    }
}

void WindowController::checkUnProcessFile()
{
    if (m_filePathWithStart == ""){
        return;
    }

    KyInfo() << "start with file, checkUnProcessFile file path:" << m_filePathWithStart;
    QUrl url(m_filePathWithStart);
    Q_EMIT sendFile(url.path());
}

void WindowController::showTileFlyout(const QRect &rect)
{
    m_winRect = rect;
    m_maxBtnHoverDelayTimer->start();

    return;

}

void WindowController::hideTileFlyout()
{
    m_maxBtnHoverDelayTimer->stop();

    return;
}

void WindowController::setKeepAbove(bool flag)
{
    bool isMoveable = (m_winMode == WindowMode::WINDOW_MODE_WINDOWMODE) ? true : false;
    setWindowProperty(isMoveable, flag);

    return;
}

void WindowController::setWindowProperty(bool isMoveable, bool isTopping)
{
    if(!m_winHelper) {
        return;
    }

    UkuiWindowHelper::States states;
    states |= UkuiWindowHelper::State::Minimizable;
    states |= UkuiWindowHelper::State::Maximizable;
    states |= UkuiWindowHelper::State::Closeable;
    states |= UkuiWindowHelper::State::Fullscreenable;
    states |= UkuiWindowHelper::State::Resizable;
    states |= UkuiWindowHelper::State::Focusable;
    states |= UkuiWindowHelper::State::Activatable;

    if (isMoveable){
        states |= UkuiWindowHelper::State::Movable;
    }

    if (isTopping) {
        states |= UkuiWindowHelper::State::KeepAbove;

    }

    m_winHelper->setWindowState(states);

    return;
}

bool WindowController::eventFilter(QObject *watched, QEvent *event)
{
    if (watched == m_mainWin) {
        if (event->type() == QEvent::KeyPress) {
            QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
            if (keyEvent->key() == Qt::Key_Alt) {
                m_altKeyPressed = true;
                KyInfo() << "Alt key pressed";
            }
            else if (keyEvent->key() == Qt::Key_F4 && (keyEvent->modifiers() & Qt::AltModifier)) {
                KyInfo() << "Alt+F4 key press detected, quitting application";
                QCoreApplication::quit();
                return true;
            }
            else if (keyEvent->key() == Qt::Key_F1) {
                KyInfo() << "F1 key pressed, showing help manual";
                CMainWnd *mainWnd = CMainWnd::getInstance();
                if (mainWnd) {
                    mainWnd->onShowHelp();
                }
                return true;
            }
        }
        else if (event->type() == QEvent::KeyRelease) {
            QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
            if (keyEvent->key() == Qt::Key_Alt) {
                m_altKeyPressed = false;
                KyInfo() << "Alt key released";
            }
        }
        else if (event->type() == QEvent::Close) {
            QCloseEvent *closeEvent = static_cast<QCloseEvent *>(event);
            if (m_altKeyPressed) {
                KyInfo() << "Close event with Alt key pressed (Alt+F4), quitting application";
                closeEvent->accept();
                QCoreApplication::quit();
                return true;
            }
            KyInfo() << "Close event without Alt key, passing to QML";
        }
    }
    return QObject::eventFilter(watched, event);
}
