-- SetupWizard.lua — RNTools first-time setup wizard (pure AceGUI)
local addonName, addonTable = ...
local AceGUI = LibStub("AceGUI-3.0")

local CURRENT_PAGE = 0
local MAX_PAGE = 8

local wizFrame = nil       -- AceGUI Frame
local contentGroup = nil   -- AceGUI SimpleGroup inside the frame
local statusBar = nil      -- raw StatusBar frame
local statusText = nil     -- FontString on the status bar
local prevBtn = nil        -- AceGUI Button
local nextBtn = nil        -- AceGUI Button

-- Wizard state
local WIZ = {
    role = nil,
    modules = {},
    cdDuration = 20,
    spamIntervals = { general = 10, trade = 23, world = 61, yell = 41 },
    aiKeywords = "inv, invite",
    barScale = 1.0,
}

local MODULE_DEFS = {
    { key = "bis",  label = "BiS Tracker",   pillKey = "BT",   leader = true,  raider = true  },
    { key = "spam", label = "Spammer",       pillKey = "SPAM", leader = true,  raider = true  },
    { key = "ar",   label = "Auto Reply",    pillKey = "AR",   leader = true,  raider = false },
    { key = "ml",   label = "Master Looter", pillKey = "ML",   leader = true,  raider = false },
    { key = "ai",   label = "Auto Invite",   pillKey = "AI",   leader = true,  raider = false },
    { key = "ms",   label = "MS + Buffs",    pillKey = "MS",   leader = true,  raider = true  },
    { key = "rb",   label = "Raid Browser",  pillKey = "RB",   leader = false, raider = true  },
}

-------------------------------------------------------------------------------
-- Helpers
-------------------------------------------------------------------------------

local function P()
    return RNToolsAddon and RNToolsAddon.db and RNToolsAddon.db.profile
end

local function ShouldShowPage(page)
    if page == 4 then return WIZ.modules.ml end
    if page == 5 then return WIZ.modules.spam end
    if page == 6 then return WIZ.modules.ai end
    return true
end

local function NextVisiblePage(from, dir)
    local p = from + dir
    while p >= 1 and p <= MAX_PAGE do
        if ShouldShowPage(p) then return p end
        p = p + dir
    end
    return from
end

local function UpdateProgress()
    if not statusBar then return end
    statusBar:SetValue(CURRENT_PAGE)
    if statusText then statusText:SetText(CURRENT_PAGE .. " / " .. MAX_PAGE) end
    local pct = CURRENT_PAGE / MAX_PAGE
    local r = pct < 0.5 and 1 or (1 - (pct - 0.5) * 2)
    local g = pct < 0.5 and pct * 2 or 1
    statusBar:SetStatusBarColor(r, g, 0.1)
end

-------------------------------------------------------------------------------
-- Apply settings
-------------------------------------------------------------------------------

