-- store.lua - App Store system app logic
-- Milestone 10: Device-Side App Management

-- State
local state = {
    screen = "home",        -- home, games, updates, search, detail
    installed = {},         -- Installed apps from mosis.apps
    updates = {},           -- Available updates
    featured = {},          -- Featured apps from store API
    categories = {},        -- Category list
    search_query = "",      -- Current search
    selected_app = nil,     -- Selected app for detail view
    is_loading = false,
    error_message = nil
}

-- Store API configuration
local STORE_API = "https://portal.mosis.dev/store"

-- ============================================================================
-- Initialization
-- ============================================================================

function init()
    print("[Store] Initializing...")

    -- Load installed apps
    refreshInstalledApps()

    -- Check for updates
    checkForUpdates()

    -- Fetch featured apps (async)
    fetchFeaturedApps()
end

function refreshInstalledApps()
    if mosis and mosis.apps then
        state.installed = mosis.apps.getInstalled() or {}
        print("[Store] Loaded " .. #state.installed .. " installed apps")
    else
        print("[Store] Warning: mosis.apps API not available")
        state.installed = {}
    end
end

function checkForUpdates()
    if mosis and mosis.apps then
        state.updates = mosis.apps.checkUpdates() or {}
        print("[Store] Found " .. #state.updates .. " updates")
        updateBadge()
    end
end

function updateBadge()
    -- Update the updates tab badge
    local badge = document:GetElementById("updates-badge")
    if badge then
        if #state.updates > 0 then
            badge.inner_rml = tostring(#state.updates)
            badge.style.display = "block"
        else
            badge.style.display = "none"
        end
    end
end

-- ============================================================================
-- API Calls
-- ============================================================================

function fetchFeaturedApps()
    state.is_loading = true

    -- TODO: Make HTTP request to STORE_API
    -- For now, use placeholder data
    state.featured = {
        {
            id = "com.mosis.weather",
            name = "Weather Pro",
            category = "Weather",
            rating = 4.8,
            downloads = 125000,
            size = 15728640,  -- 15 MB
            description = "Beautiful forecasts for your virtual world",
            icon = "W",
            color = "#2196F3"
        },
        {
            id = "com.mosis.notes",
            name = "Notes",
            category = "Productivity",
            rating = 4.7,
            downloads = 89000,
            size = 8388608,  -- 8 MB
            description = "Simple note-taking app",
            icon = "N",
            color = "#03DAC6"
        }
    }

    state.is_loading = false
    render()
end

function searchApps(query)
    state.search_query = query
    state.screen = "search"

    if query == "" then
        state.screen = "home"
        render()
        return
    end

    state.is_loading = true
    render()

    -- TODO: Make HTTP request to STORE_API/search
    -- For now, filter featured apps
    local results = {}
    local lower_query = query:lower()
    for _, app in ipairs(state.featured) do
        if app.name:lower():find(lower_query) or
           app.category:lower():find(lower_query) then
            table.insert(results, app)
        end
    end

    state.search_results = results
    state.is_loading = false
    render()
end

-- ============================================================================
-- Installation
-- ============================================================================

function installApp(app_id, download_url, signature)
    print("[Store] Installing: " .. app_id)

    showProgress(app_id)

    if mosis and mosis.apps then
        mosis.apps.install(download_url or "", signature or "", function(progress)
            updateProgress(progress)

            if progress.stage == "complete" then
                hideProgress()
                showToast("App installed successfully!")
                refreshInstalledApps()
                render()
            elseif progress.stage == "failed" then
                hideProgress()
                showError("Installation failed: " .. (progress.error or "Unknown error"))
            end
        end)
    else
        hideProgress()
        showError("App installation not available")
    end
end

function uninstallApp(package_id)
    print("[Store] Uninstalling: " .. package_id)

    if mosis and mosis.apps then
        local success = mosis.apps.uninstall(package_id)
        if success then
            showToast("App uninstalled")
            refreshInstalledApps()
            render()
        else
            showError("Failed to uninstall app")
        end
    end
end

function openApp(package_id)
    print("[Store] Launching: " .. package_id)

    if mosis and mosis.apps then
        mosis.apps.launch(package_id)
    end
end

function updateApp(package_id)
    print("[Store] Updating: " .. package_id)

    -- Find update info
    for _, update in ipairs(state.updates) do
        if update.package_id == package_id then
            installApp(package_id, update.download_url, update.signature)
            return
        end
    end

    showError("No update available for this app")
end

function updateAllApps()
    print("[Store] Updating all apps...")

    for _, update in ipairs(state.updates) do
        -- Queue updates (in a real implementation, this would be sequential)
        installApp(update.package_id, update.download_url, update.signature)
    end
end

-- ============================================================================
-- UI Helpers
-- ============================================================================

function isInstalled(package_id)
    for _, app in ipairs(state.installed) do
        if app.package_id == package_id then
            return true
        end
    end
    return false
end

function hasUpdate(package_id)
    for _, update in ipairs(state.updates) do
        if update.package_id == package_id then
            return true
        end
    end
    return false
end

function formatSize(bytes)
    if bytes >= 1048576 then
        return string.format("%.1f MB", bytes / 1048576)
    elseif bytes >= 1024 then
        return string.format("%.0f KB", bytes / 1024)
    else
        return bytes .. " B"
    end
end

function formatDownloads(count)
    if count >= 1000000 then
        return string.format("%.1fM", count / 1000000)
    elseif count >= 1000 then
        return string.format("%.0fK", count / 1000)
    else
        return tostring(count)
    end
end

-- ============================================================================
-- Progress Dialog
-- ============================================================================

function showProgress(app_name)
    local dialog = document:GetElementById("progress-dialog")
    if dialog then
        dialog.style.display = "flex"
        local title = document:GetElementById("progress-title")
        if title then
            title.inner_rml = "Installing " .. (app_name or "App")
        end
    end
end

function updateProgress(progress)
    local bar = document:GetElementById("progress-bar")
    if bar then
        bar.style.width = (progress.progress * 100) .. "%"
    end

    local status = document:GetElementById("progress-status")
    if status then
        local stage_names = {
            downloading = "Downloading...",
            verifying = "Verifying...",
            extracting = "Extracting...",
            registering = "Registering...",
            complete = "Complete!",
            failed = "Failed"
        }
        status.inner_rml = stage_names[progress.stage] or progress.stage
    end
end

function hideProgress()
    local dialog = document:GetElementById("progress-dialog")
    if dialog then
        dialog.style.display = "none"
    end
end

-- ============================================================================
-- Toast/Error Messages
-- ============================================================================

function showToast(message)
    local toast = document:GetElementById("toast")
    if toast then
        toast.inner_rml = message
        toast.style.display = "block"
        -- Auto-hide after 3 seconds (would need timer API)
    end
    print("[Store] Toast: " .. message)
end

function showError(message)
    state.error_message = message
    local error_el = document:GetElementById("error-dialog")
    if error_el then
        local msg = document:GetElementById("error-message")
        if msg then
            msg.inner_rml = message
        end
        error_el.style.display = "flex"
    end
    print("[Store] Error: " .. message)
end

function hideError()
    state.error_message = nil
    local error_el = document:GetElementById("error-dialog")
    if error_el then
        error_el.style.display = "none"
    end
end

-- ============================================================================
-- Navigation
-- ============================================================================

function showHome()
    state.screen = "home"
    setActiveTab("apps")
    render()
end

function showGames()
    state.screen = "games"
    setActiveTab("games")
    render()
end

function showUpdates()
    state.screen = "updates"
    setActiveTab("updates")
    checkForUpdates()
    render()
end

function showSearch()
    state.screen = "search"
    render()
end

function showAppDetail(app_id)
    state.screen = "detail"
    -- Find app in featured or installed
    for _, app in ipairs(state.featured) do
        if app.id == app_id then
            state.selected_app = app
            break
        end
    end
    render()
end

function setActiveTab(tab)
    local tabs = {"apps", "games", "updates"}
    for _, t in ipairs(tabs) do
        local el = document:GetElementById("nav-" .. t)
        if el then
            if t == tab then
                el:SetClass("active", true)
            else
                el:SetClass("active", false)
            end
        end
    end
end

-- ============================================================================
-- Rendering
-- ============================================================================

function render()
    -- The RML is mostly static with dynamic data binding
    -- In a full implementation, we'd update innerHTML of content areas
    print("[Store] Rendering screen: " .. state.screen)
end

-- Initialize on load
init()
