-- VDS_Popups
-- ============================================================================
-- StaticPopupDialogs for palette management + help. Lifted from
-- VDS_DyePanel.lua:437-... and adapted to dispatch Lattice actions.
-- Export/import format matches the donor for cross-version round-trips.

VDS = VDS or {}

local A = VDS.Constants.ACTIONS

-- ----------------------------------------------------------------------------
-- VDS_DYE_STUDIO_HELP
-- ----------------------------------------------------------------------------

_G.StaticPopupDialogs["VDS_DYE_STUDIO_HELP"] = {
    text = "|cFFFF6B6BVam|r|cFFFFA500oos|r|cFFFFD700e's|r|cFF32CD32 Dye|r|cFF00BFFF Stu|r|cFF9932CCdio|r\n\n"
        .. "|cFFfcd34dTabs:|r |cFFFFD700Colors|r  |cFF32CD32Custom|r  |cFF9932CCTheme|r  "
        .. "|cFF00BFFFStock|r  |cFFA0DA63Herbs|r  |cFFDC143CCanvas|r\n\n"
        .. "|cFFfcd34dColors:|r All dyes grouped by color family. Click a chip to filter.\n"
        .. "|cFFfcd34dCustom:|r Your saved palettes -- create, edit, import/export.\n"
        .. "|cFFfcd34dTheme:|r Curated themed + class palettes.\n"
        .. "|cFFfcd34dStock:|r Set per-group dye targets, see deficits, one-click "
        .. "Restock-and-Send-to-AH (Buy mode = dyes; Craft mode = herbs).\n"
        .. "|cFFfcd34dHerbs:|r Reverse-lookup which dyes each herb feeds, with AH price.\n"
        .. "|cFFfcd34dCanvas:|r 3D dye trial -- pick a decor, dye each channel, "
        .. "save & restore loadouts.\n\n"
        .. "|cFFfcd34dClick a dye:|r select it (detail strip below).\n"
        .. "|cFFfcd34dShift-click:|r search the Auction House by dye name.\n"
        .. "|cFFfcd34dCanvas left-click:|r apply to the active channel.\n"
        .. "|cFFfcd34dCanvas right-click:|r clear the active channel.\n"
        .. "|cFFfcd34dLive mode:|r click any dye to apply to the focused slot.\n\n"
        .. "|cFFfcd34dCount cell:|r |cFF4ade80green x7|r = owned, |cFF888888--|r = none\n\n"
        .. "|cFFfcd34dConfig (cog):|r filters, minimap toggle, debug log, dye-picker replacement.\n"
        .. "|cFFfcd34dReplace Blizzard dye picker:|r on by default; VDS opens "
        .. "automatically in the housing editor.\n\n"
        .. "|cFFfcd34d/vds|r or |cFFfcd34d/dyes|r - open the studio\n"
        .. "|cFFfcd34d/vds debug|r - toggle debug logging\n"
        .. "|cFFfcd34d/vds minimap|r - toggle the minimap icon\n"
        .. "|cFFfcd34d/vds hardreset|r - reset all VDS data (requires /reload)\n\n"
        .. "|cFF666666Stock targets and palettes persist across sessions.|r\n\n"
        .. "|TInterface\\Icons\\inv_misc_flower_02:14|t |cFFFF69B4Color groups "
        .. "community-verified and testing help by Kiyo. Thanks Kiyo!|r\n"
        .. "|TInterface\\Icons\\inv_misc_gem_diamond_02:14|t |cFF7FFFD4Key supporter "
        .. "-- testing + feature ideas by ReganB. Thanks ReganB!|r",
    button1 = "Close",
    timeout = 0,
    whileDead = true,
    hideOnEscape = true,
    wide = true,
    preferredIndex = 3,
    OnShow = function(self)
        self:SetWidth(self:GetWidth() * 1.5)
        self.Text:SetJustifyH("LEFT")
        self.Text:SetTextColor(0.8, 0.8, 0.8, 1)
    end,
}

