local addonName, NS = ...
local GR = _G["GRS_MainFrame"]

-- Helpers from Shared
local CreateBg = NS.CreateBg
local SkinButton = NS.SkinButton
local CreateBorder = NS.CreateBorder

-- Colors
local C_GOLD = "|cffffd100"
local C_BLUE = "|cff00ccff"
local C_NORM = "|cffffffff"

-- =========================================================================
-- DATABASE INITIALIZATION
-- =========================================================================
local function InitMapDatabase()
    -- Safety: Do not overwrite if Macro Panel initialized it first
    if not DB_Rmap_Tools then
        DB_Rmap_Tools = {
            sessions = {},
            lastRaid = nil,
            lastBoss = nil,
            canvasData = {},
            saves = {},
            macroProfiles = {}, 
            settings = {
                brushSize = 2,
                opacity = 1.0,
                isMenuHidden = false,
                disableHelpFlash = false,
                strategists = {},
                isMacroPanelOpen = false
            }
        }
    end
    if not DB_Rmap_Tools.saves then DB_Rmap_Tools.saves = {} end
    if not DB_Rmap_Tools.settings.strategists then DB_Rmap_Tools.settings.strategists = {} end
    if not DB_Rmap_Tools.macroProfiles then DB_Rmap_Tools.macroProfiles = {} end
end

-- =========================================================================
-- TOAST NOTIFICATION SYSTEM
-- =========================================================================
function GR:ShowMapToast(msg, isError)
    if not self.MapToast then
        local f = CreateFrame("Frame", "GRS_Map_Toast", UIParent, "BackdropTemplate")
        f:SetSize(300, 40); f:SetPoint("TOP", 0, -150); f:SetFrameStrata("FULLSCREEN_DIALOG"); f:SetAlpha(0)
        f:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8x8", edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", tile = false, tileSize = 16, edgeSize = 16, insets = { left = 4, right = 4, top = 4, bottom = 4 } })
        f:SetBackdropColor(0.1, 0.1, 0.1, 0.9); f:SetBackdropBorderColor(0, 0, 0, 1)
        f.icon = f:CreateTexture(nil, "ARTWORK"); f.icon:SetSize(20, 20); f.icon:SetPoint("LEFT", 15, 0)
        f.fs = f:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge"); f.fs:SetPoint("CENTER", 10, 0); f.fs:SetJustifyH("CENTER")
        f.ag = f:CreateAnimationGroup()
        f.ag:CreateAnimation("Alpha"):SetFromAlpha(0); f.ag:CreateAnimation("Alpha"):SetToAlpha(1); f.ag:CreateAnimation("Alpha"):SetDuration(0.2); f.ag:CreateAnimation("Alpha"):SetOrder(1)
        f.ag:CreateAnimation("Alpha"):SetFromAlpha(1); f.ag:CreateAnimation("Alpha"):SetToAlpha(1); f.ag:CreateAnimation("Alpha"):SetDuration(2.0); f.ag:CreateAnimation("Alpha"):SetOrder(2)
        f.ag:CreateAnimation("Alpha"):SetFromAlpha(1); f.ag:CreateAnimation("Alpha"):SetToAlpha(0); f.ag:CreateAnimation("Alpha"):SetDuration(0.5); f.ag:CreateAnimation("Alpha"):SetOrder(3)
        f.ag:SetScript("OnFinished", function() f:Hide() end)
        self.MapToast = f
    end
    local f = self.MapToast; f.fs:SetText(msg)
    if isError then f:SetBackdropBorderColor(1, 0, 0, 1); f.fs:SetTextColor(1, 0.2, 0.2); f.icon:SetTexture("Interface\\DialogFrame\\UI-Dialog-Icon-AlertNew")
    else f:SetBackdropBorderColor(0, 1, 0, 1); f.fs:SetTextColor(0.2, 1, 0.2); f.icon:SetTexture("Interface\\FriendsFrame\\StatusIcon-Online") end
    f:Show(); f.ag:Stop(); f.ag:Play()
end

-- =========================================================================
-- RAID MAP DATA (PUBLIC / SHARED)
-- =========================================================================
-- Exposed globally for Plugins and the Standalone Macro Panel
GR.RAID_MAP_DATA = {
    ["The Dreamrift"] = { { name = "Chimaerus the Undreamt God", file = "Chimaerus.tga" } },
    ["The Voidspire"] = { { name = "Imperator Averzian", file = "Avverzian.tga" }, { name = "Vorasius", file = "Vorasius.tga" }, { name = "Fallen-King Salhadaar", file = "Salhadhaar.tga" }, { name = "Vaelgor & Ezzorak", file = "Vaelgor - Ezzorak.tga" }, { name = "Lightblinded Vanguard", file = "Vanguards.tga" }, { name = "Crown of the Cosmos", file = "CrownofCosmos.tga" } },
    ["March on Quel'Danas"] = { { name = "Belo'ren, Child of Al'ar", file = "Belo'ren.tga" }, { name = "Midnight Falls", file = "MidnightFalls.tga" } },
}
GR.RAID_ORDER = { "The Dreamrift", "The Voidspire", "March on Quel'Danas" }

