local addonName, TOAST = ...

local FRAME_W  = 745
local FRAME_H  = 540
local BANNER_H = 100
local LABELS_H = 20
local ROW_H    = 26

local GOLD = { 1, 209/255, 0 }

local COLS = {
    { label = "#",          width = 28,  xOff = 4,   align = "RIGHT"  },
    { label = "Discord",    width = 140, xOff = 36,  align = "LEFT"   },
    { label = "Char-Realm", width = 150, xOff = 180, align = "LEFT"   },
    { label = "Role",       width = 50,  xOff = 334, align = "LEFT"   },
    { label = "RIO",  width = 55, xOff = 388, align = "RIGHT"  },
    { label = "Resi", width = 55, xOff = 453, align = "CENTER",
      headerTex = "Interface\\AddOns\\TOAST\\media\\resi", texSize = 48 },
    { label = "Key",  width = 80, xOff = 518, align = "CENTER" },
}

local CLASS_TOKEN = {
    ["Death Knight"] = "DEATHKNIGHT",
    ["Demon Hunter"] = "DEMONHUNTER",
    ["Druid"]        = "DRUID",
    ["Evoker"]       = "EVOKER",
    ["Hunter"]       = "HUNTER",
    ["Mage"]         = "MAGE",
    ["Monk"]         = "MONK",
    ["Paladin"]      = "PALADIN",
    ["Priest"]       = "PRIEST",
    ["Rogue"]        = "ROGUE",
    ["Shaman"]       = "SHAMAN",
    ["Warlock"]      = "WARLOCK",
    ["Warrior"]      = "WARRIOR",
}

local PREFIX_MAP = {
    ["🌊ᴛɪᴅᴇ"] = { tex = "Interface\\AddOns\\TOAST\\media\\tide", label = "TIDE" },
    ["⚡ᴛɪᴅᴇ"]  = { tex = "Interface\\AddOns\\TOAST\\media\\raid", label = "TIDE" },
    ["🔱ᴛɪᴅᴇ"] = { tex = "Interface\\AddOns\\TOAST\\media\\daan", label = "TIDE" },
    ["🧭ᴛɪᴅᴇ"] = { tex = "Interface\\AddOns\\TOAST\\media\\way",  label = "TIDE" },
    ["💦ꜱᴍɴ"]  = { tex = "Interface\\AddOns\\TOAST\\media\\smn",  label = "SMN"  },
    ["⚓ᴄᴘᴛ"]  = { tex = "Interface\\AddOns\\TOAST\\media\\cpt",  label = "CPT"  },
}

local ROLE_TEX = {
    HEAL = "Interface\\AddOns\\TOAST\\media\\heal",
    DPS  = "Interface\\AddOns\\TOAST\\media\\dps",
    TANK = "Interface\\AddOns\\TOAST\\media\\tank",
}

local lb
local rows = {}