-- ----------------------------------------------------------------------------
-- VDS_RENAME_CUSTOM_THEME  (popup.data = old name)
-- ----------------------------------------------------------------------------

_G.StaticPopupDialogs["VDS_RENAME_CUSTOM_THEME"] = {
    text         = "Rename palette \"%s\":",  -- StaticPopup_Show 2nd arg fills %s
    button1      = "Rename",
    button2      = "Cancel",
    hasEditBox   = true,
    editBoxWidth = 200,
    OnShow = function(self)
        self.EditBox:SetText(self.data or "")
        self.EditBox:HighlightText()
        self.EditBox:SetFocus()
    end,
    OnAccept = function(self)
        local newName = (self.EditBox:GetText() or ""):match("^%s*(.-)%s*$")
        if newName == "" then return end
        local oldName = self.data
        VDS.Store:Dispatch({
            type    = A.CUSTOM_THEME_RENAME,
            payload = { from = oldName, to = newName },
        })
    end,
    EditBoxOnEnterPressed = function(self)
        local parent  = self:GetParent()
        local newName = (self:GetText() or ""):match("^%s*(.-)%s*$")
        if newName == "" then return end
        VDS.Store:Dispatch({
            type    = A.CUSTOM_THEME_RENAME,
            payload = { from = parent.data, to = newName },
        })
        parent:Hide()
    end,
    EditBoxOnEscapePressed = function(self) self:GetParent():Hide() end,
    timeout      = 0,
    whileDead    = true,
    hideOnEscape = true,
    preferredIndex = 3,
}

-- ----------------------------------------------------------------------------
-- VDS_CANVAS_RENAME_LOADOUT  (popup.data = { decorID, idx, oldName })
-- ----------------------------------------------------------------------------

_G.StaticPopupDialogs["VDS_CANVAS_RENAME_LOADOUT"] = {
    text         = "Rename loadout:",
    button1      = "Rename",
    button2      = "Cancel",
    hasEditBox   = true,
    editBoxWidth = 200,
    OnShow = function(self)
        self.EditBox:SetText((self.data and self.data.oldName) or "")  -- exception(boundary): StaticPopup data set by caller; absent on direct show
        self.EditBox:HighlightText()
        self.EditBox:SetFocus()
    end,
    OnAccept = function(self)
        local newName = (self.EditBox:GetText() or ""):match("^%s*(.-)%s*$")
        VDS.Store:Dispatch({
            type    = A.CANVAS_RENAME_LOADOUT,
            payload = { decorID = self.data.decorID, idx = self.data.idx, name = newName },
        })
    end,
    EditBoxOnEnterPressed = function(self)
        local parent  = self:GetParent()
        local newName = (self:GetText() or ""):match("^%s*(.-)%s*$")
        VDS.Store:Dispatch({
            type    = A.CANVAS_RENAME_LOADOUT,
            payload = { decorID = parent.data.decorID, idx = parent.data.idx, name = newName },
        })
        parent:Hide()
    end,
    EditBoxOnEscapePressed = function(self) self:GetParent():Hide() end,
    timeout      = 0,
    whileDead    = true,
    hideOnEscape = true,
    preferredIndex = 3,
}

-- ----------------------------------------------------------------------------
-- VDS_CREATE_CUSTOM_THEME
-- ----------------------------------------------------------------------------

