EbonholdHub.EchoTableRows = {}

local UI = EbonholdHub.UI
local C  = UI.Colors

local ROW_HEIGHT = 28

local QUALITY_COLORS = {
    [0] = "ffffff", [1] = "19ff19", [2] = "0066ff", [3] = "cc66ff", [4] = "ff8000",
}

local QUALITY_SUFFIXES = {
    " %- Common$", " %- Uncommon$", " %- Rare$", " %- Epic$", " %- Legendary$"
}

local function StripQualitySuffix(name)
    for _, pattern in ipairs(QUALITY_SUFFIXES) do
        local stripped = name:match("^(.+)" .. pattern)
        if stripped then return stripped end
    end
    return name
end

local function BuildBestByName()
    local best = {}
    for spellId, data in pairs(ProjectEbonhold.PerkDatabase) do
        local raw = data.comment
        if raw and raw ~= "" then
            local name = StripQualitySuffix(raw)
            local existing = best[name]
            local mask = data.classMask or 0
            if not existing then
                existing = { spellId = spellId, quality = data.quality, qualities = {}, families = data.families or {}, classMask = mask, spellIds = {} }
                best[name] = existing
            else
                existing.classMask = bit.bor(existing.classMask or 0, mask)
                if data.quality > existing.quality then
                    existing.spellId  = spellId
                    existing.quality  = data.quality
                    existing.families = data.families or {}
                end
            end
            existing.qualities[data.quality] = true
            existing.spellIds[data.quality] = spellId
        end
    end
    return best
end

local bestByNameCache

function EbonholdHub.EchoTableRows.BuildBestByName()
    if bestByNameCache then return bestByNameCache end
    bestByNameCache = BuildBestByName()
    return bestByNameCache
end

function EbonholdHub.EchoTableRows.InvalidateBestByName()
    bestByNameCache = nil
end

function EbonholdHub.EchoTableRows.BuildSortedList()
    local best = EbonholdHub.EchoTableRows.BuildBestByName()
    local list = {}
    for name, entry in pairs(best) do
        list[#list + 1] = {
            spellId = entry.spellId, name = name, quality = entry.quality,
            qualities = entry.qualities, families = entry.families,
            classMask = entry.classMask or 0,
            spellIds = entry.spellIds,
        }
    end
    table.sort(list, function(a, b) return a.name < b.name end)
    return list
end

function EbonholdHub.EchoTableRows.BuildAllQualitiesList()
    local list = {}
    for spellId, data in pairs(ProjectEbonhold.PerkDatabase) do
        local raw = data.comment
        if raw and raw ~= "" then
            local name = StripQualitySuffix(raw)
            list[#list + 1] = {
                spellId = spellId,
                name = name,
                quality = data.quality,
                classMask = data.classMask or 0,
            }
        end
    end
    table.sort(list, function(a, b)
        if a.name ~= b.name then return a.name < b.name end
        return a.quality < b.quality
    end)
    return list
end

local function ShowSpellTooltip(owner, spellId, anchor)
    if not owner or not spellId then return end
    local spellName = GetSpellInfo(spellId)
    GameTooltip:SetOwner(owner, anchor or "ANCHOR_RIGHT")
    GameTooltip:ClearLines()
    if spellName then
        GameTooltip:AddLine(spellName, 1, 0.82, 0)
    end
    if utils and utils.GetSpellDescription then
        local description = utils.GetSpellDescription(spellId, 500, 1)
        if description and description ~= "" then
            GameTooltip:AddLine(description, 1, 1, 1, true)
        end
    end
    GameTooltip:Show()
end
EbonholdHub.EchoTableRows.ShowSpellTooltip = ShowSpellTooltip

local function WireIconTooltip(iconFrame)
    iconFrame:SetScript("OnEnter", function(self)
        GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
        GameTooltip:ClearLines()
        if not self.spellId then
            GameTooltip:AddLine("Locked Echo", 1, 0.82, 0)
            GameTooltip:AddLine("Click to pick an echo", 0.6, 0.6, 0.6)
            GameTooltip:AddLine("Right-click to clear", 0.5, 0.5, 0.5)
            GameTooltip:Show()
            return
        end
        ShowSpellTooltip(self, self.spellId)
    end)
    iconFrame:SetScript("OnLeave", function() GameTooltip:Hide() end)
end
EbonholdHub.EchoTableRows.WireIconTooltip = WireIconTooltip

function EbonholdHub.EchoTableRows.CreateLockedSlot(parent, size)
    size = size or 36
    local btn = UI.CreateIconButton(parent, size)

    local empty = btn:CreateTexture(nil, "OVERLAY")
    empty:SetAllPoints(btn.icon)
    empty:SetTexture(0, 0, 0, 0.25)
    btn._empty = empty

    EbonholdHub.EchoTableRows.ClearLockedSlot(btn)
    WireIconTooltip(btn)
    btn:EnableMouse(true)
    btn:RegisterForClicks("LeftButtonUp", "RightButtonUp")
    return btn
end

function EbonholdHub.EchoTableRows.ClearLockedSlot(btn)
    if not btn then return end
    btn.spellId = nil
    btn._quality = nil
    btn.icon:SetTexture("Interface\\Buttons\\UI-EmptySlot")
    btn.icon:SetVertexColor(0.55, 0.55, 0.55)
    if btn._empty then btn._empty:Show() end
    UI.ClearIconButtonQuality(btn)
end

function EbonholdHub.EchoTableRows.SetLockedSlot(btn, spellId, quality)
    if not btn then return end
    if not spellId then
        EbonholdHub.EchoTableRows.ClearLockedSlot(btn)
        return
    end
    btn.spellId = spellId
    btn._quality = quality
    btn.icon:SetTexture(select(3, GetSpellInfo(spellId)))
    btn.icon:SetVertexColor(1, 1, 1)
    if btn._empty then btn._empty:Hide() end
    UI.SetIconButtonQuality(btn, quality)
end

