--[[
    Commander 3.0 - Data Sources Test Suite

    Tests for data source commands:
    - bags, equipped, durability
    - spells
    - mounts
    - currencies, gold
    - quests
    - party, target, focus
    - specs, talents
]]

local ADDON_NAME, C3 = ...

local Framework = C3.TestFramework
local Assert = Framework.Assert
local suite = Framework:Suite("datasources")

-------------------------------------------------------------------------------
-- Helper Functions
-------------------------------------------------------------------------------

---Collect iterator results into an array
local function collectResults(result)
    if type(result) == "function" then
        local items = {}
        for item in result do
            table.insert(items, item)
        end
        return items
    elseif type(result) == "table" then
        if result[1] ~= nil or next(result) == nil then
            return result -- Already an array or empty table
        end
        return { result } -- Single object
    end
    return {}
end

-------------------------------------------------------------------------------
-- Bags Tests
-------------------------------------------------------------------------------

Framework:Test(suite, "bags command executes without error", function()
    local result = C3:Query("bags")
    -- May be empty or have items - just verify no error
    Assert.notNil(result, "bags should return a result")
end)

Framework:Test(suite, "bags returns Item types", function()
    local result = C3:Query("bags | first")
    if result and type(result) == "table" and result._type then
        Assert.equals("Item", result._type, "bags items should be Item type")
    end
    -- Empty bags is acceptable
end)

Framework:Test(suite, "bags items have expected properties", function()
    local result = C3:Query("bags | first")
    if result and type(result) == "table" and result._type == "Item" then
        -- Items should have basic properties
        Assert.notNil(result.name, "Item should have name")
        Assert.notNil(result.id, "Item should have id")
    end
end)

-------------------------------------------------------------------------------
-- Equipped Tests
-------------------------------------------------------------------------------

Framework:Test(suite, "equipped command executes without error", function()
    local result = C3:Query("equipped")
    Assert.notNil(result)
end)

Framework:Test(suite, "equipped returns Item types for worn gear", function()
    local result = C3:Query("equipped | first")
    if result and type(result) == "table" and result._type == "Item" then
        Assert.notNil(result.equipSlot, "equipped items should have equipSlot")
    end
end)

-------------------------------------------------------------------------------
-- Durability Tests
-------------------------------------------------------------------------------

Framework:Test(suite, "durability command executes without error", function()
    local result = C3:Query("durability")
    Assert.notNil(result)
end)

Framework:Test(suite, "durability returns valid percentages", function()
    local result = C3:Query("durability | first")
    if result and type(result) == "table" then
        if result.percent then
            Assert.inRange(result.percent, 0, 100, "percent should be 0-100")
        end
    end
end)

-------------------------------------------------------------------------------
-- Spells Tests
-------------------------------------------------------------------------------

Framework:Test(suite, "spells command executes without error", function()
    local result = C3:Query("spells")
    Assert.notNil(result)
end)

Framework:Test(suite, "spells returns Spell types", function()
    local result = C3:Query("spells | first")
    if result and type(result) == "table" and result._type then
        Assert.equals("Spell", result._type)
        Assert.notNil(result.name, "spell should have name")
        Assert.notNil(result.id, "spell should have id")
    end
end)

Framework:Test(suite, "spells have expected properties", function()
    local result = C3:Query("spells | first")
    if result and type(result) == "table" and result._type == "Spell" then
        -- Spells should have icon
        Assert.notNil(result.icon, "Spell should have icon")
    end
end)

-------------------------------------------------------------------------------
-- Mounts Tests
-------------------------------------------------------------------------------

Framework:Test(suite, "mounts command executes without error", function()
    local result = C3:Query("mounts")
    Assert.notNil(result)
end)

Framework:Test(suite, "mounts returns Mount types", function()
    local result = C3:Query("mounts | first")
    if result and type(result) == "table" and result._type then
        Assert.equals("Mount", result._type)
        Assert.notNil(result.name, "mount should have name")
    end
end)

Framework:Test(suite, "mounts have flight/ground properties", function()
    local result = C3:Query("mounts | first")
    if result and type(result) == "table" and result._type == "Mount" then
        -- Mount should have flying/ground boolean
        Assert.notNil(result.isFlying ~= nil or result.isGround ~= nil,
            "Mount should have flight/ground info")
    end
end)

