--[[
    Commander 3.0 - Session CLI Command

    Commands: session

    Manage terminal sessions (tmux-like functionality).
    Subcommands: list, new, switch, delete, rename, info
]]

local ADDON_NAME, C3 = ...

-- Use shared color utilities
local Colorize = function(...) return C3.Colors.Colorize(...) end
local GetThemeColor = function(...) return C3.Colors.GetColor(...) end

-------------------------------------------------------------------------------
-- Session Lookup Helper
-------------------------------------------------------------------------------

---Find a session by name or ID (exact match, case-insensitive for names)
---@param name string Session name or ID to find
---@return table|nil session The found session, or nil if not found
local function findSession(name)
    if not name then return nil end
    local sessions = C3.SessionManager:List()
    local nameLower = name:lower()
    for _, session in ipairs(sessions) do
        if session.id == name or (session.name and session.name:lower() == nameLower) then
            return session
        end
    end
    return nil
end

-------------------------------------------------------------------------------
-- Session Type Registration
-------------------------------------------------------------------------------

C3.Types:Register("SessionInfo", {
    description = "Terminal session information",
    source = "session list",
    properties = {
        { "id", "Session ID" },
        { "name", "Session name" },
        { "isActive", "true if this is the active session" },
        { "created", "Creation time" },
        { "lastActive", "Last activity time" },
        { "cwd", "Current working directory" },
        { "historyCount", "Number of commands in history" },
    },
    format = function(self)
        local active = self.isActive and (Colorize("*", "accent.success") .. " ") or "  "
        local name = self.name or "Unnamed"

        -- Format times
        local now = GetTime()
        local ageStr = ""
        if self.lastActive then
            local age = now - self.lastActive
            if age < 60 then
                ageStr = string.format("%ds ago", math.floor(age))
            elseif age < 3600 then
                ageStr = string.format("%dm ago", math.floor(age / 60))
            else
                ageStr = string.format("%dh ago", math.floor(age / 3600))
            end
        end

        local warnColor = GetThemeColor("accent.warning") or "EBCB8B"
        local dimColor = GetThemeColor("status.dim") or "4C566A"
        return string.format("%s|cff%s%-20s|r |cff%s(%s)|r |cff%s[%d cmds]|r",
            active, warnColor, name, dimColor, ageStr, dimColor, self.historyCount or 0)
    end
})

-------------------------------------------------------------------------------
-- Intellisense Providers
-------------------------------------------------------------------------------

---Session action intellisense provider
---@param partial string
---@param ctx table
---@return table suggestions
local function actionProvider(partial, ctx)
    local actions = {
        { text = "list", description = "List all sessions" },
        { text = "new", description = "Create a new session" },
        { text = "switch", description = "Switch to a session" },
        { text = "delete", description = "Delete a session" },
        { text = "rename", description = "Rename a session" },
        { text = "info", description = "Show session info" },
    }
    return C3.Intellisense.fuzzyFilter(actions, partial, function(item)
        return item.text
    end)
end

---Session name intellisense provider (for switch/delete/rename)
---@param partial string
---@param ctx table
---@return table suggestions
local function sessionNameProvider(partial, ctx)
    local suggestions = {}

    if C3.SessionManager then
        local sessions = C3.SessionManager:List()
        local activeSession = C3.SessionManager:GetActive()

        for _, session in ipairs(sessions) do
            local isActive = session == activeSession
            suggestions[#suggestions + 1] = {
                text = session.name or session.id,
                description = isActive and Colorize("Active", "accent.success") or "",
            }
        end
    end

    return C3.Intellisense.fuzzyFilter(suggestions, partial, function(item)
        return item.text
    end)
end

-------------------------------------------------------------------------------
-- session - Manage sessions
-------------------------------------------------------------------------------