-- =========================================================================
-- HELP / TUTORIAL SYSTEM
-- =========================================================================
local function OpenMapHelpDialog()
    local f = _G["GRS_Map_HelpDlg"]
    if f then f:Show(); return end
    
    f = CreateFrame("Frame", "GRS_Map_HelpDlg", UIParent, "BackdropTemplate")
    f:SetSize(400, 500); f:SetPoint("CENTER"); f:SetFrameStrata("DIALOG"); f:EnableMouse(true); f:SetMovable(true)
    f:RegisterForDrag("LeftButton"); f:SetScript("OnDragStart", f.StartMoving); f:SetScript("OnDragStop", f.StopMovingOrSizing)
    
    f:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8x8", edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", tile = false, tileSize = 16, edgeSize = 16, insets = { left = 4, right = 4, top = 4, bottom = 4 } })
    f:SetBackdropColor(0, 0, 0, 0.9); f:SetBackdropBorderColor(1, 0.82, 0, 1)
    
    local title = f:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    title:SetPoint("TOP", 0, -15); title:SetText("A.X.I.O.M. Manual")
    
    local close = CreateFrame("Button", nil, f)
    close:SetSize(24, 24); close:SetPoint("TOPRIGHT", -5, -5); SkinButton(close)
    local cfs = close:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    cfs:SetPoint("CENTER"); cfs:SetText("X"); close:SetFontString(cfs)
    close:SetScript("OnClick", function() f:Hide() end)

    local sf = CreateFrame("ScrollFrame", nil, f, "UIPanelScrollFrameTemplate")
    sf:SetPoint("TOPLEFT", 15, -50); sf:SetPoint("BOTTOMRIGHT", -30, 15)
    local content = CreateFrame("Frame", nil, sf); content:SetSize(355, 1000); sf:SetScrollChild(content)
    
    local txt = content:CreateFontString(nil, "OVERLAY", "GameFontHighlight"); txt:SetPoint("TOPLEFT", 0, 0); txt:SetWidth(350); txt:SetJustifyH("LEFT")
    
    local t = ""
    local function AddLine(str) t = t .. str .. "\n" end
    local function AddItem(head, desc) t = t .. "  • " .. C_BLUE .. head .. "|r: " .. C_GOLD .. desc .. "|r\n" end
    
    AddLine(C_GOLD .. "Welcome to the tactical map interface.|r\n")
    AddLine(C_NORM .. "1. Navigation|r")
    AddItem("Select Raid", "Choose the active raid wing from the top-left dropdown.")
    AddItem("Select Boss", "Pick a boss to load its tactical map. Defaults to the first boss.")
    AddLine("")
    AddLine(C_NORM .. "2. Tools & Canvas|r")
    AddItem("Drag & Drop", "Pull icons from the Left Panel onto the Map Overlay.")
    AddItem("Delete", "Drag any icon OFF the map raster to destroy it.")
    AddLine("")
    AddLine(C_NORM .. "3. Manipulation|r")
    AddItem("Move", "Left-Click and Drag any icon on the map.")
    AddItem("Scale", "Right-Click and Drag (Left/Right) to resize.")
    AddItem("Stretch", "Hold SHIFT + Right-Click Drag to stretch shapes non-uniformly.")
    AddItem("Rotate", "Use Mouse Wheel while hovering over an icon.")
    AddLine("")
    AddLine(C_NORM .. "4. Custom Labels|r")
    AddItem("Create", "Drag the 'A' icon onto the map.")
    AddItem("Edit", "Double-Click a label to enter text input mode.")
    AddItem("Format", "Use the popup bar for Bold, Italic, Underline, Color, and Size.")
    AddLine("")
    AddLine(C_NORM .. "5. Save System|r")
    AddItem("Slots", "10 Save Slots available per boss (Below the map).")
    AddItem("Save", "Select a slot number, then click SAVE to store the current layout.")
    AddItem("Load", "Click any named/colored slot to instantly load that layout.")
    AddItem("Reset", "Select a slot and click RESET SAVE to clear it.")
    
    txt:SetText(t); content:SetHeight(txt:GetStringHeight() + 20); f:Show()
end

