--[[
    Warband Nexus - Search State Manager
    Per-tab search query storage (UI debounces redraws separately).
]]

local ADDON_NAME, ns = ...

local issecretvalue = issecretvalue
local E = ns.Constants.EVENTS

-- Debug print helper
local DebugPrint = ns.DebugPrint
local WarbandNexus = ns.WarbandNexus

-- Ace3 Event System
local AceEvent = LibStub("AceEvent-3.0")

-- STATE STORAGE

-- Per-tab search state (query updated when debounced UI callback runs; no second timer here).
local searchStates = {}

-- CONSTANTS

-- List redraw debounce lives in UI (`UI_CONSTANTS.SEARCH_DEBOUNCE_SEC` / SearchBoxComponent).

-- PRIVATE HELPERS

-- Flexible validation: accept any non-empty string
-- Supports main tabs (items, currency) and sub-tabs (plans_mount, plans_achievement)
local function ValidateTabId(tabId)
    if not tabId or type(tabId) ~= "string" or tabId == "" then
        DebugPrint("[SearchStateManager] ERROR: Invalid tab ID:", tostring(tabId))
        return false
    end
    return true
end

--- Lowercase search query for storage; never call string methods on secret API values (Midnight 12.0+).
local function NormalizeSearchQuery(searchText)
    if not searchText or type(searchText) ~= "string" then return "" end
    if issecretvalue and issecretvalue(searchText) then return "" end
    return searchText:lower()
end

local function GetOrCreateState(tabId)
    if not searchStates[tabId] then
        searchStates[tabId] = {
            query = "",
            resultCount = 0,
            isEmpty = false,
            timestamp = GetTime(),
        }
    end
    return searchStates[tabId]
end

local function FireStateChangedEvent(tabId)
    local state = searchStates[tabId]
    if not state then return end
    
    -- Fire event for UI consumption
    AceEvent:SendMessage(E.SEARCH_STATE_CHANGED, {
        tabId = tabId,
        searchText = state.query,
        resultCount = state.resultCount,
        isEmpty = state.isEmpty,
        timestamp = state.timestamp
    })
end

-- PUBLIC API

local SearchStateManager = {}

--[[
    Set search query for a tab (called from debounced search UI; no extra timer).
    @param tabId string - Tab identifier (e.g., "items", "currency")
    @param searchText string - Search query text
]]
function SearchStateManager:SetSearchQuery(tabId, searchText)
    if not ValidateTabId(tabId) then return end
    
    local state = GetOrCreateState(tabId)
    local normalizedQuery = NormalizeSearchQuery(searchText)
    
    state.query = normalizedQuery
    state.timestamp = GetTime()
    
    AceEvent:SendMessage(E.SEARCH_QUERY_UPDATED, {
        tabId = tabId,
        searchText = normalizedQuery
    })
    
    FireStateChangedEvent(tabId)
end

--[[
    Get current search state for a tab
    @param tabId string - Tab identifier
    @return table - {query, isEmpty, resultCount, timestamp} or nil if invalid
]]
function SearchStateManager:GetSearchState(tabId)
    if not ValidateTabId(tabId) then return nil end
    
    local state = GetOrCreateState(tabId)
    
    -- Return copy to prevent external modification
    return {
        query = state.query,
        isEmpty = state.isEmpty,
        resultCount = state.resultCount,
        timestamp = state.timestamp
    }
end

--[[
    Update result count after UI has rendered
    Called by Draw functions after rendering is complete
    @param tabId string - Tab identifier
    @param resultCount number - Number of results rendered
]]
function SearchStateManager:UpdateResults(tabId, resultCount)
    if not ValidateTabId(tabId) then return end
    
    local state = GetOrCreateState(tabId)
    state.resultCount = resultCount or 0
    state.isEmpty = state.resultCount == 0
    state.timestamp = GetTime()
    
    -- No event fire here - this is called AFTER rendering
    -- UI already has the results, this just updates internal state
end

--[[
    Clear search for a tab
    @param tabId string - Tab identifier
]]
function SearchStateManager:ClearSearch(tabId)
    if not ValidateTabId(tabId) then return end
    
    local state = GetOrCreateState(tabId)
    
    state.query = ""
    state.resultCount = 0
    state.isEmpty = false
    state.timestamp = GetTime()
    
    -- Fire event to update UI
    FireStateChangedEvent(tabId)
end

--[[
    Check if a tab has an active search
    @param tabId string - Tab identifier
    @return boolean - True if search query is not empty
]]
function SearchStateManager:HasActiveSearch(tabId)
    if not ValidateTabId(tabId) then return false end
    
    local state = searchStates[tabId]
    if not state or not state.query then return false end
    if issecretvalue and issecretvalue(state.query) then return false end
    return state.query ~= ""
end

--[[
    Get search query for a tab (convenience method)
    @param tabId string - Tab identifier
    @return string - Search query (lowercase) or empty string
]]
function SearchStateManager:GetQuery(tabId)
    if not ValidateTabId(tabId) then return "" end
    
    local state = searchStates[tabId]
    local q = state and state.query or ""
    if q and issecretvalue and issecretvalue(q) then return "" end
    if not q or q == "" then return "" end
    return q
end

-- INITIALIZATION

-- Expose to namespace
ns.SearchStateManager = SearchStateManager
