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

Item {
    id: root

    property string searchQuery: ""
    property string selectedCategory: "All"
    property string viewMode: "list" // "list" or "grid"
    property int selectedIndex: 0
    property int maxResults: 50
    property int gridColumns: 4
    property bool debounceSearch: true
    property int debounceInterval: 50
    property bool keyboardNavigationActive: false
    readonly property var categories: {
        const allCategories = AppSearchService.getAllCategories().filter(cat => cat !== "Education" && cat !== "Science")
        const result = ["All"]
        return result.concat(allCategories.filter(cat => cat !== "All"))
    }
    readonly property var categoryIcons: categories.map(category => AppSearchService.getCategoryIcon(category))
    property var appUsageRanking: AppUsageHistoryData.appUsageRanking || {}
    property alias model: filteredModel
    property var _watchApplications: AppSearchService.applications

    signal appLaunched(var app)
    signal categorySelected(string category)
    signal viewModeSelected(string mode)

    function updateFilteredModel() {
        filteredModel.clear()
        selectedIndex = 0
        keyboardNavigationActive = false

        let apps = []
        if (searchQuery.length === 0) {
            apps = selectedCategory === "All" ? AppSearchService.getAppsInCategory("All") : AppSearchService.getAppsInCategory(selectedCategory).slice(0, maxResults)
        } else {
            if (selectedCategory === "All") {
                apps = AppSearchService.searchApplications(searchQuery)
            } else {
                const categoryApps = AppSearchService.getAppsInCategory(selectedCategory)
                if (categoryApps.length > 0) {
                    const allSearchResults = AppSearchService.searchApplications(searchQuery)
                    const categoryNames = new Set(categoryApps.map(app => app.name))
                    apps = allSearchResults.filter(searchApp => categoryNames.has(searchApp.name)).slice(0, maxResults)
                } else {
                    apps = []
                }
            }
        }

        if (searchQuery.length === 0) {
            apps = apps.sort((a, b) => {
                                 const aId = a.id || a.execString || a.exec || ""
                                 const bId = b.id || b.execString || b.exec || ""
                                 const aUsage = appUsageRanking[aId] ? appUsageRanking[aId].usageCount : 0
                                 const bUsage = appUsageRanking[bId] ? appUsageRanking[bId].usageCount : 0
                                 if (aUsage !== bUsage) {
                                     return bUsage - aUsage
                                 }
                                 return (a.name || "").localeCompare(b.name || "")
                             })
        }

        apps.forEach(app => {
                         if (app) {
                             filteredModel.append({
                                                      "name": app.name || "",
                                                      "exec": app.execString || "",
                                                      "icon": app.icon || "application-x-executable",
                                                      "comment": app.comment || "",
                                                      "categories": app.categories || [],
                                                      "desktopEntry": app
                                                  })
                         }
                     })
    }

    function selectNext() {
        if (filteredModel.count === 0) {
            return
        }
        keyboardNavigationActive = true
        selectedIndex = viewMode === "grid" ? Math.min(selectedIndex + gridColumns, filteredModel.count - 1) : Math.min(selectedIndex + 1, filteredModel.count - 1)
    }

    function selectPrevious() {
        if (filteredModel.count === 0) {
            return
        }
        keyboardNavigationActive = true
        selectedIndex = viewMode === "grid" ? Math.max(selectedIndex - gridColumns, 0) : Math.max(selectedIndex - 1, 0)
    }

    function selectNextInRow() {
        if (filteredModel.count === 0 || viewMode !== "grid") {
            return
        }
        keyboardNavigationActive = true
        selectedIndex = Math.min(selectedIndex + 1, filteredModel.count - 1)
    }

    function selectPreviousInRow() {
        if (filteredModel.count === 0 || viewMode !== "grid") {
            return
        }
        keyboardNavigationActive = true
        selectedIndex = Math.max(selectedIndex - 1, 0)
    }

    function launchSelected() {
        if (filteredModel.count === 0 || selectedIndex < 0 || selectedIndex >= filteredModel.count) {
            return
        }
        const selectedApp = filteredModel.get(selectedIndex)
        launchApp(selectedApp)
    }

    function launchApp(appData) {
        if (!appData) {
            return
        }
        appData.desktopEntry.execute()
        appLaunched(appData)
        AppUsageHistoryData.addAppUsage(appData.desktopEntry)
    }

    function setCategory(category) {
        selectedCategory = category
        categorySelected(category)
    }

    function setViewMode(mode) {
        viewMode = mode
        viewModeSelected(mode)
    }

    onSearchQueryChanged: {
        if (debounceSearch) {
            searchDebounceTimer.restart()
        } else {
            updateFilteredModel()
        }
    }
    onSelectedCategoryChanged: updateFilteredModel()
    onAppUsageRankingChanged: updateFilteredModel()
    on_WatchApplicationsChanged: updateFilteredModel()
    Component.onCompleted: {
        updateFilteredModel()
    }

    ListModel {
        id: filteredModel
    }

    Timer {
        id: searchDebounceTimer

        interval: root.debounceInterval
        repeat: false
        onTriggered: updateFilteredModel()
    }
}
