EbonholdHub.GearSetStrip = {}

local UI = EbonholdHub.UI
local C  = UI.Colors
local EL = EbonholdHub.EquipmentLoadout

local SET_ROW_H = 26
local MAX_SETS = 8

local popupState = {}

local function ResolvePopupEditBox(frame)
    if not frame then return nil end
    if frame.editBox then return frame.editBox end
    return _G[frame:GetName() .. "EditBox"]
end

StaticPopupDialogs["EBONHOLDHUB_RENAME_GEAR_SET"] = {
    text = "Rename gear set:",
    button1 = OKAY,
    button2 = CANCEL,
    hasEditBox = true,
    maxLetters = 32,
    OnAccept = function(self)
        local data = popupState
        if not data or not data.sets or not data.index then return end
        local editBox = data.editBox or ResolvePopupEditBox(self)
        local name = editBox and editBox:GetText() or ""
        if EL.RenameSetIn(data.sets, data.index, name) and data.onDone then
            data.onDone()
        end
    end,
    EditBoxOnEnterPressed = function(self)
        popupState.editBox = self
        local parent = self:GetParent()
        if parent and parent.button1 then
            parent.button1:Click()
        end
    end,
    OnShow = function(self)
        local editBox = ResolvePopupEditBox(self)
        popupState.editBox = editBox
        local set = popupState.sets and popupState.sets[popupState.index]
        if editBox then
            editBox:SetText(set and set.name or "")
            editBox:HighlightText()
            editBox:SetFocus()
        end
    end,
    timeout = 0,
    whileDead = true,
    hideOnEscape = true,
    preferredIndex = 3,
}

StaticPopupDialogs["EBONHOLDHUB_DELETE_GEAR_SET"] = {
    text = "Delete this gear set?\n\nItems in this set will be lost.",
    button1 = DELETE,
    button2 = CANCEL,
    OnAccept = function()
        local data = popupState
        if not data or not data.sets or not data.index then return end
        if EL.RemoveSetFrom(data.sets, data.index, data.getActiveIndex, data.setActiveIndex) and data.onDone then
            data.onDone()
        end
    end,
    timeout = 0,
    whileDead = true,
    hideOnEscape = true,
    preferredIndex = 3,
}

local function StyleChip(btn, selected)
    if selected then
        UI.SetFont(btn.label, UI.FONT_SIZE_SMALL, C.text)
        btn._bg:SetVertexColor(C.accent[1], C.accent[2], C.accent[3], 0.18)
    else
        UI.SetFont(btn.label, UI.FONT_SIZE_SMALL, C.textDim)
        btn._bg:SetVertexColor(0.12, 0.12, 0.14, 0.85)
    end
end

local function CreateChip(parent, text, width)
    local btn = CreateFrame("Button", nil, parent)
    btn:SetSize(width or 72, SET_ROW_H)
    btn:RegisterForClicks("LeftButtonUp", "RightButtonUp")
    local bg = btn:CreateTexture(nil, "BACKGROUND")
    bg:SetAllPoints()
    bg:SetTexture("Interface\\Buttons\\WHITE8X8")
    btn._bg = bg
    local label = btn:CreateFontString(nil, "OVERLAY")
    UI.SetFont(label, UI.FONT_SIZE_SMALL, C.textDim)
    label:SetPoint("LEFT", btn, "LEFT", 8, 0)
    label:SetPoint("RIGHT", btn, "RIGHT", -8, 0)
    label:SetJustifyH("LEFT")
    label:SetText(text or "")
    btn.label = label
    StyleChip(btn, false)
    return btn
end