-- =========================================================================
-- STRATEGISTS POPUP
-- =========================================================================
local function OpenStrategistDialog()
    local f = _G["GRS_Map_StratDlg"]
    if not f then
        f = CreateFrame("Frame", "GRS_Map_StratDlg", UIParent, "BackdropTemplate")
        f:SetSize(300, 380)
        f:SetPoint("CENTER"); f:SetFrameStrata("FULLSCREEN_DIALOG")
        f:EnableMouse(true); f:SetMovable(true)
        f:RegisterForDrag("LeftButton"); f:SetScript("OnDragStart", f.StartMoving); f:SetScript("OnDragStop", f.StopMovingOrSizing)
        
        f:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8x8" })
        f:SetBackdropColor(0, 0, 0, 0.75)
        
        local title = f:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
        title:SetPoint("TOP", 0, -15); title:SetText("Strategists"); title:SetTextColor(1, 1, 1)
        
        local close = CreateFrame("Button", nil, f)
        close:SetSize(20, 20); close:SetPoint("TOPRIGHT", -5, -5); SkinButton(close)
        local cfs = close:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
        cfs:SetPoint("CENTER"); cfs:SetText("X"); close:SetFontString(cfs)
        close:SetScript("OnClick", function() f:Hide() end)
        
        f.leaderLbl = f:CreateFontString(nil, "OVERLAY", "GameFontHighlightMedium")
        f.leaderLbl:SetPoint("TOP", 0, -45); f.leaderLbl:SetTextColor(1, 0.82, 0)
        
        f.dropdowns = {}
        local y = -80
        for i=1, 5 do
            local lbl = f:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
            lbl:SetPoint("TOPLEFT", 20, y); lbl:SetText("Raid Assistance / Strategist " .. i .. ":")
            lbl:SetTextColor(1, 1, 1)
            
            local btn = CreateFrame("Button", nil, f)
            btn:SetSize(260, 24); btn:SetPoint("TOPLEFT", 20, y - 15)
            CreateBg(btn, 0.2, 0.2, 0.2, 1)
            local txt = btn:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
            txt:SetPoint("LEFT", 5, 0); txt:SetText("- None -"); btn.txt = txt
            
            local list = CreateFrame("Frame", nil, btn)
            list:SetSize(260, 150); list:SetPoint("TOPLEFT", btn, "BOTTOMLEFT", 0, -2)
            list:SetFrameStrata("TOOLTIP"); CreateBg(list, 0.1, 0.1, 0.1, 1); list:Hide()
            
            local scroll = CreateFrame("ScrollFrame", nil, list, "UIPanelScrollFrameTemplate")
            scroll:SetPoint("TOPLEFT", 5, -5); scroll:SetPoint("BOTTOMRIGHT", -25, 5)
            local content = CreateFrame("Frame", nil, scroll); content:SetSize(230, 200); scroll:SetScrollChild(content)
            
            btn:SetScript("OnClick", function() list:SetShown(not list:IsShown()) end)
            
            btn.RefreshList = function()
                local candidates = {}; local num = GetNumGroupMembers()
                if num == 0 then table.insert(candidates, {name=UnitName("player"), class=select(2, UnitClass("player"))}) 
                else
                    for j=1, num do
                        local unit = IsInRaid() and ("raid"..j) or ("party"..j)
                        if IsInRaid() or j < num then 
                            if not IsInRaid() and j == num then unit = "player" end 
                            local name = GetUnitName(unit, true)
                            local _, cls = UnitClass(unit)
                            if name then table.insert(candidates, {name=name, class=cls}) end
                        end
                    end
                    if not IsInRaid() then 
                        local pName, _, pCls = UnitName("player"), UnitClass("player")
                        local found = false
                        for _, c in ipairs(candidates) do if c.name == pName then found = true break end end
                        if not found then table.insert(candidates, {name=pName, class=select(2, UnitClass("player"))}) end
                    end
                end
                
                table.sort(candidates, function(a,b) return a.name < b.name end)
                table.insert(candidates, 1, {name="- None -", class=nil})
                
                local kids = {content:GetChildren()}; for _, k in ipairs(kids) do k:Hide() end
                local dy = 0
                for _, cand in ipairs(candidates) do
                    local b = CreateFrame("Button", nil, content)
                    b:SetSize(230, 20); b:SetPoint("TOPLEFT", 0, dy)
                    local t = b:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
                    t:SetPoint("LEFT", 5, 0)
                    if cand.class then
                        local cColor = C_ClassColor.GetClassColor(cand.class)
                        t:SetText(cColor:WrapTextInColorCode(cand.name))
                    else t:SetText(cand.name) end
                    b:SetFontString(t)
                    b:SetScript("OnClick", function()
                        f.selections[i] = (cand.name ~= "- None -") and cand.name or nil
                        txt:SetText(t:GetText())
                        list:Hide()
                    end)
                    b:Show(); dy = dy - 20
                end
                content:SetHeight(math.abs(dy) + 10)
            end
            
            f.dropdowns[i] = btn
            y = y - 45
        end
        
        local save = CreateFrame("Button", nil, f)
        save:SetSize(80, 24); save:SetPoint("BOTTOMLEFT", 60, 20)
        CreateBg(save, 0, 0, 0, 1)
        local sFs = save:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
        sFs:SetPoint("CENTER"); sFs:SetText("Save")
        save:SetFontString(sFs)
        save:SetScript("OnClick", function()
            DB_Rmap_Tools.settings.strategists = f.selections
            GR:ShowMapToast("Strategists Saved", false)
            f:Hide()
        end)
        
        local closeBtn = CreateFrame("Button", nil, f)
        closeBtn:SetSize(80, 24); closeBtn:SetPoint("BOTTOMRIGHT", -60, 20)
        CreateBg(closeBtn, 0, 0, 0, 1)
        local cFs = closeBtn:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
        cFs:SetPoint("CENTER"); cFs:SetText("Close")
        closeBtn:SetFontString(cFs)
        closeBtn:SetScript("OnClick", function() f:Hide() end)
    end
    
    local leaderName = "Unknown"
    for i=1, GetNumGroupMembers() do
        local unit = IsInRaid() and ("raid"..i) or ("party"..i)
        if UnitIsGroupLeader(unit) then leaderName = GetUnitName(unit, true) break end
    end
    if not IsInGroup() then leaderName = UnitName("player") end
    
    f.leaderLbl:SetText("Raid Leader: " .. leaderName)
    f.selections = CopyTable(DB_Rmap_Tools.settings.strategists or {})
    
    for i, btn in ipairs(f.dropdowns) do
        btn:RefreshList()
        local saved = f.selections[i]
        if saved then btn.txt:SetText(saved) else btn.txt:SetText("- None -") end
    end
    
    f:Show()
