-- ETB Alt Overview Panel (Phase 3) — instance-major weekly lockout grid.
-- Docks to the right of the Wishlist window. Rows are instances + world bosses,
-- columns are characters, cells are colour-coded: green = still open, red = done,
-- amber = partially cleared. One horizontal scan answers "who can still farm X".
local ADDON_NAME, NS = ...
local ETB = NS.ETB
if not ETB then return end

ETB.AltOverview = {}
local AO = ETB.AltOverview
AO.frame = nil
AO.elements = {}

local LABEL_W   = 156      -- instance-name column
local COL_W     = 74       -- per-character column
local ROW_H     = 22
local HEADER_H  = 38
local TOP_PAD   = 56       -- title + reserved space above the grid
local SIDE_PAD  = 14
local LEGEND_H  = 26

-- Status colours. Background is the primary signal; text is a quiet confirmation.
local STATUS = {
    open    = { 0.14, 0.42, 0.16, "ff9be8a0", "open" },
    done    = { 0.42, 0.14, 0.14, "ffe89b9b", "done" },
    partial = { 0.44, 0.36, 0.10, "fff0d878", nil    },  -- text becomes "x/y"
    locked  = { 0.44, 0.28, 0.10, "fff0c078", "lock" },  -- legacy raid, no per-boss data
}

local function clear()
    for _, el in ipairs(AO.elements) do
        el:Hide(); el:ClearAllPoints(); el:SetParent(nil)
    end
    wipe(AO.elements)
end