C3.Command:Define({
    name = "session",
    description = "Manage terminal sessions",
    category = "terminal",
    acceptsInput = false,
    args = {
        {
            name = "action",
            required = false,
            description = "list, new, switch, delete, rename, info",
            provider = actionProvider,
        },
        {
            name = "name",
            required = false,
            description = "Session name (for new/switch/delete/rename)",
            provider = sessionNameProvider,
        },
        { name = "newname", required = false, description = "New name (for rename)" },
    },
    execute = function(ctx)
        local action = ctx:GetArg(1) or "list"
        local name = ctx:GetArg(2)
        local newname = ctx:GetArg(3)

        action = action:lower()

        -- List sessions
        if action == "list" or action == "ls" then
            local sessions = C3.SessionManager:List()
            local activeSession = C3.SessionManager:GetActive()

            if #sessions == 0 then
                return ctx:Error("No sessions")
            end

            local results = {}
            for _, session in ipairs(sessions) do
                results[#results + 1] = C3.Types.Create("SessionInfo", {
                    id = session.id,
                    name = session.name,
                    isActive = session == activeSession,
                    created = session.created,
                    lastActive = session.lastActive,
                    cwd = session.cwd,
                    historyCount = #session.history,
                })
            end

            return results
        end

        -- Create new session
        if action == "new" or action == "create" then
            local sessionName = name or ("Session " .. (#C3.SessionManager:List() + 1))

            local newSession = C3.SessionManager:Create({ name = sessionName })

            -- If terminal is available, add as tab
            if C3.Terminal and C3.Terminal.tabs then
                C3.Terminal.tabs:Add(newSession)
            end

            return ctx:Text(Colorize("Created", "accent.success") .. " session: " .. Colorize(sessionName, "accent.warning"))
        end

        -- Switch to session
        if action == "switch" or action == "attach" or action == "goto" then
            if not name then
                return ctx:Error("Usage: session switch <name|id>")
            end

            local targetSession = findSession(name)
            if not targetSession then
                return ctx:Error("Session not found: " .. name)
            end

            -- Switch via terminal tabs if available
            if C3.Terminal and C3.Terminal.tabs then
                for _, tab in ipairs(C3.Terminal.tabs:GetTabs()) do
                    if tab and tab.session == targetSession then
                        C3.Terminal:SwitchToTab(tab)
                        return ctx:Text(Colorize("Switched", "accent.success") .. " to session: " .. Colorize(targetSession.name, "accent.warning"))
                    end
                end
            end

            -- Fallback: just set active
            C3.SessionManager:SetActive(targetSession)
            return ctx:Text(Colorize("Switched", "accent.success") .. " to session: " .. Colorize(targetSession.name, "accent.warning"))
        end

        -- Delete session
        if action == "delete" or action == "close" or action == "kill" then
            if not name then
                return ctx:Error("Usage: session delete <name|id>")
            end

            local targetSession = findSession(name)
            if not targetSession then
                return ctx:Error("Session not found: " .. name)
            end

            local sessionName = targetSession.name

            -- Don't delete the active session if it's the only one
            if targetSession == C3.SessionManager:GetActive() and #C3.SessionManager:List() == 1 then
                return ctx:Error("Cannot delete the only session")
            end

            -- Remove from tabs if terminal is available
            if C3.Terminal and C3.Terminal.tabs then
                local tabs = C3.Terminal.tabs
                for i = tabs:GetCount(), 1, -1 do
                    local tab = tabs:GetTabByIndex(i)
                    if tab and tab.session == targetSession then
                        tabs:Remove(tab)
                        break
                    end
                end
            end

            C3.SessionManager:Close(targetSession.id)
            return ctx:Text(Colorize("Deleted", "accent.error") .. " session: " .. Colorize(sessionName, "accent.warning"))
        end

        -- Rename session
        if action == "rename" then
            if not name then
                return ctx:Error("Usage: session rename <name|id> <newname>")
            end
            if not newname then
                return ctx:Error("Usage: session rename <name|id> <newname>")
            end

            local targetSession = findSession(name)
            if not targetSession then
                return ctx:Error("Session not found: " .. name)
            end

            local oldName = targetSession.name
            targetSession.name = newname

            -- Update tab if terminal is available
            if C3.Terminal and C3.Terminal.tabs then
                C3.Terminal.tabs:Render()
            end

            return ctx:Text(Colorize("Renamed", "accent.success") .. " session: " .. Colorize(oldName, "accent.warning") .. " -> " .. Colorize(newname, "accent.warning"))
        end

        -- Show session info
        if action == "info" then
            local targetSession
            if name then
                targetSession = findSession(name)
                if not targetSession then
                    return ctx:Error("Session not found: " .. name)
                end
            else
                targetSession = C3.SessionManager:GetActive()
            end

            local activeSession = C3.SessionManager:GetActive()

            return C3.Types.Create("SessionInfo", {
                id = targetSession.id,
                name = targetSession.name,
                isActive = targetSession == activeSession,
                created = targetSession.created,
                lastActive = targetSession.lastActive,
                cwd = targetSession.cwd,
                historyCount = #targetSession.history,
            })
        end

        -- Unknown action
        return ctx:Error("Unknown action: " .. action .. "\nValid: list, new, switch, delete, rename, info")
    end
})

return true