local function ApplyAllSettings()
    local p = P()

    -- Module enable/disable + pill visibility
    for _, def in ipairs(MODULE_DEFS) do
        local on = WIZ.modules[def.key] and true or false
        if p then
            p["module_" .. def.key] = on
            p["bar_pill_" .. def.pillKey] = on
        end
    end

    -- Master Looter
    if type(RTMasterLooterSave) ~= "table" then RTMasterLooterSave = {} end
    if not WIZ.modules.ml then RTMasterLooterSave.enabled = false end

    -- Roll Manager countdown — write to saved var AND runtime global
    if type(RTRollManagerSave) ~= "table" then RTRollManagerSave = {} end
    RTRollManagerSave.cdDuration = WIZ.cdDuration
    RM_cdDuration = WIZ.cdDuration
    if RNTools_SyncCDLabel then RNTools_SyncCDLabel() end

    -- Spammer intervals — write to both AceDB profile AND RTSpammerSave
    if p then
        p.spam_interval_general = WIZ.spamIntervals.general
        p.spam_interval_trade   = WIZ.spamIntervals.trade
        p.spam_interval_world   = WIZ.spamIntervals.world
        p.spam_interval_yell    = WIZ.spamIntervals.yell
    end
    if type(RTSpammerSave) ~= "table" then RTSpammerSave = {} end
    if type(RTSpammerSave.presets) ~= "table" then RTSpammerSave.presets = {} end
    -- Write to Default preset (the spammer migrates .current into presets on load)
    if type(RTSpammerSave.presets["Default"]) ~= "table" then RTSpammerSave.presets["Default"] = {} end
    if type(RTSpammerSave.presets["Default"].intervals) ~= "table" then RTSpammerSave.presets["Default"].intervals = {} end
    RTSpammerSave.presets["Default"].intervals["General"] = tostring(WIZ.spamIntervals.general)
    RTSpammerSave.presets["Default"].intervals["Trade"]   = tostring(WIZ.spamIntervals.trade)
    RTSpammerSave.presets["Default"].intervals["World"]   = tostring(WIZ.spamIntervals.world)
    RTSpammerSave.presets["Default"].intervals["YELL"]    = tostring(WIZ.spamIntervals.yell)
    -- Also write to .current for backward compat (pre-migration)
    if type(RTSpammerSave.current) ~= "table" then RTSpammerSave.current = {} end
    if type(RTSpammerSave.current.intervals) ~= "table" then RTSpammerSave.current.intervals = {} end
    RTSpammerSave.current.intervals["General"] = tostring(WIZ.spamIntervals.general)
    RTSpammerSave.current.intervals["Trade"]   = tostring(WIZ.spamIntervals.trade)
    RTSpammerSave.current.intervals["World"]   = tostring(WIZ.spamIntervals.world)
    RTSpammerSave.current.intervals["YELL"]    = tostring(WIZ.spamIntervals.yell)
    if not WIZ.modules.spam then
        RTSpammerSave.enabled = false
    end

    -- Auto Response
    if type(RTAutoResponseSave) ~= "table" then RTAutoResponseSave = {} end
    if not WIZ.modules.ar then RTAutoResponseSave.enabled = false end

    -- Auto Invite
    if type(RNToolsAutoInviteSave) ~= "table" then RNToolsAutoInviteSave = {} end
    if WIZ.modules.ai then
        -- Convert comma-separated string to keyword table format
        local kwTable = {}
        for kw in WIZ.aiKeywords:gmatch("[^,]+") do
            kw = kw:match("^%s*(.-)%s*$")  -- trim
            if kw ~= "" then
                kwTable[#kwTable + 1] = { keyword = kw, contains = false }
            end
        end
        if #kwTable > 0 then
            RNToolsAutoInviteSave.keywords = kwTable
        end
        RNToolsAutoInviteSave.isEnabled = true
    else
        RNToolsAutoInviteSave.isEnabled = false
    end

    -- BiS Tracker
    if type(BiSRaidConfig) ~= "table" then BiSRaidConfig = {} end
    BiSRaidConfig.enabled = WIZ.modules.bis and true or false

    -- Raid Browser
    if p then p.rb_enabled = WIZ.modules.rb and true or false end

    -- Scale
    if p then p.addonScale = WIZ.barScale end

    -- Role
    if p then p.rnt_role = WIZ.role end

    -- Mark complete
    if type(RNToolsSetupSave) ~= "table" then RNToolsSetupSave = {} end
    RNToolsSetupSave.install_complete = GetAddOnMetadata(addonName, "Version") or "1"
    RNToolsSetupSave.role = WIZ.role
end

-------------------------------------------------------------------------------
-- Page builders
-------------------------------------------------------------------------------

local function SetPage(pageNum)  -- forward declaration filled below
end

-- Page 1: Welcome
local function BuildPage1()
    local ver = GetAddOnMetadata(addonName, "Version") or "?"

    local hdr = AceGUI:Create("Heading")
    hdr:SetText("Welcome to RNTools v" .. ver)
    hdr:SetFullWidth(true)
    contentGroup:AddChild(hdr)

    local desc = AceGUI:Create("Label")
    desc:SetText(
        "\nThis wizard will help you configure RNTools for your character " ..
        "in just a few steps.\n\n" ..
        "You can re-run this anytime with |cffFFD100/rnt setup|r\n")
    desc:SetFullWidth(true)
    desc:SetFontObject(GameFontHighlight)
    contentGroup:AddChild(desc)

    -- Profile import
    local profiles = {}
    if RNTools_AceDB and type(RNTools_AceDB) == "table" and RNTools_AceDB.profiles then
        -- Get the current active profile key (not just "Name - Realm")
        local currentProfile = RNToolsAddon and RNToolsAddon.db and RNToolsAddon.db:GetCurrentProfile()
        for k, _ in pairs(RNTools_AceDB.profiles) do
            if k ~= currentProfile and k ~= "Default" then
                profiles[#profiles + 1] = k
            end
        end
    end

    if #profiles > 0 then
        local importLbl = AceGUI:Create("Label")
        importLbl:SetText("\n|cff20ff60Found " .. #profiles .. " profile(s) available to copy:|r\n")
        importLbl:SetFullWidth(true)
        contentGroup:AddChild(importLbl)

        local importRow = AceGUI:Create("SimpleGroup")
        importRow:SetLayout("Flow")
        importRow:SetFullWidth(true)
        contentGroup:AddChild(importRow)

        for i = 1, math.min(3, #profiles) do
            local pKey = profiles[i]
            local btn = AceGUI:Create("Button")
            btn:SetText("Copy from: " .. pKey)
            btn:SetRelativeWidth(0.48)
            btn:SetCallback("OnClick", function()
                StaticPopupDialogs["RNTOOLS_COPY_PROFILE"] = {
                    text = "Copy all settings from |cffFFD100" .. pKey .. "|r?\n\nThis will overwrite your current settings and reload the UI.",
                    button1 = "Yes, Copy",
                    button2 = "Cancel",
                    OnAccept = function()
                        if RNToolsAddon and RNToolsAddon.db then
                            RNToolsAddon.db:CopyProfile(pKey)
                            if type(RNToolsSetupSave) ~= "table" then RNToolsSetupSave = {} end
                            RNToolsSetupSave.install_complete = GetAddOnMetadata(addonName, "Version") or "1"
                            ReloadUI()
                        end
                    end,
                    timeout = 0,
                    whileDead = true,
                    hideOnEscape = true,
                    preferredIndex = 3,
                }
                StaticPopup_Show("RNTOOLS_COPY_PROFILE")
            end)
            importRow:AddChild(btn)
        end
    end

    -- Bottom-center buttons
    local spacer = AceGUI:Create("Label")
    spacer:SetText("\n\n")
    spacer:SetFullWidth(true)
    contentGroup:AddChild(spacer)

    local btnRow = AceGUI:Create("SimpleGroup")
    btnRow:SetLayout("Flow")
    btnRow:SetFullWidth(true)
    contentGroup:AddChild(btnRow)

    local pad = AceGUI:Create("Label")
    pad:SetText("")
    pad:SetRelativeWidth(0.35)
    btnRow:AddChild(pad)

    local skipBtn = AceGUI:Create("Button")
    skipBtn:SetText("|cffff4444Skip Setup|r")
    skipBtn:SetRelativeWidth(0.3)
    skipBtn:SetCallback("OnClick", function()
        if type(RNToolsSetupSave) ~= "table" then RNToolsSetupSave = {} end
        RNToolsSetupSave.install_complete = GetAddOnMetadata(addonName, "Version") or "1"
        wizFrame:Hide()
    end)
    btnRow:AddChild(skipBtn)
end

-- Page 2: Role
local function BuildPage2()
    local hdr = AceGUI:Create("Heading")
    hdr:SetText("Choose Your Role")
    hdr:SetFullWidth(true)
    contentGroup:AddChild(hdr)

    local desc = AceGUI:Create("Label")
    desc:SetText(
        "\nYour role determines which modules are recommended.\n" ..
        "You can customize individual modules on the next page.\n")
    desc:SetFullWidth(true)
    desc:SetFontObject(GameFontHighlight)
    contentGroup:AddChild(desc)

    local desc2 = AceGUI:Create("Label")
    desc2:SetText(
        "|cffFFD100Leader / Officer|r — ML, Rolls, Spammer, AR, AI, BiS, MS+Buffs\n" ..
        "|cff44aaFFRaider|r — Spammer, Roll tracking, BiS Tracker, MS+Buffs, Raid Browser\n")
    desc2:SetFullWidth(true)
    contentGroup:AddChild(desc2)

    local row = AceGUI:Create("SimpleGroup")
    row:SetLayout("Flow")
    row:SetFullWidth(true)
    contentGroup:AddChild(row)

    local leaderBtn = AceGUI:Create("Button")
    leaderBtn:SetText("|cffFFD100Raid Leader / Officer|r")
    leaderBtn:SetRelativeWidth(0.48)
    leaderBtn:SetCallback("OnClick", function()
        WIZ.role = "leader"
        for _, def in ipairs(MODULE_DEFS) do WIZ.modules[def.key] = def.leader end
        SetPage(NextVisiblePage(CURRENT_PAGE, 1))
    end)
    row:AddChild(leaderBtn)

    local raiderBtn = AceGUI:Create("Button")
    raiderBtn:SetText("|cff44aaFFRaider|r")
    raiderBtn:SetRelativeWidth(0.48)
    raiderBtn:SetCallback("OnClick", function()
        WIZ.role = "raider"
        for _, def in ipairs(MODULE_DEFS) do WIZ.modules[def.key] = def.raider end
        SetPage(NextVisiblePage(CURRENT_PAGE, 1))
    end)
    row:AddChild(raiderBtn)
end

-- Page 3: Module picker
local function BuildPage3()
    local hdr = AceGUI:Create("Heading")
    hdr:SetText("Choose Your Modules")
    hdr:SetFullWidth(true)
    contentGroup:AddChild(hdr)

    local desc = AceGUI:Create("Label")
    desc:SetText("\nUncheck modules you don't need. Disabled modules won't run, " ..
        "won't appear in the status bar or main window tabs.\n")
    desc:SetFullWidth(true)
    desc:SetFontObject(GameFontHighlight)
    contentGroup:AddChild(desc)

    local row1 = AceGUI:Create("SimpleGroup")
    row1:SetLayout("Flow")
    row1:SetFullWidth(true)
    contentGroup:AddChild(row1)

    local row2 = AceGUI:Create("SimpleGroup")
    row2:SetLayout("Flow")
    row2:SetFullWidth(true)
    contentGroup:AddChild(row2)

    for i, def in ipairs(MODULE_DEFS) do
        local parent = (i <= 4) and row1 or row2
        local cb = AceGUI:Create("CheckBox")
        cb:SetLabel(def.label)
        cb:SetValue(WIZ.modules[def.key] and true or false)
        cb:SetWidth(120)
        cb:SetCallback("OnValueChanged", function(_, _, val)
            WIZ.modules[def.key] = val
        end)
        parent:AddChild(cb)
    end
end

-- Page 4: ML + Rolls
local function BuildPage4()
    local hdr = AceGUI:Create("Heading")
    hdr:SetText("Master Looter + Roll Manager")
    hdr:SetFullWidth(true)
    contentGroup:AddChild(hdr)

    local desc = AceGUI:Create("Label")
    desc:SetText(
        "\nSet your roll countdown duration. Collectors (main loot, shard, BoE) " ..
        "can be configured later in the Master Looter tab.\n\n" ..
        "|cff88888820s is recommended for most raids. Set to Off to close rolls manually.|r\n")
    desc:SetFullWidth(true)
    desc:SetFontObject(GameFontHighlight)
    contentGroup:AddChild(desc)

    local row = AceGUI:Create("SimpleGroup")
    row:SetLayout("Flow")
    row:SetFullWidth(true)
    contentGroup:AddChild(row)

    local cdValues = { 0, 10, 15, 20, 25, 30 }
    local cdBtns = {}
    for i, secs in ipairs(cdValues) do
        local label = secs == 0 and "Off" or (secs .. "s")
        local btn = AceGUI:Create("Button")
        btn:SetText(WIZ.cdDuration == secs and ("|cff20ff60" .. label .. "|r") or label)
        btn:SetRelativeWidth(0.16)
        cdBtns[i] = btn
        btn:SetCallback("OnClick", function()
            WIZ.cdDuration = secs
            for j, v in ipairs(cdValues) do
                local l = v == 0 and "Off" or (v .. "s")
                cdBtns[j]:SetText(v == secs and ("|cff20ff60" .. l .. "|r") or l)
            end
        end)
        row:AddChild(btn)
    end
end

-- Page 5: Spammer intervals
local function BuildPage5()
    local hdr = AceGUI:Create("Heading")
    hdr:SetText("Spammer Intervals")
    hdr:SetFullWidth(true)
    contentGroup:AddChild(hdr)

    local desc = AceGUI:Create("Label")
    desc:SetText(
        "\nSet the interval (in seconds) between messages for each channel.\n" ..
        "You can write your actual messages later in the Spammer tab.\n")
    desc:SetFullWidth(true)
    desc:SetFontObject(GameFontHighlight)
    contentGroup:AddChild(desc)

    local channels = {
        { key = "general", label = "General (sec)" },
        { key = "trade",   label = "Trade (sec)" },
        { key = "world",   label = "World/LFG (sec)" },
        { key = "yell",    label = "Yell (sec)" },
    }

    for _, ch in ipairs(channels) do
        local row = AceGUI:Create("SimpleGroup")
        row:SetLayout("Flow")
        row:SetFullWidth(true)
        contentGroup:AddChild(row)

        local lbl = AceGUI:Create("Label")
        lbl:SetText(ch.label)
        lbl:SetRelativeWidth(0.35)
        row:AddChild(lbl)

        local eb = AceGUI:Create("EditBox")
        eb:SetText(tostring(WIZ.spamIntervals[ch.key] or 30))
        eb:SetRelativeWidth(0.25)
        eb:DisableButton(true)
        eb:SetCallback("OnTextChanged", function(_, _, val)
            local num = tonumber(val)
            if num and num > 0 then WIZ.spamIntervals[ch.key] = num end
        end)
        row:AddChild(eb)
    end
end

-- Page 6: Auto Invite
local function BuildPage6()
    local hdr = AceGUI:Create("Heading")
    hdr:SetText("Auto Invite")
    hdr:SetFullWidth(true)
    contentGroup:AddChild(hdr)

    local desc = AceGUI:Create("Label")
    desc:SetText(
        "\nSet keywords that trigger an automatic raid invite when whispered.\n" ..
        "Separate multiple keywords with commas.\n")
    desc:SetFullWidth(true)
    desc:SetFontObject(GameFontHighlight)
    contentGroup:AddChild(desc)

    local eb = AceGUI:Create("EditBox")
    eb:SetLabel("Invite Keywords")
    eb:SetText(WIZ.aiKeywords)
    eb:SetFullWidth(true)
    eb:DisableButton(true)
    eb:SetCallback("OnTextChanged", function(_, _, val)
        WIZ.aiKeywords = val
    end)
    contentGroup:AddChild(eb)
end

-- Page 7: UI Scale
local function BuildPage7()
    local hdr = AceGUI:Create("Heading")
    hdr:SetText("UI Scale")
    hdr:SetFullWidth(true)
    contentGroup:AddChild(hdr)

    local desc = AceGUI:Create("Label")
    desc:SetText(
        "\nAdjust the RNTools UI scale. You can drag the status bar to reposition it.\n\n" ..
        "|cff888888Tip: Right-click the status bar to open RNTools. Click pills to toggle modules.|r\n")
    desc:SetFullWidth(true)
    desc:SetFontObject(GameFontHighlight)
    contentGroup:AddChild(desc)

    -- Read current scale from profile if available
    local pp = P()
    local rawScale = (pp and tonumber(pp.addonScale)) or 1.0
    if rawScale <= 0 then rawScale = 1.0 end
    WIZ.barScale = rawScale
    local initPct = math.floor(rawScale * 100 + 0.5)

    local slider = AceGUI:Create("Slider")
    slider:SetLabel("UI Scale: " .. initPct .. "%")
    slider:SetSliderValues(50, 200, 5)
    slider:SetValue(initPct)
    slider:SetFullWidth(true)
    slider:SetCallback("OnValueChanged", function(_, _, val)
        local snapped = math.floor(val / 5 + 0.5) * 5
        snapped = math.max(50, math.min(200, snapped))
        slider:SetLabel("UI Scale: " .. snapped .. "%")
    end)
    -- Apply on mouse release (same pattern as Config.lua)
    slider.slider:HookScript("OnMouseUp", function()
        local val = slider:GetValue()
        local snapped = math.floor(val / 5 + 0.5) * 5
        snapped = math.max(50, math.min(200, snapped))
        WIZ.barScale = snapped / 100
        -- Live preview: scale the wizard frame itself + all addon windows
        if wizFrame and wizFrame.frame then wizFrame.frame:SetScale(WIZ.barScale) end
        if RNTools_ApplyAddonScale then RNTools_ApplyAddonScale(WIZ.barScale) end
    end)
    contentGroup:AddChild(slider)
end

-- Page 8: Complete
local function BuildPage8()
    local hdr = AceGUI:Create("Heading")
    hdr:SetText("|cff20ff60Setup Complete!|r")
    hdr:SetFullWidth(true)
    contentGroup:AddChild(hdr)

    -- Summary
    local roleText = WIZ.role == "leader" and "|cffFFD100Leader / Officer|r" or "|cff44aaFFRaider|r"
    local enabledMods = {}
    for _, def in ipairs(MODULE_DEFS) do
        if WIZ.modules[def.key] then enabledMods[#enabledMods + 1] = def.label end
    end
    local modText = #enabledMods > 0 and table.concat(enabledMods, ", ") or "None"

    local summary = AceGUI:Create("Label")
    summary:SetText(
        "\n|cffFFD100Role:|r " .. roleText ..
        "\n|cffFFD100Modules:|r " .. modText .. "\n")
    summary:SetFullWidth(true)
    contentGroup:AddChild(summary)

    local tips = AceGUI:Create("Label")
    tips:SetText(
        "|cffFFD100Quick Tips:|r\n" ..
        "  - Right-click status bar to open RNTools\n" ..
        "  - |cffFFD100/rnt|r to open main window\n" ..
        "  - |cffFFD100/rnt setup|r to re-run this wizard\n" ..
        "  - Click status bar pills to toggle modules\n")
    tips:SetFullWidth(true)
    contentGroup:AddChild(tips)

    local warn = AceGUI:Create("Label")
    warn:SetText("|cffff4444Clicking Finish will reload your UI to apply all settings.|r\n")
    warn:SetFullWidth(true)
    contentGroup:AddChild(warn)

    local row = AceGUI:Create("SimpleGroup")
    row:SetLayout("Flow")
    row:SetFullWidth(true)
    contentGroup:AddChild(row)

    local spacer1 = AceGUI:Create("Label")
    spacer1:SetText("")
    spacer1:SetRelativeWidth(0.15)
    row:AddChild(spacer1)

    local discordBtn = AceGUI:Create("Button")
    discordBtn:SetText("Discord")
    discordBtn:SetRelativeWidth(0.3)
    discordBtn:SetCallback("OnClick", function()
        StaticPopupDialogs["RNTOOLS_DISCORD_LINK"] = {
            text = "Join RNTools Discord:\n\nPress Ctrl+C to copy",
            button1 = "OK",
            timeout = 0, whileDead = true, hideOnEscape = true,
            hasEditBox = true,
            OnShow = function(self)
                self.editBox:SetText("https://discord.com/invite/uZTTqejway")
                self.editBox:HighlightText()
            end,
        }
        StaticPopup_Show("RNTOOLS_DISCORD_LINK")
    end)
    row:AddChild(discordBtn)

    local spacer2 = AceGUI:Create("Label")
    spacer2:SetText("")
    spacer2:SetRelativeWidth(0.05)
    row:AddChild(spacer2)

    local finishBtn = AceGUI:Create("Button")
    finishBtn:SetText("|cff20ff60Finish|r")
    finishBtn:SetRelativeWidth(0.3)
    finishBtn:SetCallback("OnClick", function()
        ApplyAllSettings()
        ReloadUI()
    end)
    row:AddChild(finishBtn)
end

local PAGE_BUILDERS = {
    BuildPage1, BuildPage2, BuildPage3, BuildPage4,
    BuildPage5, BuildPage6, BuildPage7, BuildPage8,
}

-------------------------------------------------------------------------------
-- SetPage
-------------------------------------------------------------------------------

SetPage = function(pageNum)
    CURRENT_PAGE = pageNum

    -- Clear page content
    if contentGroup then contentGroup:ReleaseChildren() end

    -- Update progress
    UpdateProgress()

    -- Nav button state — use Show/Hide for clean transitions
    if prevBtn then
        if pageNum <= 1 then prevBtn:Hide() else prevBtn:Show(); prevBtn:Enable() end
    end
    if nextBtn then
        -- Hide on role page (own buttons navigate) and complete page (Finish button)
        if pageNum == 2 or pageNum >= MAX_PAGE then
            nextBtn:Hide()
        else
            nextBtn:Show()
            nextBtn:Enable()
        end
    end

    -- Build page
    if PAGE_BUILDERS[pageNum] then
        PAGE_BUILDERS[pageNum]()
    end
end

local function NextPage()
    local next = NextVisiblePage(CURRENT_PAGE, 1)
    if next ~= CURRENT_PAGE then SetPage(next) end
end

local function PreviousPage()
    local prev = NextVisiblePage(CURRENT_PAGE, -1)
    if prev ~= CURRENT_PAGE then SetPage(prev) end
end

-------------------------------------------------------------------------------
-- Frame creation
-------------------------------------------------------------------------------

local function CreateWizardFrame()
    if wizFrame then
        wizFrame:Show()
        return
    end

    local frame = AceGUI:Create("Frame")
    frame:SetTitle("|cffFFD100RNTools|r |cff888888Setup Wizard|r")
    frame:SetWidth(550)
    frame:SetHeight(420)
    frame:SetLayout("Fill")
    frame:EnableResize(false)
    frame:SetCallback("OnClose", function(widget) widget:Hide() end)
    frame:SetStatusText("")
    if frame.statustext then frame.statustext:Hide() end

    -- Hide ALL AceGUI Frame bottom elements: Close button + status bar footer
    -- The AceGUI Frame stores these internally — find them by scanning children
    -- anchored to BOTTOM regions, then also try the widget's known refs.
    local kids = { frame.frame:GetChildren() }
    for _, child in ipairs(kids) do
        if child:GetObjectType() == "Button" then
            local point = child:GetPoint(1)
            if point and (point == "BOTTOMRIGHT" or point == "BOTTOMLEFT") then
                child:Hide()
                child:SetHeight(0)
                child:ClearAllPoints()
                child:SetPoint("TOPLEFT", frame.frame, "TOPLEFT", 0, 0)
            end
        end
    end

    -- Add a proper X close button at top-right
    local xBtn = CreateFrame("Button", nil, frame.frame, "UIPanelCloseButton")
    xBtn:SetPoint("TOPRIGHT", frame.frame, "TOPRIGHT", -2, -2)
    xBtn:SetScript("OnClick", function() frame:Hide() end)
    -- ElvUI skin if available
    if TryGetElvUISkinModule then
        local _, s = TryGetElvUISkinModule()
        if s and s.HandleCloseButton then
            pcall(s.HandleCloseButton, s, xBtn, frame.frame)
        end
    end

    frame.frame:SetClampedToScreen(true)
    frame.frame:ClearAllPoints()
    frame.frame:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
    frame.frame:SetFrameStrata("TOOLTIP")

    -- Darken the backdrop slightly (10-15% darker than default AceGUI Frame)
    frame.frame:SetBackdropColor(0.05, 0.05, 0.05, 0.95)

    -- Splash background texture (above backdrop, below content)
    local splashTex = frame.frame:CreateTexture(nil, "BACKGROUND", nil, 2)
    splashTex:SetTexture("Interface\\AddOns\\RNTools\\Textures\\Splash")
    splashTex:SetAllPoints(frame.frame)
    splashTex:SetAlpha(0.12)

    wizFrame = frame
    _G["RNToolsSetupFrame"] = frame.frame
    tinsert(UISpecialFrames, "RNToolsSetupFrame")

    -- Content scroll frame fills the main area
    local scroll = AceGUI:Create("ScrollFrame")
    scroll:SetLayout("List")
    frame:AddChild(scroll)
    contentGroup = scroll

    -- Bottom navigation area: raw frames on the AceGUI frame
    local rawFrame = frame.frame

    -- Previous button (raw, anchored bottom-left)
    local prev = CreateFrame("Button", "RNTSetupPrevBtn", rawFrame, "UIPanelButtonTemplate")
    prev:SetSize(110, 25)
    prev:SetPoint("BOTTOMLEFT", rawFrame, "BOTTOMLEFT", 14, 14)
    prev:SetText("Previous")
    prev:SetFrameLevel(rawFrame:GetFrameLevel() + 5)
    prev:SetScript("OnClick", function() PreviousPage() end)
    prev:Hide()

    -- Next button (raw, anchored bottom-right)
    local next = CreateFrame("Button", "RNTSetupNextBtn", rawFrame, "UIPanelButtonTemplate")
    next:SetSize(110, 25)
    next:SetPoint("BOTTOMRIGHT", rawFrame, "BOTTOMRIGHT", -14, 14)
    next:SetText("Continue")
    next:SetFrameLevel(rawFrame:GetFrameLevel() + 5)
    next:SetScript("OnClick", function() NextPage() end)
    next:Hide()

    -- Status bar between prev and next
    local bar = CreateFrame("StatusBar", "RNTSetupStatusBar", rawFrame)
    bar:SetFrameLevel(rawFrame:GetFrameLevel() + 2)
    bar:SetStatusBarTexture("Interface\\TargetingFrame\\UI-StatusBar")
    bar:SetMinMaxValues(0, MAX_PAGE)
    bar:SetPoint("TOPLEFT", prev, "TOPRIGHT", 6, -2)
    bar:SetPoint("BOTTOMRIGHT", next, "BOTTOMLEFT", -6, 2)
    bar:SetStatusBarColor(1, 0.2, 0.1)

    local barBg = bar:CreateTexture(nil, "BACKGROUND")
    barBg:SetAllPoints()
    barBg:SetTexture("Interface\\TargetingFrame\\UI-StatusBar")
    barBg:SetVertexColor(0.15, 0.15, 0.15, 0.8)

    local barText = bar:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    barText:SetPoint("CENTER")
    barText:SetText("0 / " .. MAX_PAGE)

    statusBar = bar
    statusText = barText

    -- Wrap raw buttons for SetPage state management
    prevBtn = {
        Show = function() prev:Show() end,
        Hide = function() prev:Hide() end,
        Enable = function() prev:Enable() end,
        Disable = function() prev:Disable() end,
    }
    nextBtn = {
        Show = function() next:Show() end,
        Hide = function() next:Hide() end,
        Enable = function() next:Enable() end,
        Disable = function() next:Disable() end,
    }

    -- ElvUI skin raw buttons if available
    if TryGetElvUISkinModule then
        local _, s = TryGetElvUISkinModule()
        if s and s.HandleButton then
            pcall(s.HandleButton, s, prev, true)
            pcall(s.HandleButton, s, next, true)
        end
        if s and s.HandleStatusBar then
            pcall(s.HandleStatusBar, s, bar)
        end
    end

    -- Shrink the scroll frame to leave room for nav bar at bottom
    scroll.frame:ClearAllPoints()
    scroll.frame:SetPoint("TOPLEFT", rawFrame, "TOPLEFT", 17, -50)
    scroll.frame:SetPoint("BOTTOMRIGHT", rawFrame, "BOTTOMRIGHT", -17, 46)

    frame:Show()
end

-------------------------------------------------------------------------------
-- Public API
-------------------------------------------------------------------------------

function RNTools_OpenSetupWizard()
    CURRENT_PAGE = 0
    WIZ.role = nil
    WIZ.modules = {}
    WIZ.cdDuration = 20
    WIZ.spamIntervals = { general = 31, trade = 23, world = 71, yell = 41 }
    WIZ.aiKeywords = "inv, invite"
    WIZ.barScale = 1.0

    -- Seed spam intervals from current profile if available
    local pp = P()
    if pp then
        WIZ.spamIntervals.general = pp.spam_interval_general or 10
        WIZ.spamIntervals.trade   = pp.spam_interval_trade   or 23
        WIZ.spamIntervals.world   = pp.spam_interval_world   or 61
        WIZ.spamIntervals.yell    = pp.spam_interval_yell    or 41
        WIZ.barScale = pp.addonScale or 1.0
    end

    CreateWizardFrame()
    SetPage(1)
end

function RNTools_SetupWizardPage(page)
    if wizFrame and wizFrame:IsShown() then SetPage(page) end
end

function RNTools_ShouldShowSetup()
    if type(RNToolsSetupSave) ~= "table" then return true end
    return not RNToolsSetupSave.install_complete
end

-- Auto-launch on first login
local setupLauncher = CreateFrame("Frame")
setupLauncher:RegisterEvent("PLAYER_ENTERING_WORLD")
setupLauncher:SetScript("OnEvent", function(self)
    self:UnregisterEvent("PLAYER_ENTERING_WORLD")
    local timer = CreateFrame("Frame")
    local elapsed = 0
    timer:SetScript("OnUpdate", function(self, dt)
        elapsed = elapsed + dt
        if elapsed >= 1.0 then
            self:SetScript("OnUpdate", nil)
            if RNTools_ShouldShowSetup() then
                RNTools_OpenSetupWizard()
            end
        end
    end)
end)