_G.StaticPopupDialogs["VDS_CREATE_CUSTOM_THEME"] = {
    text         = "Name for the new palette:",
    button1      = "Create",
    button2      = "Cancel",
    hasEditBox   = true,
    editBoxWidth = 200,
    OnShow = function(self)
        -- Default: "Palette N" where N = highest existing "Palette K" + 1.
        local highest = 0
        for _, t in ipairs(VDS.Store:GetState().account.customThemes) do
            local n = t.name and tonumber(t.name:match("^Palette%s+(%d+)$"))
            if n and n > highest then highest = n end
        end
        self.EditBox:SetText("Palette " .. (highest + 1))
        self.EditBox:HighlightText()
        self.EditBox:SetFocus()
    end,
    OnAccept = function(self)
        local name = (self.EditBox:GetText() or ""):match("^%s*(.-)%s*$")
        if name == "" then return end
        VDS.Store:Dispatch({
            type    = A.CUSTOM_THEME_CREATE,
            payload = { name = name, dyes = {} },
        })
    end,
    EditBoxOnEnterPressed = function(self)
        local parent = self:GetParent()
        local name = (self:GetText() or ""):match("^%s*(.-)%s*$")
        if name == "" then return end
        VDS.Store:Dispatch({
            type    = A.CUSTOM_THEME_CREATE,
            payload = { name = name, dyes = {} },
        })
        parent:Hide()
    end,
    EditBoxOnEscapePressed = function(self) self:GetParent():Hide() end,
    timeout      = 0,
    whileDead    = true,
    hideOnEscape = true,
    preferredIndex = 3,
}

-- ----------------------------------------------------------------------------
-- VDS_DELETE_CUSTOM_THEME
-- ----------------------------------------------------------------------------

_G.StaticPopupDialogs["VDS_DELETE_CUSTOM_THEME"] = {
    text = "Delete palette \"%s\"? This cannot be undone.",
    button1 = "Delete",
    button2 = "Cancel",
    OnAccept = function(self)
        VDS.Store:Dispatch({
            type    = A.CUSTOM_THEME_DELETE,
            payload = { name = self.data },
        })
    end,
    timeout = 0,
    whileDead = true,
    hideOnEscape = true,
    preferredIndex = 3,
}

-- ----------------------------------------------------------------------------
-- VDS_EXPORT_CUSTOM_THEME  (popup.data = { name, dyeIDs[] })
-- ----------------------------------------------------------------------------