end

local function CreateRobustVerticalScrollbar(parent, targetScrollFrame)
    local container = CreateFrame("Frame", nil, parent, "BackdropTemplate")
    container:SetWidth(18)
    container:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8x8", edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", tile = false, tileSize = 16, edgeSize = 12, insets = { left = 3, right = 3, top = 3, bottom = 3 } })
    container:SetBackdropColor(0, 0, 0, 0.8); container:SetBackdropBorderColor(0.6, 0.6, 0.6, 1); container:SetFrameLevel(parent:GetFrameLevel() + 5)
    local upBtn = CreateFrame("Button", nil, container); upBtn:SetSize(16, 16); upBtn:SetPoint("TOP", 0, -2); upBtn:SetNormalTexture("Interface\\Buttons\\UI-ScrollBar-ScrollUpButton-Up")
    local downBtn = CreateFrame("Button", nil, container); downBtn:SetSize(16, 16); downBtn:SetPoint("BOTTOM", 0, 2); downBtn:SetNormalTexture("Interface\\Buttons\\UI-ScrollBar-ScrollDownButton-Up")
    local slider = CreateFrame("Slider", nil, container); slider:SetOrientation("VERTICAL"); slider:SetPoint("TOP", upBtn, "BOTTOM", 0, 0); slider:SetPoint("BOTTOM", downBtn, "TOP", 0, 0); slider:SetWidth(18)
    local thumb = slider:CreateTexture(nil, "ARTWORK"); thumb:SetSize(14, 24); thumb:SetColorTexture(0.5, 0.5, 0.5, 1); slider:SetThumbTexture(thumb)
    slider:SetScript("OnValueChanged", function(self, value) targetScrollFrame:SetVerticalScroll(value) end)
    container.SetMinMaxValues = function(self, min, max) slider:SetMinMaxValues(min, max); thumb:SetShown(max > min) end
    container.GetValue = function(self) return slider:GetValue() end
    container.SetValue = function(self, v) local min, max = slider:GetMinMaxValues(); slider:SetValue(math.max(min, math.min(max, v))) end
    return container
end

-- =========================================================================
-- SAVE NAME POPUP DIALOG
-- =========================================================================
local function OpenSaveNameDialog(slotIndex, callback)
    local f = _G["GRS_Map_SaveDlg"]
    if not f then
        f = CreateFrame("Frame", "GRS_Map_SaveDlg", UIParent, "BackdropTemplate")
        f:SetSize(300, 150); f:SetPoint("CENTER"); f:SetFrameStrata("FULLSCREEN_DIALOG"); f:EnableMouse(true)
        f:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8x8", edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", tile = false, tileSize = 16, edgeSize = 16, insets = { left = 4, right = 4, top = 4, bottom = 4 } })
        f:SetBackdropColor(0, 0, 0, 0.95); f:SetBackdropBorderColor(0.6, 0.6, 0.6, 1)
        f.lbl = f:CreateFontString(nil, "OVERLAY", "GameFontNormal"); f.lbl:SetPoint("TOP", 0, -20); f.lbl:SetText("Name this Save (Max 10):")
        f.eb = CreateFrame("EditBox", nil, f, "InputBoxTemplate"); f.eb:SetSize(180, 24); f.eb:SetPoint("TOP", 0, -50); f.eb:SetAutoFocus(true); f.eb:SetMaxLetters(10)
        f.ok = CreateFrame("Button", nil, f, "UIPanelButtonTemplate"); f.ok:SetSize(80, 24); f.ok:SetPoint("BOTTOMLEFT", 60, 20); f.ok:SetText("Save")
        f.cancel = CreateFrame("Button", nil, f, "UIPanelButtonTemplate"); f.cancel:SetSize(80, 24); f.cancel:SetPoint("BOTTOMRIGHT", -60, 20); f.cancel:SetText("Cancel"); f.cancel:SetScript("OnClick", function() f:Hide() end)
    end
    f.eb:SetText(""); f.ok:SetScript("OnClick", function() local txt = f.eb:GetText() or ""; if txt ~= "" then callback(txt) end; f:Hide() end); f:Show()
end