local function mk(ftype, parent, tmpl)
    local f = CreateFrame(ftype or "Frame", nil, parent, tmpl)
    AO.elements[#AO.elements + 1] = f
    return f
end

local function classColor(class)
    local c = class and RAID_CLASS_COLORS and RAID_CLASS_COLORS[class]
    if c then return c.r, c.g, c.b end
    return 0.9, 0.9, 0.9
end

-- A single grid cell: coloured background + short status label.
local function cell(parent, x, y, status, prog, total)
    local s = STATUS[status] or STATUS.open
    local c = mk("Frame", parent)
    c:SetSize(COL_W - 4, ROW_H - 3)
    c:SetPoint("TOPLEFT", x, y)
    local bg = c:CreateTexture(nil, "BACKGROUND")
    bg:SetAllPoints()
    bg:SetColorTexture(s[1], s[2], s[3], 0.55)
    local fs = c:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    fs:SetPoint("CENTER")
    local label = s[5]
    if status == "partial" then label = (prog or 0) .. "/" .. (total or 0) end
    fs:SetText("|c" .. s[4] .. (label or "") .. "|r")
    return c
end

function AO:Create()
    if self.frame then return self.frame end
    local f = CreateFrame("Frame", "ETBAltOverviewPanel", UIParent, "BackdropTemplate")
    f:SetFrameStrata("HIGH")
    f:SetFrameLevel(90)   -- just under the wishlist window so its border reads on top
    if f.SetBackdrop then
        f:SetBackdrop({
            bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background-Dark",
            edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Border",
            tile = true, tileSize = 32, edgeSize = 32,
            insets = { left = 8, right = 8, top = 8, bottom = 8 },
        })
    end
    f.title = f:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    f.title:SetPoint("TOP", 0, -16)
    f.title:SetText("|cffffd100Weekly Overview|r")
    f.sub = f:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    f.sub:SetPoint("TOP", f.title, "BOTTOM", 0, -3)
    f.sub:SetTextColor(0.5, 0.5, 0.5)
    self.frame = f
    return f
end

-- Render the grid from the current AltTracker snapshot data.
function AO:Render()
    local f = self:Create()
    clear()

    local AT = ETB.AltTracker
    local data = AT and AT.BuildOverview and AT:BuildOverview()
    if not data or #data.chars == 0 then
        f:SetSize(280, 120)
        f.sub:SetText("No characters tracked yet")
        local msg = mk("Frame", f)
        msg:SetSize(252, 40); msg:SetPoint("TOP", 0, -TOP_PAD)
        local t = msg:CreateFontString(nil, "OVERLAY", "GameFontDisable")
        t:SetPoint("CENTER"); t:SetWidth(248)
        t:SetText("Log into your characters with ETB enabled to populate this overview.")
        return
    end

    local chars = data.chars
    local nCols = #chars

    local gridW = SIDE_PAD * 2 + LABEL_W + nCols * COL_W
    local nRows = #data.instances
        + (#data.worldBosses > 0 and (#data.worldBosses + 1) or 0)
        + (#data.dailies > 0 and (#data.dailies + 1) or 0)
    local gridH = TOP_PAD + HEADER_H + nRows * ROW_H + LEGEND_H + 14
    f:SetSize(math.max(gridW, 280), math.max(gridH, 140))
    f.sub:SetText(nCols .. " characters - this reset")

    local x0 = SIDE_PAD
    local y0 = -TOP_PAD

    -- Column headers: class-coloured character names + level.
    for i, ch in ipairs(chars) do
        local hx = x0 + LABEL_W + (i - 1) * COL_W
        local h = mk("Frame", f)
        h:SetSize(COL_W - 4, HEADER_H)
        h:SetPoint("TOPLEFT", hx, y0)
        local nm = h:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
        nm:SetPoint("TOP", 0, -2); nm:SetWidth(COL_W - 6)
        local r, g, b = classColor(ch.class)
        nm:SetText(ch.name or "?")
        nm:SetTextColor(r, g, b)
        local lv = h:CreateFontString(nil, "OVERLAY", "GameFontDisableSmall")
        lv:SetPoint("TOP", nm, "BOTTOM", 0, -1)
        lv:SetText("L" .. (ch.level or 0))
        h:EnableMouse(true)
        h:SetScript("OnEnter", function(s)
            GameTooltip:SetOwner(s, "ANCHOR_BOTTOM")
            GameTooltip:AddLine(ch.name or "?", r, g, b)
            GameTooltip:AddLine("Level " .. (ch.level or 0) .. " - " .. (ch.armorType or "?"), 0.8, 0.8, 0.8)
            GameTooltip:Show()
        end)
        h:SetScript("OnLeave", function() GameTooltip:Hide() end)
    end

    local y = y0 - HEADER_H

    -- One row per instance.
    local function row(label, isWB, getStatus)
        local lr = mk("Frame", f)
        lr:SetSize(LABEL_W, ROW_H)
        lr:SetPoint("TOPLEFT", x0, y)
        local lt = lr:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
        lt:SetPoint("LEFT", 2, 0); lt:SetWidth(LABEL_W - 6); lt:SetJustifyH("LEFT")
        lt:SetText(label)
        if isWB then lt:SetTextColor(0.7, 0.85, 1) end
        for i, ch in ipairs(chars) do
            local cx = x0 + LABEL_W + (i - 1) * COL_W
            local status, prog, total = getStatus(ch.key)
            cell(f, cx, y, status, prog, total)
        end
        y = y - ROW_H
    end

    -- A section divider header spanning the grid width.
    local function section(title)
        local div = mk("Frame", f)
        div:SetSize(LABEL_W + nCols * COL_W, ROW_H)
        div:SetPoint("TOPLEFT", x0, y)
        local dt = div:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
        dt:SetPoint("LEFT", 2, 0)
        dt:SetText("|cffffd100" .. title .. "|r")
        y = y - ROW_H
    end

    for _, inst in ipairs(data.instances) do
        row(inst.name or "?", false, function(key)
            return AT:InstanceStatus(key, inst.key)
        end)
    end

    -- World boss section (weekly).
    if #data.worldBosses > 0 then
        section("World Bosses")
        for _, wb in ipairs(data.worldBosses) do
            row(wb.name or "?", true, function(key)
                return AT:WorldBossStatus(key, wb.key)
            end)
        end
    end

    -- Daily lockouts (heroic scenarios and anything else with a ~24h reset).
    if #data.dailies > 0 then
        section("Daily")
        for _, inst in ipairs(data.dailies) do
            row(inst.name or "?", false, function(key)
                return AT:InstanceStatus(key, inst.key)
            end)
        end
    end

    -- Legend.
    local legend = mk("Frame", f)
    legend:SetSize(gridW - SIDE_PAD * 2, LEGEND_H)
    legend:SetPoint("TOPLEFT", x0, y - 4)
    local lg = legend:CreateFontString(nil, "OVERLAY", "GameFontDisableSmall")
    lg:SetPoint("LEFT", 2, 0)
    lg:SetText("|cff9be8a0open|r  |cfff0d878partial|r  |cffe89b9bdone|r"
        .. "   |cff808080(other characters as of their last login)|r")
end

-- Position relative to a host frame (the Wishlist window) so it tracks movement.
function AO:Anchor(host)
    local f = self:Create()
    f:ClearAllPoints()
    f:SetPoint("TOPLEFT", host, "TOPRIGHT", 6, 0)
    self._host = host
end

function AO:Show(host)
    self:Create()
    if host then
        self:Anchor(host)
    elseif not self._host then
        self.frame:ClearAllPoints()
        self.frame:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
    end
    self:Render()
    self.frame:Show()
    self._shown = true
end

function AO:Hide()
    if self.frame then self.frame:Hide() end
    self._shown = false
end

function AO:Toggle(host)
    if self._shown and self.frame and self.frame:IsShown() then
        self:Hide()
    else
        self:Show(host)
    end
end

function AO:IsShown()
    return self._shown and self.frame and self.frame:IsShown()
end

-- Live refresh: redraw if the panel is open when lockouts change or when an
-- appearance is collected (so dungeon progress stays current).
if ETB.EventBus then
    local function refresh() if AO:IsShown() then AO:Render() end end
    ETB.EventBus:Register("ETB_LOCKOUTS_UPDATED", refresh)
    ETB.EventBus:Register("ETB_ITEM_COLLECTED", refresh)
end

ETB:Debug("AltOverview", "Weekly overview panel loaded")
return AO