_G.StaticPopupDialogs["VDS_EXPORT_CUSTOM_THEME"] = {
    text = "Export string for \"%s\" (select + Ctrl-C):",
    button1 = "Close",
    hasEditBox = true,
    editBoxWidth = 260,
    OnShow = function(self)
        local d = self.data or {}
        -- "VDS:" prefix on export; import also accepts "VDS:" for donor cross-import.
        local name = d.name or "palette"
        local ids = d.dyeIDs or {}
        local idStrs = {}
        for _, id in ipairs(ids) do idStrs[#idStrs + 1] = tostring(id) end
        local payload = name .. "|" .. table.concat(idStrs, ",")
        local encoded = "VDS:" .. VDS.StaticData.Base64Encode(payload)
        self.EditBox:SetText(encoded)
        self.EditBox:HighlightText()
        self.EditBox:SetFocus()
    end,
    EditBoxOnEscapePressed = function(self) self:GetParent():Hide() end,
    timeout = 0,
    whileDead = true,
    hideOnEscape = true,
    preferredIndex = 3,
}

-- ----------------------------------------------------------------------------
-- VDS_CANVAS_SAVE_LOADOUT  (popup.data = { decorID, dyes })
-- ----------------------------------------------------------------------------

_G.StaticPopupDialogs["VDS_CANVAS_SAVE_LOADOUT"] = {
    text         = "Save loadout as:",
    button1      = "Save",
    button2      = "Cancel",
    hasEditBox   = true,
    editBoxWidth = 200,
    OnShow = function(self)
        -- Default: "Loadout N" where N = highest existing "Loadout K" index for
        -- this decor + 1 (1 when none exist). decorID is read from state
        -- because popup.data is assigned AFTER StaticPopup_Show fires OnShow
        -- (caller pattern); state has the same decorID the snapshot will use.
        local decorID = VDS.Store:GetState().session.ui.canvas.decorID
        local highest = 0
        local list = decorID and VDS.Store:GetState().account.canvas.loadouts[decorID]
        if list then
            for _, lo in ipairs(list) do
                local n = lo.name and tonumber(lo.name:match("^Loadout%s+(%d+)$"))
                if n and n > highest then highest = n end
            end
        end
        self.EditBox:SetText("Loadout " .. (highest + 1))
        self.EditBox:HighlightText()
        self.EditBox:SetFocus()
    end,
    OnAccept = function(self)
        local name = (self.EditBox:GetText() or ""):match("^%s*(.-)%s*$")
        if name == "" then return end
        local d = self.data or {}
        VDS.Store:Dispatch({
            type    = A.CANVAS_SAVE_LOADOUT,
            payload = { decorID = d.decorID, dyes = d.dyes, name = name },
        })
    end,
    EditBoxOnEnterPressed = function(self)
        local parent = self:GetParent()
        local name = (self:GetText() or ""):match("^%s*(.-)%s*$")
        if name == "" then return end
        local d = parent.data or {}
        VDS.Store:Dispatch({
            type    = A.CANVAS_SAVE_LOADOUT,
            payload = { decorID = d.decorID, dyes = d.dyes, name = name },
        })
        parent:Hide()
    end,
    EditBoxOnEscapePressed = function(self) self:GetParent():Hide() end,
    timeout      = 0,
    whileDead    = true,
    hideOnEscape = true,
    preferredIndex = 3,
}

-- Accepts: VDS:<base64> (current), VDSR:<base64> (legacy pre-rename export),
-- or raw CSV (donor). Returns name + ids, or nil + error string.
local function parseImportPayload(text)
    text = (text or ""):gsub("^%s+", ""):gsub("%s+$", "")
    if text == "" then return nil, "empty input" end

    local prefix, b64
    if text:sub(1, 5) == "VDSR:" then
        prefix, b64 = "VDSR", text:sub(6)
    elseif text:sub(1, 4) == "VDS:" then
        prefix, b64 = "VDS", text:sub(5)
    end

    if prefix then
        -- Base64Decode is pure Lua; bad input produces garbage, not error.
        local payload = VDS.StaticData.Base64Decode(b64)
        if not payload or payload == "" then
            return nil, "failed to decode " .. prefix .. " string"
        end
        local pipe = payload:find("|", 1, true)
        if not pipe then return nil, "invalid format (no | separator)" end
        local name   = payload:sub(1, pipe - 1)
        local idsStr = payload:sub(pipe + 1)
        if name == "" or idsStr == "" then return nil, "empty name or dye list" end
        local ids = {}
        for idStr in idsStr:gmatch("[^,]+") do
            local n = tonumber(idStr)
            if not n then return nil, "invalid dye ID: " .. idStr end
            ids[#ids + 1] = n
        end
        if #ids == 0 then return nil, "no dyes parsed" end
        return name, ids
    end

    local ids = {} -- legacy bare CSV; auto-name with timestamp
    for n in text:gmatch("%d+") do ids[#ids + 1] = tonumber(n) end
    if #ids == 0 then return nil, "no dye IDs found" end
    return "Imported " .. date("%H:%M:%S"), ids
end

_G.StaticPopupDialogs["VDS_IMPORT_CUSTOM_THEME"] = {
    text = "Paste palette string:",
    button1 = "Import",
    button2 = "Cancel",
    hasEditBox = true,
    editBoxWidth = 260,
    OnShow = function(self) self.EditBox:SetFocus() end,
    OnAccept = function(self)
        local name, idsOrErr = parseImportPayload(self.EditBox:GetText())
        if not name then
            print("|cFFFF6666VDS:|r import failed -- " .. tostring(idsOrErr))
            return
        end
        VDS.Store:Dispatch({
            type    = A.CUSTOM_THEME_CREATE,
            payload = { name = name, dyes = idsOrErr },
        })
        print("|cFF14b8a6VDS:|r imported palette \"" .. name .. "\" ("
              .. #idsOrErr .. " dyes)")
    end,
    EditBoxOnEscapePressed = function(self) self:GetParent():Hide() end,
    timeout = 0,
    whileDead = true,
    hideOnEscape = true,
    preferredIndex = 3,
}