-- =========================================================================
-- MAIN WINDOW LOGIC
-- =========================================================================
function GR:RR_OpenMapWindow()
    InitMapDatabase()
    if self.MapWindow then self.MapWindow:Show(); return end
    
    local f = CreateFrame("Frame", "GRS_RR_MapWindow", UIParent)
    f:SetSize(1064, 720); f:SetPoint("CENTER"); f:SetFrameStrata("MEDIUM"); f:SetFrameLevel(10); f:SetMovable(true); f:SetResizable(true); f:EnableMouse(true); f:SetResizeBounds(800, 500, 2500, 2500)
    f:RegisterForDrag("LeftButton"); f:SetScript("OnDragStart", f.StartMoving); f:SetScript("OnDragStop", f.StopMovingOrSizing)
    f:CreateTexture(nil, "BACKGROUND"):SetAllPoints(); f:GetRegions():SetColorTexture(0, 0, 0, 0.8)
    
    -- Auto-Close on Combat
    f:RegisterEvent("PLAYER_REGEN_DISABLED")
    f:SetScript("OnEvent", function(self, event)
        if event == "PLAYER_REGEN_DISABLED" then
            self:Hide()
        end
    end)
    
    local mainTitle = f:CreateFontString(nil, "OVERLAY", "GameFontNormalHuge"); mainTitle:SetPoint("TOP", 0, -10); mainTitle:SetText("A.X.I.O.M. | Raid Map")
    mainTitle:SetTextColor(0, 0.8, 1, 0.8)
    
    local c = CreateFrame("Button", nil, f); c:SetSize(24, 24); c:SetPoint("TOPRIGHT", -5, -5); SkinButton(c)
    local cfs = c:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); cfs:SetPoint("CENTER"); cfs:SetText("X"); c:SetFontString(cfs); c:SetScript("OnClick", function() f:Hide() end)
    
    local helpBtn = CreateFrame("Button", nil, f); helpBtn:SetSize(24, 24); helpBtn:SetPoint("RIGHT", c, "LEFT", -5, 0)
    local glow = helpBtn:CreateTexture(nil, "BACKGROUND"); glow:SetTexture("Interface\\Buttons\\WHITE8x8"); glow:SetVertexColor(1, 0.82, 0, 1); glow:SetPoint("TOPLEFT", -2, 2); glow:SetPoint("BOTTOMRIGHT", 2, -2)
    local ag = glow:CreateAnimationGroup(); ag:SetLooping("BOUNCE"); local a1 = ag:CreateAnimation("Alpha"); a1:SetFromAlpha(0); a1:SetToAlpha(1); a1:SetDuration(2.0); ag:Play()
    local blackBg = helpBtn:CreateTexture(nil, "ARTWORK"); blackBg:SetAllPoints(); blackBg:SetColorTexture(0, 0, 0, 1)
    local hfs = helpBtn:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); hfs:SetPoint("CENTER"); hfs:SetText("?"); helpBtn:SetScript("OnClick", function() OpenMapHelpDialog() end)
    
    local menuPane = CreateFrame("Frame", nil, f); menuPane:SetPoint("TOPLEFT", 0, -40); menuPane:SetPoint("TOPRIGHT", 0, -40); menuPane:SetFrameStrata("HIGH"); menuPane:SetFrameLevel(20); menuPane:CreateTexture(nil, "BACKGROUND"):SetAllPoints(); f.menuPane = menuPane
    
    local mapPane = CreateFrame("Frame", nil, f); mapPane:SetPoint("BOTTOMRIGHT", 0, 100); mapPane:SetFrameStrata("HIGH"); mapPane:SetFrameLevel(20); mapPane:EnableMouse(true)
    f.mapPane = mapPane; GR.mapPane = mapPane 
    local mapTex = mapPane:CreateTexture(nil, "BACKGROUND"); mapTex:SetPoint("CENTER"); mapTex:Hide(); f.mapTex = mapTex; GR.mapTex = mapTex 
    local mapOverlay = CreateFrame("Frame", "GRS_Map_Overlay", mapPane); mapOverlay:SetSize(1024, 512); mapOverlay:SetPoint("CENTER", mapTex, "CENTER"); mapOverlay:SetFrameStrata("LOW"); mapOverlay:SetAlpha(0); f.mapOverlay = mapOverlay
    
    local slotContainer = CreateFrame("Frame", nil, f); slotContainer:SetPoint("TOPLEFT", mapPane, "BOTTOMLEFT", 10, -5); slotContainer:SetPoint("TOPRIGHT", mapPane, "BOTTOMRIGHT", -10, -5); slotContainer:SetHeight(60); f.slotContainer = slotContainer; f.saveSlots = {}; GR.selectedSaveSlot = nil

    local function ReflowSaveSlots()
        local boss = DB_Rmap_Tools.lastBoss; local saves = (boss and DB_Rmap_Tools.saves[boss]) or {}
        local x, y = 0, 0; local maxW = slotContainer:GetWidth()
        for i=1, 10 do
            local btn = f.saveSlots[i]; local savedData = saves[i]
            local display = savedData and savedData.name or tostring(i); btn:SetText(display)
            btn:SetWidth(math.max(30, btn:GetFontString():GetStringWidth() + 20))
            if (x + btn:GetWidth()) > maxW then x = 0; y = y - 25 end
            btn:ClearAllPoints(); btn:SetPoint("TOPLEFT", x, y); x = x + btn:GetWidth() + 5
            if GR.selectedSaveSlot == i then btn:SetBackdropBorderColor(1, 0.82, 0, 1) else if savedData then btn:SetBackdropBorderColor(0, 1, 0, 1) else btn:SetBackdropBorderColor(0.5, 0.5, 0.5, 1) end end
        end
    end

    local function SelectSaveSlot(idx)
        GR.selectedSaveSlot = idx
        GR:WipeCanvasData() 
        
        local boss = DB_Rmap_Tools.lastBoss
        local saves = (boss and DB_Rmap_Tools.saves[boss]) or {}
        
        if idx == 11 then
            GR:RenderLiveBuffer() 
        elseif saves[idx] then
            local entry = saves[idx]
            DB_Rmap_Tools.canvasData = CopyTable(entry.data or {}) 
            for _, toolData in ipairs(DB_Rmap_Tools.canvasData) do
                GR:SpawnIndependentIcon(toolData, nil, nil, true) 
            end
            GR:ShowMapToast("Loaded: " .. entry.name, false)
        else
            table.wipe(DB_Rmap_Tools.canvasData)
        end
        ReflowSaveSlots()
        if f.btnSave then f.btnSave:UpdateState() end; if f.btnReset then f.btnReset:UpdateState() end
    end

    for i=1, 10 do
        local b = CreateFrame("Button", nil, slotContainer, "BackdropTemplate"); b:SetHeight(20)
        b:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8x8", edgeFile = "Interface\\Buttons\\WHITE8x8", edgeSize = 1 })
        b:SetBackdropColor(0.2, 0.2, 0.2, 1); b:SetBackdropBorderColor(0.5, 0.5, 0.5, 1)
        local fs = b:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); fs:SetPoint("CENTER"); b:SetFontString(fs)
        b:SetScript("OnClick", function() SelectSaveSlot(i) end); f.saveSlots[i] = b
    end

    local function CreateMapDropdown(parent, labelText)
        local lbl = parent:CreateFontString(nil, "OVERLAY", "GameFontHighlight"); lbl:SetText(labelText)
        local btn = CreateFrame("Button", nil, parent); btn:SetSize(200, 24); CreateBg(btn, 0.2, 0.2, 0.2, 1)
        local txt = btn:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); txt:SetPoint("LEFT", 5, 0); txt:SetText("Select..."); btn.txt = txt
        local list = CreateFrame("Frame", nil, btn); CreateBg(list, 0.1, 0.1, 0.1, 1); list:SetSize(200, 10); list:SetPoint("TOPLEFT", btn, "BOTTOMLEFT", 0, -2); list:SetFrameStrata("DIALOG"); list:SetFrameLevel(100); list:Hide()
        btn:SetScript("OnClick", function() list:SetShown(not list:IsShown()) end); return btn, list, lbl
    end

    local raidBtn, raidList, raidLbl = CreateMapDropdown(menuPane, "Choose Raid:")
    local bossBtn, bossList, bossLbl = CreateMapDropdown(menuPane, "Choose Boss:")
    local sep = menuPane:CreateTexture(nil, "ARTWORK"); sep:SetSize(1, 16); sep:SetColorTexture(0.5, 0.5, 0.5, 0.8)

    local function UpdateLayout()
        local w, h = f:GetSize(); local isHidden = DB_Rmap_Tools.settings.isMenuHidden; local hasMap = mapTex:IsShown()
        raidLbl:ClearAllPoints(); raidBtn:ClearAllPoints(); bossLbl:ClearAllPoints(); bossBtn:ClearAllPoints(); sep:ClearAllPoints(); mapPane:ClearAllPoints()
        if self.RaidTools then self.RaidTools:ClearAllPoints(); self.RaidTools:SetShown(hasMap) end
        if isHidden then
            menuPane:Hide()
            if self.RaidTools and hasMap then self.RaidTools:SetPoint("TOPLEFT", f, "TOPLEFT", 0, -25); self.RaidTools:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", 0, 100); mapPane:SetPoint("TOPLEFT", self.RaidTools, "TOPRIGHT", 0, 0)
            else mapPane:SetPoint("TOPLEFT", f, "TOPLEFT", 0, -25) end
            mapPane:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 0, 100)
        else
            menuPane:Show()
            if self.RaidTools and hasMap then self.RaidTools:SetPoint("TOPLEFT", menuPane, "BOTTOMLEFT", 0, 0); self.RaidTools:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", 0, 100); mapPane:SetPoint("TOPLEFT", self.RaidTools, "TOPRIGHT", 0, 0)
            else mapPane:SetPoint("TOPLEFT", menuPane, "BOTTOMLEFT", 0, 0) end
            mapPane:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 0, 100)
            sep:Show(); menuPane:SetHeight(50)
            raidLbl:SetPoint("LEFT", menuPane, "LEFT", 20, 0); raidBtn:SetPoint("LEFT", raidLbl, "RIGHT", 10, 0)
            sep:SetPoint("LEFT", raidBtn, "RIGHT", 20, 0); bossLbl:SetPoint("LEFT", sep, "RIGHT", 20, 0); bossBtn:SetPoint("LEFT", bossLbl, "RIGHT", 10, 0)
        end
        if hasMap then
            local pW, pH = mapPane:GetSize(); local scale = math.min(pW / 1024, pH / 512)
            mapTex:SetSize(1024 * scale, 512 * scale); mapOverlay:SetSize(1024 * scale, 512 * scale)
            if GR.RefreshCanvasIcons then GR:RefreshCanvasIcons() end
        end
        ReflowSaveSlots()
    end
    f:SetScript("OnSizeChanged", UpdateLayout)

    local function SpawnRaidTools()
        if self.RaidTools then return end
        local RaidTools = CreateFrame("Frame", "GRS_RR_RaidTools", f); RaidTools:SetWidth(256); RaidTools:SetFrameStrata("HIGH"); RaidTools:SetFrameLevel(mapPane:GetFrameLevel() + 10) 
        local rtBg = RaidTools:CreateTexture(nil, "BACKGROUND"); rtBg:SetAllPoints(); rtBg:SetColorTexture(0, 0, 0, 0.1); self.RaidTools = RaidTools
        local rtScroll = CreateFrame("ScrollFrame", nil, RaidTools); rtScroll:SetPoint("TOPLEFT", 5, -30); rtScroll:SetPoint("BOTTOMRIGHT", -25, 5); self.RaidToolsScroll = rtScroll
        local rtSlider = CreateRobustVerticalScrollbar(RaidTools, rtScroll); rtSlider:SetPoint("TOPRIGHT", -2, -30); rtSlider:SetPoint("BOTTOMRIGHT", -2, 5); self.RaidToolsSlider = rtSlider
        local rtContent = CreateFrame("Frame", nil, rtScroll); rtContent:SetSize(226, 1); rtScroll:SetScrollChild(rtContent); rtScroll:SetScript("OnMouseWheel", function(s, d) rtSlider:SetValue(rtSlider:GetValue() - (d * 30)) end); self.RaidToolsContent = rtContent
        if self.RT_PopulateToolGrid then self:RT_PopulateToolGrid() end
    end

    local function PopulateBossList(raidName)
        local bosses = GR.RAID_MAP_DATA[raidName] or {}; local kids = {bossList:GetChildren()}; for _, k in ipairs(kids) do k:Hide() end; local yIdx = 0
        for _, bData in ipairs(bosses) do
            local b = CreateFrame("Button", nil, bossList); b:SetSize(190, 20); b:SetPoint("TOPLEFT", 5, yIdx - 5)
            local t = b:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); t:SetPoint("LEFT", 2, 0); t:SetText(bData.name); b:SetFontString(t)
            b:SetScript("OnClick", function()
                bossBtn.txt:SetText(bData.name); mapTex:SetTexture("Interface\\AddOns\\GuildRecruiterManagement\\RaidRoster\\Resources\\Midnight\\" .. bData.file)
                mapTex:Show(); mapOverlay:Show(); bossList:Hide(); DB_Rmap_Tools.lastBoss = bData.name; GR.selectedSaveSlot = nil; SpawnRaidTools(); UpdateLayout()
                if GR.UpdateMacroPanel then GR:UpdateMacroPanel(bData.name) end -- SAFE UPDATE CALL
            end); b:Show(); yIdx = yIdx - 20
        end
        bossList:SetHeight(math.abs(yIdx) + 10)
    end

    local rY = 0
    for _, rName in ipairs(GR.RAID_ORDER) do
        local b = CreateFrame("Button", nil, raidList); b:SetSize(190, 20); b:SetPoint("TOPLEFT", 5, rY - 5)
        local t = b:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); t:SetPoint("LEFT", 2, 0); t:SetText(rName); b:SetFontString(t)
        b:SetScript("OnClick", function()
            raidBtn.txt:SetText(rName); DB_Rmap_Tools.lastRaid = rName; raidList:Hide(); PopulateBossList(rName)
            local firstBoss = GR.RAID_MAP_DATA[rName] and GR.RAID_MAP_DATA[rName][1]
            if firstBoss then
                DB_Rmap_Tools.lastBoss = firstBoss.name; bossBtn.txt:SetText(firstBoss.name)
                mapTex:SetTexture("Interface\\AddOns\\GuildRecruiterManagement\\RaidRoster\\Resources\\Midnight\\" .. firstBoss.file); mapTex:Show(); mapOverlay:Show(); SpawnRaidTools()
                if GR.UpdateMacroPanel then GR:UpdateMacroPanel(firstBoss.name) end -- SAFE UPDATE CALL
            else DB_Rmap_Tools.lastBoss = nil; bossBtn.txt:SetText("Select..."); mapTex:Hide(); mapOverlay:Hide(); if self.RaidTools then self.RaidTools:Hide() end end
            GR.selectedSaveSlot = nil; UpdateLayout()
        end); b:Show(); rY = rY - 20
    end
    raidList:SetHeight(math.abs(rY) + 10)

    local toggleBtn = CreateFrame("Button", nil, f); toggleBtn:SetSize(120, 24); toggleBtn:SetPoint("BOTTOMLEFT", 5, 5); toggleBtn:SetFrameLevel(30); CreateBg(toggleBtn, 0, 0, 0, 1)
    local toggleFs = toggleBtn:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); toggleFs:SetPoint("CENTER"); toggleFs:SetText("Toggle Map Only"); toggleBtn:SetFontString(toggleFs); toggleBtn:SetScript("OnClick", function() DB_Rmap_Tools.settings.isMenuHidden = not DB_Rmap_Tools.settings.isMenuHidden; UpdateLayout() end)
    
    local buttons = { { name = "Live", width = 60 }, { name = "Push", width = 60 }, { name = "Awareness Enforcer", width = 140, func = function() print("Awareness Enforcer Active") end },
        { name = "Strategists", width = 100, func = function() OpenStrategistDialog() end },
        { name = "Reset Save", width = 80, key = "reset", func = function() if not GR.selectedSaveSlot then return end; local boss = DB_Rmap_Tools.lastBoss; if boss and DB_Rmap_Tools.saves[boss] then DB_Rmap_Tools.saves[boss][GR.selectedSaveSlot] = nil; GR:ShowMapToast("Slot " .. GR.selectedSaveSlot .. " Cleared", false); ReflowSaveSlots() end end },
        { name = "Save", width = 60, key = "save", func = function() if not GR.selectedSaveSlot then return end; OpenSaveNameDialog(GR.selectedSaveSlot, function(name) local boss = DB_Rmap_Tools.lastBoss; if not boss then return end; if not DB_Rmap_Tools.saves[boss] then DB_Rmap_Tools.saves[boss] = {} end; local copy = {}; if DB_Rmap_Tools.canvasData then copy = CopyTable(DB_Rmap_Tools.canvasData) end; DB_Rmap_Tools.saves[boss][GR.selectedSaveSlot] = { name = name, data = copy }; GR:ShowMapToast("Saved: " .. name, false); ReflowSaveSlots() end) end } }
    
    local resizer = CreateFrame("Button", nil, f); resizer:SetSize(16, 16); resizer:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 0, 0); resizer:SetFrameLevel(30); resizer:SetNormalTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Up")
    resizer:SetScript("OnMouseDown", function() f:StartSizing("BOTTOMRIGHT") end); resizer:SetScript("OnMouseUp", function() f:StopMovingOrSizing() end)
    local lastBtn = resizer
    for i, bData in ipairs(buttons) do
        local btn = CreateFrame("Button", nil, f); btn:SetSize(bData.width, 24)
        if i == 1 then btn:SetPoint("BOTTOMRIGHT", lastBtn, "BOTTOMLEFT", -5, 5) else btn:SetPoint("RIGHT", lastBtn, "LEFT", -5, 0) end
        btn:SetFrameLevel(30); CreateBg(btn, 0, 0, 0, 1); local fs = btn:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); fs:SetPoint("CENTER"); fs:SetText(bData.name); btn:SetFontString(fs)
        if bData.key == "save" then
            f.btnSave = btn; btn:SetScript("OnClick", function() if btn:IsEnabled() then bData.func() end end)
            btn.UpdateState = function() if GR.selectedSaveSlot then btn:Enable(); fs:SetTextColor(1, 1, 1); btn:SetScript("OnEnter", nil) else btn:Disable(); fs:SetTextColor(0.5, 0.5, 0.5); btn:SetScript("OnEnter", function(s) GameTooltip:SetOwner(s, "ANCHOR_TOP"); GameTooltip:SetText("Select a save slot first", 1, 0.2, 0.2); GameTooltip:Show() end); btn:SetScript("OnLeave", function() GameTooltip:Hide() end) end end; btn:UpdateState()
        elseif bData.key == "reset" then
            f.btnReset = btn; btn:SetScript("OnClick", function() if btn:IsEnabled() then bData.func() end end)
            btn.UpdateState = function() local boss = DB_Rmap_Tools.lastBoss; local hasData = boss and DB_Rmap_Tools.saves[boss] and DB_Rmap_Tools.saves[boss][GR.selectedSaveSlot]; if GR.selectedSaveSlot and hasData then btn:Enable(); fs:SetTextColor(1, 1, 1) else btn:Disable(); fs:SetTextColor(0.5, 0.5, 0.5) end end; btn:UpdateState()
        elseif bData.func then btn:SetScript("OnClick", bData.func) end
        lastBtn = btn
    end
    
    -- INITIAL DATA LOAD
    if not DB_Rmap_Tools.lastRaid or not GR.RAID_MAP_DATA[DB_Rmap_Tools.lastRaid] then DB_Rmap_Tools.lastRaid = GR.RAID_ORDER[1]; DB_Rmap_Tools.lastBoss = nil end
    local currentRaid = DB_Rmap_Tools.lastRaid; raidBtn.txt:SetText(currentRaid); PopulateBossList(currentRaid)
    local bossDataList = GR.RAID_MAP_DATA[currentRaid]; local bossFound = false
    if DB_Rmap_Tools.lastBoss then for _, b in ipairs(bossDataList) do if b.name == DB_Rmap_Tools.lastBoss then bossFound = true; break end end end
    if not bossFound and bossDataList and bossDataList[1] then DB_Rmap_Tools.lastBoss = bossDataList[1].name end
    local currentBoss = DB_Rmap_Tools.lastBoss
    if currentBoss then
        local selectedBossData; for _, b in ipairs(bossDataList) do if b.name == currentBoss then selectedBossData = b; break end end
        if selectedBossData then bossBtn.txt:SetText(currentBoss); mapTex:SetTexture("Interface\\AddOns\\GuildRecruiterManagement\\RaidRoster\\Resources\\Midnight\\" .. selectedBossData.file); mapTex:Show(); mapOverlay:Show(); SpawnRaidTools() end
        if GR.UpdateMacroPanel then GR:UpdateMacroPanel(currentBoss) end -- SAFE UPDATE CALL
    end
    UpdateLayout()
    self.MapWindow = f
end