local function BuildLeaderboard()
    lb = CreateFrame("Frame", "TOASTLeaderboard", UIParent, "BackdropTemplate")
    Mixin(lb, BackdropTemplateMixin)
    lb:SetBackdrop({
        bgFile   = "Interface\\DialogFrame\\UI-DialogBox-Background-Dark",
        edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
        edgeSize = 26,
        insets   = { left=9, right=9, top=9, bottom=9 },
    })
    lb:SetBackdropColor(1, 1, 1, 1)
    lb:SetBackdropBorderColor(1, 1, 1, 1)
    lb:SetSize(FRAME_W, FRAME_H)
    lb:SetPoint("CENTER")
    lb:SetMovable(true)
    lb:SetClampedToScreen(true)
    lb:SetFrameStrata("HIGH")
    lb:Hide()

    -- ── Header banner ──────────────────────────────────────────────
    local header = CreateFrame("Frame", nil, lb)
    header:SetSize(FRAME_W, BANNER_H)
    header:SetPoint("TOPLEFT", lb, "TOPLEFT", 0, 0)
    header:EnableMouse(true)
    header:RegisterForDrag("LeftButton")
    header:SetScript("OnDragStart", function() lb:StartMoving() end)
    header:SetScript("OnDragStop",  function() lb:StopMovingOrSizing() end)

    local headerBg = header:CreateTexture(nil, "BACKGROUND")
    headerBg:SetAllPoints()
    headerBg:SetColorTexture(0, 0, 0, 0.65)

    local logo = header:CreateTexture(nil, "OVERLAY")
    logo:SetTexture("Interface\\AddOns\\TOAST\\media\\TOAST")
    logo:SetSize(64, 64)
    logo:SetPoint("TOPLEFT", header, "TOPLEFT", 12, -8)

    local titleFS = header:CreateFontString(nil, "OVERLAY", "GameFontNormalHuge")
    titleFS:SetPoint("TOPLEFT", logo, "TOPRIGHT", 10, -8)
    titleFS:SetText("TOAST Leaderboard")

    local subFS = header:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    subFS:SetPoint("TOPLEFT", titleFS, "BOTTOMLEFT", 0, -4)
    subFS:SetTextColor(GOLD[1], GOLD[2], GOLD[3])
    subFS:SetText("Season Rankings  \226\128\162  " .. #TOAST.roster .. " members")

    local closeBtn = CreateFrame("Button", "TOASTLeaderboardClose", lb, "UIPanelCloseButton")
    closeBtn:SetPoint("TOPRIGHT", lb, "TOPRIGHT", -4, -4)
    closeBtn:SetScript("OnClick", function() TOAST.commands["lb"]() end)

    -- ── Gold separator (y = -BANNER_H) ────────────────────────────
    local goldSep = lb:CreateTexture(nil, "ARTWORK")
    goldSep:SetColorTexture(GOLD[1], GOLD[2], GOLD[3], 1)
    goldSep:SetSize(FRAME_W, 2)
    goldSep:SetPoint("TOPLEFT", lb, "TOPLEFT", 0, -BANNER_H)

    -- ── Search box (between gold sep and column labels) ───────────
    rows = {}
    local content  -- pre-declared so the OnTextChanged closure captures it as an upvalue
    local searchBox = CreateFrame("EditBox", "TOASTLeaderboardSearch", lb, "InputBoxTemplate")
    searchBox:SetSize(200, 22)
    searchBox:SetPoint("TOPRIGHT", lb, "TOPRIGHT", -10, -(BANNER_H + 4))
    searchBox:SetAutoFocus(false)
    searchBox:SetText("Search...")
    searchBox:SetScript("OnEditFocusGained", function(self)
        if self:GetText() == "Search..." then self:SetText("") end
    end)
    searchBox:SetScript("OnEditFocusLost", function(self)
        if self:GetText() == "" then self:SetText("Search...") end
    end)
    searchBox:SetScript("OnTextChanged", function(self)
        if not content then return end
        local query = self:GetText():lower()
        if query == "search..." then
            for i, r in ipairs(rows) do
                r.frame:Show()
                r.frame:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -(i - 1) * ROW_H)
            end
            content:SetHeight(#rows * ROW_H)
            TOASTLeaderboardSF:SetVerticalScroll(0)
            return
        end
        local visibleIndex = 0
        for _, r in ipairs(rows) do
            local match = (query == ""
                or r.name:find(query, 1, true)
                or r.discord:find(query, 1, true))
            if match then
                r.frame:Show()
                r.frame:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -visibleIndex * ROW_H)
                visibleIndex = visibleIndex + 1
            else
                r.frame:Hide()
            end
        end
        content:SetHeight(math.max(visibleIndex * ROW_H, 1))
        TOASTLeaderboardSF:SetVerticalScroll(0)
    end)

    -- ── Column labels (28px below gold sep to clear search box) ───
    local colBar = CreateFrame("Frame", nil, lb)
    colBar:SetSize(FRAME_W - 20, LABELS_H)
    colBar:SetPoint("TOPLEFT", lb, "TOPLEFT", 10, -(BANNER_H + 34))

    for _, col in ipairs(COLS) do
        if col.headerTex then
            local tex = colBar:CreateTexture(nil, "OVERLAY")
            tex:SetTexture(col.headerTex)
            tex:SetSize(col.texSize, col.texSize)
            tex:SetPoint("CENTER", colBar, "LEFT", col.xOff + col.width / 2, 0)
        else
            local fs = colBar:CreateFontString(nil, "OVERLAY", "GameFontNormal")
            fs:SetWidth(col.width)
            fs:SetJustifyH(col.align)
            fs:SetPoint("LEFT", colBar, "LEFT", col.xOff, 0)
            fs:SetTextColor(GOLD[1], GOLD[2], GOLD[3])
            fs:SetText(col.label)
        end
    end

    -- ── Grey separator below labels ────────────────────────────────
    local greySep = lb:CreateTexture(nil, "ARTWORK")
    greySep:SetColorTexture(0.5, 0.5, 0.5, 0.4)
    greySep:SetSize(FRAME_W, 1)
    greySep:SetPoint("TOPLEFT", lb, "TOPLEFT", 0, -(BANNER_H + 34 + LABELS_H + 1))

    -- ── Scroll frame ───────────────────────────────────────────────
    -- Starts 2px below grey sep; leaves 20px bottom margin for backdrop border.
    local SF_TOP  = BANNER_H + 34 + LABELS_H + 3
    local sf = CreateFrame("ScrollFrame", "TOASTLeaderboardSF", lb, "UIPanelScrollFrameTemplate")
    sf:SetSize(FRAME_W - 54, FRAME_H - SF_TOP - 20)
    sf:SetPoint("TOPLEFT", lb, "TOPLEFT", 10, -SF_TOP)

    content = CreateFrame("Frame", nil, sf)
    content:SetSize(FRAME_W - 54, #TOAST.roster * ROW_H)
    sf:SetScrollChild(content)

    local playerName = UnitName("player")

    for i, entry in ipairs(TOAST.roster) do
        local row = CreateFrame("Frame", nil, content)
        row:SetSize(FRAME_W - 54, ROW_H)
        row:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -(i - 1) * ROW_H)

        local isEven = (i % 2 == 0)
        local bg = row:CreateTexture(nil, "BACKGROUND")
        bg:SetAllPoints()
        if isEven then
            bg:SetColorTexture(0.1, 0.1, 0.3, 0.15)
        else
            bg:SetColorTexture(0, 0, 0, 0)
        end

        local isSelf = (entry.name == playerName)
        if isSelf then
            bg:SetColorTexture(1, 0.84, 0, 0.12)
            local border = row:CreateTexture(nil, "OVERLAY")
            border:SetColorTexture(1, 0.84, 0, 0.6)
            border:SetSize(FRAME_W - 54, 1)
            border:SetPoint("TOPLEFT", row, "TOPLEFT", 0, 0)
            local border2 = row:CreateTexture(nil, "OVERLAY")
            border2:SetColorTexture(1, 0.84, 0, 0.6)
            border2:SetSize(FRAME_W - 54, 1)
            border2:SetPoint("BOTTOMLEFT", row, "BOTTOMLEFT", 0, 0)
        end

        row:EnableMouse(true)
        row:SetScript("OnEnter", function()
            bg:SetColorTexture(1, 0.84, 0, 0.08)
        end)
        row:SetScript("OnLeave", function()
            if isSelf then
                bg:SetColorTexture(1, 0.84, 0, 0.12)
            elseif isEven then
                bg:SetColorTexture(0.1, 0.1, 0.3, 0.15)
            else
                bg:SetColorTexture(0, 0, 0, 0)
            end
        end)

        -- Class-colored name, plain realm: "Name-Realm"
        local token = CLASS_TOKEN[entry.class_]
        local c = token and RAID_CLASS_COLORS[token]
        local charRealm
        if c then
            charRealm = string.format("|cff%02x%02x%02x%s|r-%s",
                math.floor(c.r * 255), math.floor(c.g * 255), math.floor(c.b * 255),
                entry.name, entry.realm)
        else
            charRealm = entry.name .. "-" .. entry.realm
        end

        local keyData = TOAST.keys and TOAST.keys[entry.name]
        local keyVal  = keyData and ("+" .. keyData.level .. " " .. keyData.short) or "\226\128\148"

        local vals = {
            entry.rank,
            "",  -- ci==2 handled below via PREFIX_MAP
            charRealm,
            entry.role,
            entry.rio,
            entry.resi,
            keyVal,
        }

        local keyFS
        for ci, col in ipairs(COLS) do
            if ci == 2 then
                local prefix = entry.discord_nickname:match("^(%S+)")
                local p = prefix and PREFIX_MAP[prefix]
                local name = entry.discord_nickname:match("^%S+ (.+)$") or entry.discord_nickname
                if p then
                    local icon = row:CreateTexture(nil, "OVERLAY")
                    icon:SetTexture(p.tex)
                    icon:SetSize(20, 20)
                    icon:SetPoint("LEFT", row, "LEFT", col.xOff, 0)

                    local labelFS = row:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
                    labelFS:SetPoint("LEFT", row, "LEFT", col.xOff + 14, 0)
                    labelFS:SetText(p.label)

                    local nameFS = row:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
                    nameFS:SetWidth(col.width - 48)
                    nameFS:SetJustifyH("LEFT")
                    nameFS:SetPoint("LEFT", row, "LEFT", col.xOff + 48, 0)
                    nameFS:SetText(name)
                else
                    local fs = row:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
                    fs:SetWidth(col.width)
                    fs:SetJustifyH(col.align)
                    fs:SetPoint("LEFT", row, "LEFT", col.xOff, 0)
                    fs:SetText(name)
                end
            elseif ci == 4 then
                local tex = row:CreateTexture(nil, "OVERLAY")
                tex:SetTexture(ROLE_TEX[entry.role] or "")
                tex:SetSize(22, 22)
                tex:SetPoint("LEFT", row, "LEFT", col.xOff, 0)
            else
                local fs = row:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
                fs:SetWidth(col.width)
                fs:SetJustifyH(col.align)
                fs:SetPoint("LEFT", row, "LEFT", col.xOff, 0)
                fs:SetText(tostring(vals[ci]))
                if ci == 7 then keyFS = fs end
            end
        end
        rows[i] = { frame = row, name = entry.name:lower(), discord = entry.discord_nickname:lower(), keyFS = keyFS }
    end
    content:SetHeight(#TOAST.roster * ROW_H)
end

TOAST.RefreshKeyColumn = function()
    if not lb then return end
    for i, r in ipairs(rows) do
        local entry   = TOAST.roster[i]
        local keyData = TOAST.keys and TOAST.keys[entry.name]
        r.keyFS:SetText(keyData and ("+" .. keyData.level .. " " .. keyData.short) or "\226\128\148")
    end
end

TOAST.commands["lb"] = function()
    if not lb then BuildLeaderboard() end
    if lb:IsShown() then lb:Hide() else lb:Show() end
end