Framework:Test(suite, "mounts --favorites filters correctly", function()
    local favResult = C3:Query("mounts --favorites | count")
    -- Just verify it doesn't error
    Assert.notNil(favResult)
end)

-------------------------------------------------------------------------------
-- Currencies Tests
-------------------------------------------------------------------------------

Framework:Test(suite, "currencies command executes without error", function()
    local result = C3:Query("currencies")
    Assert.notNil(result)
end)

Framework:Test(suite, "currencies returns Currency types", function()
    local result = C3:Query("currencies | first")
    if result and type(result) == "table" and result._type then
        Assert.equals("Currency", result._type)
    end
end)

Framework:Test(suite, "gold command executes without error", function()
    local result = C3:Query("gold")
    Assert.notNil(result)
end)

-------------------------------------------------------------------------------
-- Quests Tests
-------------------------------------------------------------------------------

Framework:Test(suite, "quests command executes without error", function()
    local result = C3:Query("quests")
    Assert.notNil(result)
end)

Framework:Test(suite, "quests returns Quest types", function()
    local result = C3:Query("quests | first")
    if result and type(result) == "table" and result._type then
        Assert.equals("Quest", result._type)
    end
end)

-------------------------------------------------------------------------------
-- Party/Group Tests
-------------------------------------------------------------------------------

Framework:Test(suite, "party command executes without error", function()
    local result = C3:Query("party")
    -- May return empty if not in party - that's fine
    Assert.notNil(result)
end)

Framework:Test(suite, "target command executes without error", function()
    -- May return nil or info depending on target state
    local ok = pcall(function()
        C3:Query("target")
    end)
    Assert.isTrue(ok, "target command should not throw")
end)

Framework:Test(suite, "focus command executes without error", function()
    -- May return nil or info depending on focus state
    local ok = pcall(function()
        C3:Query("focus")
    end)
    Assert.isTrue(ok, "focus command should not throw")
end)

Framework:Test(suite, "raid command executes without error", function()
    local result = C3:Query("raid")
    Assert.notNil(result)
end)

Framework:Test(suite, "group command executes without error", function()
    local result = C3:Query("group")
    Assert.notNil(result)
end)

-------------------------------------------------------------------------------
-- Specs/Talents Tests
-------------------------------------------------------------------------------

Framework:Test(suite, "specs command executes without error", function()
    local result = C3:Query("specs")
    Assert.notNil(result)
end)

Framework:Test(suite, "talents command executes without error", function()
    local result = C3:Query("talents")
    Assert.notNil(result)
end)

-------------------------------------------------------------------------------
-- Achievements Tests
-------------------------------------------------------------------------------

Framework:Test(suite, "achievements command executes without error", function()
    local result = C3:Query("achievements")
    Assert.notNil(result)
end)

Framework:Test(suite, "achpoints command executes without error", function()
    local result = C3:Query("achpoints")
    Assert.notNil(result)
end)

-------------------------------------------------------------------------------
-- Guild Tests
-------------------------------------------------------------------------------

Framework:Test(suite, "guild command executes without error", function()
    local result = C3:Query("guild")
    -- May return error if not in guild
    Assert.notNil(result)
end)

Framework:Test(suite, "ginfo command executes without error", function()
    local result = C3:Query("ginfo")
    Assert.notNil(result)
end)

-------------------------------------------------------------------------------
-- Toys Tests
-------------------------------------------------------------------------------

Framework:Test(suite, "toys command executes without error", function()
    local result = C3:Query("toys")
    Assert.notNil(result)
end)

-------------------------------------------------------------------------------
-- Character Stats Tests
-------------------------------------------------------------------------------

Framework:Test(suite, "stats command executes without error", function()
    local result = C3:Query("stats")
    Assert.notNil(result)
end)

Framework:Test(suite, "stats returns stat objects", function()
    local result = C3:Query("stats | first")
    if result and type(result) == "table" and result._type then
        Assert.equals("Stat", result._type, "stats should return Stat type")
    end
end)

Framework:Test(suite, "info command executes without error", function()
    local result = C3:Query("info")
    Assert.notNil(result)
end)

return suite