function EbonholdHub.GearSetStrip.Create(parent, opts)
    opts = opts or {}
    local editable = opts.editable ~= false

    local holder = CreateFrame("Frame", nil, parent)
    holder:SetHeight(SET_ROW_H)

    local strip = CreateFrame("Frame", nil, holder)
    strip:SetPoint("TOPLEFT", holder, "TOPLEFT", 0, 0)
    strip:SetPoint("BOTTOMLEFT", holder, "BOTTOMLEFT", 0, 0)
    strip:SetHeight(SET_ROW_H)

    holder._strip = strip
    holder._chips = {}
    holder._editable = editable
    holder._build = opts.build
    holder._getBuild = opts.getBuild
    holder._onChange = opts.onChange

    local function ResolveBuild()
        if holder._getBuild then
            holder._build = holder._getBuild()
        end
    end

    local function GetContext()
        ResolveBuild()
        if holder._build then
            return EL.GetSetsForBuild(holder._build)
        end
        return EL.GetSets()
    end

    local function SelectIndex(index)
        ResolveBuild()
        if holder._build then
            EL.SetActiveSetIndexForBuild(holder._build, index)
        else
            EL.SetActiveSetIndex(index)
        end
    end

    local function ShowRenameDialog(index)
        local sets = GetContext()
        popupState = {
            sets = sets,
            index = index,
            onDone = function()
                holder:Refresh()
                if holder._onChange then holder._onChange() end
            end,
        }
        StaticPopup_Show("EBONHOLDHUB_RENAME_GEAR_SET")
    end

    local function ShowDeleteDialog(index)
        local sets = GetContext()
        popupState = {
            sets = sets,
            index = index,
            getActiveIndex = function()
                local _, idx = GetContext()
                return idx
            end,
            setActiveIndex = SelectIndex,
            onDone = function()
                holder:Refresh()
                if holder._onChange then holder._onChange() end
            end,
        }
        StaticPopup_Show("EBONHOLDHUB_DELETE_GEAR_SET")
    end

    function holder:Refresh()
        for _, chip in ipairs(self._chips) do
            chip:Hide()
        end
        self._chips = {}

        local sets, active = GetContext()
        if not editable and #sets <= 1 then
            self:Hide()
            return
        end
        self:Show()
        local prev

        for i, set in ipairs(sets) do
            local label = set.name or ("Set " .. i)
            local filled = EL.CountFilled(set.loadout)
            if filled > 0 then
                label = label .. " (" .. filled .. ")"
            end
            local chip = CreateChip(strip, label, math.min(160, math.max(72, #label * 6 + 18)))
            if prev then
                chip:SetPoint("LEFT", prev, "RIGHT", 4, 0)
            else
                chip:SetPoint("LEFT", strip, "LEFT", 0, 0)
            end
            prev = chip
            StyleChip(chip, i == active)

            chip:SetScript("OnClick", function(_, button)
                if editable and button == "RightButton" then
                    if IsShiftKeyDown() and #sets > 1 then
                        ShowDeleteDialog(i)
                    else
                        ShowRenameDialog(i)
                    end
                    return
                end
                if button == "LeftButton" and i ~= active then
                    SelectIndex(i)
                    holder:Refresh()
                    if holder._onChange then holder._onChange() end
                end
            end)

            chip:SetScript("OnEnter", function(self)
                GameTooltip:SetOwner(self, "ANCHOR_BOTTOM")
                GameTooltip:ClearLines()
                GameTooltip:AddLine(set.name or ("Set " .. i), 1, 0.82, 0)
                if editable then
                    GameTooltip:AddLine("Right-click to rename", 0.6, 0.6, 0.6)
                    if #sets > 1 then
                        GameTooltip:AddLine("Shift + right-click to delete", 0.6, 0.6, 0.6)
                    end
                end
                GameTooltip:Show()
            end)
            chip:SetScript("OnLeave", function() GameTooltip:Hide() end)

            self._chips[#self._chips + 1] = chip
        end

        if editable and #sets < MAX_SETS then
            local addBtn = UI.CreateButton(strip, 28, SET_ROW_H, "+", { hoverBorder = C.accent })
            addBtn:RegisterForClicks("LeftButtonUp")
            if prev then
                addBtn:SetPoint("LEFT", prev, "RIGHT", 4, 0)
            else
                addBtn:SetPoint("LEFT", strip, "LEFT", 0, 0)
            end
            addBtn:SetScript("OnClick", function()
                EL.AddSet(nil, false)
                holder:Refresh()
                if holder._onChange then holder._onChange() end
            end)
            addBtn:SetScript("OnEnter", function(self)
                GameTooltip:SetOwner(self, "ANCHOR_BOTTOM")
                GameTooltip:AddLine("Add gear set", 1, 0.82, 0)
                GameTooltip:AddLine("Creates an empty alternative loadout.", 0.6, 0.6, 0.6)
                GameTooltip:Show()
            end)
            addBtn:SetScript("OnLeave", function() GameTooltip:Hide() end)
            self._chips[#self._chips + 1] = addBtn
            prev = addBtn
        end

        local width = 0
        for _, chip in ipairs(self._chips) do
            width = width + chip:GetWidth() + 4
        end
        strip:SetWidth(math.max(1, width))
        holder:SetWidth(math.max(1, width))
    end

    holder:Refresh()
    return holder
end

function EbonholdHub.GearSetStrip.RowHeight()
    return SET_ROW_H
end
