import QtQuick
import Quickshell
import qs.Common
import qs.Services
import qs.Widgets

FloatingWindow {
    id: root

    property bool disablePopupTransparency: true
    property string searchQuery: ""
    property var filteredApps: []
    property int selectedIndex: -1
    property bool keyboardNavigationActive: false
    property var appsModel: []
    property var parentModal: null
    parentWindow: parentModal

    signal appSelected(string appId)

    objectName: "appBrowserPopup"
    title: I18n.tr("Select Application")
    minimumSize: Qt.size(400, 350)
    implicitWidth: 500
    implicitHeight: 550
    color: "transparent"
    visible: false

    onClosed: hide()

    WindowBlur {
        targetWindow: root
        blurX: 0
        blurY: 0
        blurWidth: root.visible ? root.width : 0
        blurHeight: root.visible ? root.height : 0
        blurRadius: Theme.cornerRadius
    }

    Rectangle {
        anchors.fill: parent
        radius: Theme.cornerRadius
        color: Theme.withAlpha(Theme.surfaceContainer, 0.95)
        border.color: Theme.outlineMedium
        border.width: Theme.layerOutlineWidth
    }

    FocusScope {
        anchors.fill: parent
        focus: true

        Keys.onPressed: event => {
            switch (event.key) {
            case Qt.Key_Escape:
                root.hide();
                event.accepted = true;
                return;
            case Qt.Key_Down:
                root.selectNext();
                event.accepted = true;
                return;
            case Qt.Key_Up:
                root.selectPrevious();
                event.accepted = true;
                return;
            case Qt.Key_Return:
            case Qt.Key_Enter:
                if (root.keyboardNavigationActive) {
                    root.selectApp();
                } else if (root.filteredApps.length > 0) {
                    root.selectAppByIndex(0);
                }
                event.accepted = true;
                return;
            }
        }

        Column {
            anchors.fill: parent
            spacing: 0

            Item {
                width: parent.width
                height: 48

                MouseArea {
                    anchors.fill: parent
                    onPressed: windowControls.tryStartMove()
                }

                Rectangle {
                    anchors.fill: parent
                    color: Theme.withAlpha(Theme.surfaceContainerHigh, 0.5)
                }

                Row {
                    anchors.left: parent.left
                    anchors.leftMargin: Theme.spacingL
                    anchors.verticalCenter: parent.verticalCenter
                    spacing: Theme.spacingM

                    DankIcon {
                        name: "add_circle"
                        size: Theme.iconSize
                        color: Theme.primary
                        anchors.verticalCenter: parent.verticalCenter
                    }

                    StyledText {
                        text: I18n.tr("Select Application")
                        font.pixelSize: Theme.fontSizeXLarge
                        color: Theme.surfaceText
                        font.weight: Font.Medium
                        anchors.verticalCenter: parent.verticalCenter
                    }
                }

                Row {
                    anchors.right: parent.right
                    anchors.rightMargin: Theme.spacingM
                    anchors.verticalCenter: parent.verticalCenter
                    spacing: Theme.spacingXS

                    DankActionButton {
                        iconName: "close"
                        iconSize: Theme.iconSize - 4
                        iconColor: Theme.surfaceText
                        onClicked: root.hide()
                    }
                }
            }

            Item {
                width: parent.width
                height: parent.height - 48

                Column {
                    anchors.fill: parent
                    anchors.margins: Theme.spacingL
                    spacing: Theme.spacingM

                    DankTextField {
                        id: searchField
                        width: parent.width
                        height: 48
                        cornerRadius: Theme.cornerRadius
                        backgroundColor: Theme.withAlpha(Theme.surfaceContainerHigh, 0.8)
                        normalBorderColor: Theme.outlineMedium
                        focusedBorderColor: Theme.primary
                        leftIconName: "search"
                        leftIconSize: Theme.iconSize
                        leftIconColor: Theme.surfaceVariantText
                        leftIconFocusedColor: Theme.primary
                        showClearButton: true
                        textColor: Theme.surfaceText
                        font.pixelSize: Theme.fontSizeMedium
                        placeholderText: I18n.tr("Search applications...")
                        text: root.searchQuery
                        onTextEdited: {
                            root.searchQuery = text;
                            root.updateFilteredApps();
                        }
                    }

                    DankListView {
                        id: appList
                        width: parent.width
                        height: parent.height - searchField.height - Theme.spacingM
                        spacing: Theme.spacingS
                        // Start with no model. It is (re)bound in show() so that each open
                        // gets a fresh QQmlDelegateModel, avoiding a crash where a stale
                        // incubation queue from a previous open races with a background
                        // refreshApplications() replacing the underlying DesktopEntries
                        // QObjectModel (SIGSEGV in QQmlIncubatorPrivate::incubate via
                        // libQt6QmlModels). See hide()/onVisibleChanged() for the teardown.
                        model: null
                        clip: true

                        delegate: Rectangle {
                            width: appList.width
                            height: 60
                            radius: Theme.cornerRadius
                            required property int index
                            required property var modelData

                            readonly property bool isSelected: root.keyboardNavigationActive && index === root.selectedIndex

                            color: isSelected ? Theme.withAlpha(Theme.primary, 0.16) : appArea.containsMouse ? Theme.withAlpha(Theme.primary, 0.08) : Theme.withAlpha(Theme.surfaceVariant, 0.3)
                            border.color: isSelected ? Theme.primary : Theme.outlineMedium
                            border.width: isSelected ? 2 : Theme.layerOutlineWidth

                            Row {
                                anchors.fill: parent
                                anchors.margins: Theme.spacingM
                                spacing: Theme.spacingM

                                Image {
                                    width: 28
                                    height: 28
                                    source: Paths.resolveIconUrl(modelData.icon || "application-x-executable")
                                    sourceSize.width: 28
                                    sourceSize.height: 28
                                    fillMode: Image.PreserveAspectFit
                                    anchors.verticalCenter: parent.verticalCenter
                                    onStatusChanged: {
                                        if (status === Image.Error)
                                            source = "image://icon/application-x-executable";
                                    }
                                }

                                Column {
                                    anchors.verticalCenter: parent.verticalCenter
                                    spacing: Theme.spacingXXS
                                    width: parent.width - 28 - Theme.spacingM * 3 - 24

                                    StyledText {
                                        text: modelData.name || modelData.id || ""
                                        font.pixelSize: Theme.fontSizeMedium
                                        font.weight: Font.Medium
                                        color: Theme.surfaceText
                                        elide: Text.ElideRight
                                        width: parent.width
                                    }

                                    StyledText {
                                        text: modelData.comment || modelData.genericName || ""
                                        font.pixelSize: Theme.fontSizeSmall
                                        color: Theme.outline
                                        elide: Text.ElideRight
                                        width: parent.width
                                    }
                                }

                                DankIcon {
                                    name: "add"
                                    size: Theme.iconSize - 4
                                    color: Theme.primary
                                    anchors.verticalCenter: parent.verticalCenter
                                }
                            }

                            MouseArea {
                                id: appArea
                                anchors.fill: parent
                                hoverEnabled: true
                                cursorShape: Qt.PointingHandCursor
                                onClicked: {
                                    const appId = modelData.id || modelData.execString || "";
                                    root.appSelected(appId);
                                    root.hide();
                                }
                            }

                            Behavior on color {
                                ColorAnimation {
                                    duration: Theme.shortDuration
                                    easing.type: Theme.standardEasing
                                }
                            }
                        }
                    }
                }
            }
        }

        FloatingWindowControls {
            id: windowControls
            targetWindow: root
        }
    }

    function updateFilteredApps() {
        const allApps = root.appsModel || [];
        var filtered = [];
        if (!searchQuery || searchQuery.length === 0) {
            filtered = allApps.slice();
        } else {
            var query = searchQuery.toLowerCase();
            for (var i = 0; i < allApps.length; i++) {
                var app = allApps[i];
                var name = (app.name || "").toLowerCase();
                var id = (app.id || "").toLowerCase();
                var comment = (app.comment || app.genericName || "").toLowerCase();
                if (name.indexOf(query) !== -1 || id.indexOf(query) !== -1 || comment.indexOf(query) !== -1)
                    filtered.push(app);
            }
        }
        filteredApps = filtered;
        selectedIndex = -1;
        keyboardNavigationActive = false;
    }

    function selectNext() {
        if (filteredApps.length === 0)
            return;
        keyboardNavigationActive = true;
        selectedIndex = Math.min(selectedIndex + 1, filteredApps.length - 1);
    }

    function selectPrevious() {
        if (filteredApps.length === 0)
            return;
        keyboardNavigationActive = true;
        selectedIndex = Math.max(selectedIndex - 1, -1);
        if (selectedIndex === -1)
            keyboardNavigationActive = false;
    }

    function selectApp() {
        if (selectedIndex < 0 || selectedIndex >= filteredApps.length)
            return;
        selectAppByIndex(selectedIndex);
    }

    function selectAppByIndex(idx) {
        const app = filteredApps[idx];
        if (!app)
            return;
        root.appSelected(app.id || app.execString || "");
        hide();
    }

    function show() {
        updateFilteredApps();
        // Rebind the model reactively (search relies on filteredApps changes flowing
        // through), and do it after populating so the ListView starts incubating from
        // a fully-formed array rather than [].
        appList.model = Qt.binding(() => root.filteredApps);
        visible = true;
        Qt.callLater(() => searchField.forceActiveFocus());
    }

    function hide() {
        // Drop the model before clearing visible, so the ListView releases its
        // QQmlDelegateModel (and any in-flight incubators) synchronously on this
        // frame. This is the crux of the fix: a later show() will allocate a fresh
        // DelegateModel instead of reusing one whose incubation queue may hold
        // references invalidated by a concurrent refreshApplications().
        appList.model = null;
        visible = false;
        searchQuery = "";
        filteredApps = [];
        selectedIndex = -1;
        keyboardNavigationActive = false;
    }

    onVisibleChanged: {
        if (!visible) {
            // Guard against visibility being cleared without going through hide()
            // (e.g. window manager close, FloatingWindow.onClosed -> hide()).
            appList.model = null;
            searchQuery = "";
            filteredApps = [];
            selectedIndex = -1;
            keyboardNavigationActive = false;
        }
    }
}
