-- ============================================================================
-- ARENACORE EDIT MODE - Simple Drag-to-Position System
-- ============================================================================
-- CONCEPT: Same frames, same database, same refresh logic as sliders
-- DIFFERENCE: Click-and-drag instead of sliders to adjust positioning
-- SHARED: Everything saves to the same database paths (trinkets.positioning, etc.)
-- ============================================================================

local AC = _G.ArenaCore
if not AC then return end

AC.EditMode = AC.EditMode or {}
local EM = AC.EditMode

-- ============================================================================
-- STATE MANAGEMENT
-- ============================================================================
EM.isActive = false
EM.registeredFrames = {} -- Tracks all draggable frames by group

-- ============================================================================
-- DRAGGABLE ELEMENT GROUPS
-- ============================================================================
-- Each group defines:
-- - dbPath: Database path for positioning (e.g., "trinkets.positioning")
-- - refreshFunc: Function to call after position changes
-- - selector: Function to find all frames in this group

local ELEMENT_GROUPS = {
    trinkets = {
        dbPath = "trinkets.positioning",
        refreshFunc = "RefreshTrinketsOtherLayout",
        selector = function()
            local frames = {}
            -- Use FrameManager system (new unified architecture)
            local arenaFrames = AC.FrameManager and AC.FrameManager:GetFrames()
            if arenaFrames then
                for i = 1, 3 do
                    local f = arenaFrames[i]
                    if f and f.trinketIndicator then
                        table.insert(frames, f.trinketIndicator)
                    end
                end
            end
            return frames
        end
    },
    
    racials = {
        dbPath = "racials.positioning",
        refreshFunc = "RefreshTrinketsOtherLayout",
        selector = function()
            local frames = {}
            local arenaFrames = AC.FrameManager and AC.FrameManager:GetFrames()
            if arenaFrames then
                for i = 1, 3 do
                    local f = arenaFrames[i]
                    if f and f.racialIndicator then
                        table.insert(frames, f.racialIndicator)
                    end
                end
            end
            return frames
        end
    },
    
    castBars = {
        dbPath = "castBars.positioning",
        refreshFunc = "RefreshCastBarsLayout",
        selector = function()
            local frames = {}
            local arenaFrames = AC.FrameManager and AC.FrameManager:GetFrames()
            if arenaFrames then
                for i = 1, 3 do
                    local f = arenaFrames[i]
                    if f and f.castBar then
                        table.insert(frames, f.castBar)
                    end
                end
            end
            return frames
        end
    },
    
    -- NOTE: DR Icons support is in EditMode_DR.lua
    -- They require special handling due to dynamic container recreation
    
    classIcons = {
        dbPath = "classIcons.positioning",
        refreshFunc = "RefreshTrinketsOtherLayout",
        selector = function()
            local frames = {}
            local arenaFrames = AC.FrameManager and AC.FrameManager:GetFrames()
            if arenaFrames then
                for i = 1, 3 do
                    local f = arenaFrames[i]
                    if f and f.classIcon then
                        table.insert(frames, f.classIcon)
                    end
                end
            end
            return frames
        end
    },
    
    specIcons = {
        dbPath = "specIcons.positioning",
        refreshFunc = "RefreshTrinketsOtherLayout",
        selector = function()
            local frames = {}
            local arenaFrames = AC.FrameManager and AC.FrameManager:GetFrames()
            if arenaFrames then
                for i = 1, 3 do
                    local f = arenaFrames[i]
                    if f and f.specIcon then
                        table.insert(frames, f.specIcon)
                    end
                end
            end
            return frames
        end
    },
    
    debuffs = {
        dbPath = "moreGoodies.debuffs.positioning",
        refreshFunc = "RefreshDebuffsLayout",
        selector = function()
            local frames = {}
            local arenaFrames = AC.FrameManager and AC.FrameManager:GetFrames()
            if arenaFrames then
                for i = 1, 3 do
                    local f = arenaFrames[i]
                    if f and f.debuffContainer then
                        table.insert(frames, f.debuffContainer)
                    end
                end
            end
            return frames
        end
    }
    
    -- NOTE: Class Packs (TriBadges) support is in EditMode_ClassPacks.lua
    -- They require special handling due to their custom frame structure
}

-- Expose ELEMENT_GROUPS so modules can extend it
EM.ELEMENT_GROUPS = ELEMENT_GROUPS

-- ============================================================================
-- CORE DRAG LOGIC
-- ============================================================================

local function SavePosition(groupConfig, offsetX, offsetY)
    -- Save to database using ProfileManager (same as sliders)
    local PM = AC.ProfileManager
    if not PM then 
        print("|cffFF0000[EDIT MODE]|r ProfileManager not found!")
        return 
    end
    
    -- CRITICAL: Class icons have a base offset that gets added during refresh
    -- We need to subtract it before saving to prevent snap/jump
    if groupConfig.dbPath == "classIcons.positioning" then
        offsetX = offsetX - 8  -- Subtract base LEFT offset
        offsetY = offsetY - 0  -- No base vertical offset
    end
    
    -- DRAG + SLIDER SYSTEM: Save Edit Mode position as base, keep slider offsets unchanged
    -- This mimics Ctrl+Alt+Click frame dragging behavior
    -- Final Position = Edit Mode Base + Slider Offset
    
    -- Special field mapping for Class Packs (TriBadges)
    if groupConfig.dbPath == "classPacks" then
        -- Get current slider offset (if it exists)
        local currentOffsetX = PM:GetSetting("classPacks.sliderOffsetX") or 0
        local currentOffsetY = PM:GetSetting("classPacks.sliderOffsetY") or 0
        
        -- Calculate base position (subtract current slider offset from dragged position)
        local baseX = offsetX - currentOffsetX
        local baseY = offsetY - currentOffsetY
        
        -- Save base position from Edit Mode drag
        PM:SetSetting("classPacks.draggedBaseX", baseX)
        PM:SetSetting("classPacks.draggedBaseY", baseY)
        
        -- Update main position (base + offset = final)
        PM:SetSetting("classPacks.offsetX", offsetX)
        PM:SetSetting("classPacks.offsetY", offsetY)
        
        print("|cffFFAA00[EDIT MODE]|r Class Packs: Base=(" .. baseX .. ", " .. baseY .. "), Offset=(" .. currentOffsetX .. ", " .. currentOffsetY .. "), Final=(" .. offsetX .. ", " .. offsetY .. ")")
    else
        -- Default path uses horizontal/vertical
        -- Get current slider offset (if it exists)
        local currentOffsetX = PM:GetSetting(groupConfig.dbPath .. ".sliderOffsetX") or 0
        local currentOffsetY = PM:GetSetting(groupConfig.dbPath .. ".sliderOffsetY") or 0
        
        -- Calculate base position (subtract current slider offset from dragged position)
        local baseX = offsetX - currentOffsetX
        local baseY = offsetY - currentOffsetY
        
        -- Save base position from Edit Mode drag
        PM:SetSetting(groupConfig.dbPath .. ".draggedBaseX", baseX)
        PM:SetSetting(groupConfig.dbPath .. ".draggedBaseY", baseY)
        
        -- Update main position (base + offset = final)
        PM:SetSetting(groupConfig.dbPath .. ".horizontal", offsetX)
        PM:SetSetting(groupConfig.dbPath .. ".vertical", offsetY)
        
        print("|cffFFAA00[EDIT MODE]|r " .. groupConfig.dbPath .. ": Base=(" .. baseX .. ", " .. baseY .. "), Offset=(" .. currentOffsetX .. ", " .. currentOffsetY .. "), Final=(" .. offsetX .. ", " .. offsetY .. ")")
    end
    
    -- Delay refresh slightly to ensure database is updated
    C_Timer.After(0.05, function()
        if groupConfig.refreshFunc and AC[groupConfig.refreshFunc] then
            AC[groupConfig.refreshFunc](AC)
            
            -- REBIND: Recreate/reuse glow + drag on fresh frames
            C_Timer.After(0.1, function()
                if EM.isActive then
                    local frames = groupConfig.selector()
                    -- DEBUG: print("|cff00FFFF[EditMode]|r Rebind: Found " .. #frames .. " frames for " .. (groupConfig.dbPath or "unknown"))
                    for i, frame in ipairs(frames) do
                        EM:MakeDraggable(frame, groupConfig)  -- Idempotent: reuses if present, creates if missing
                        if frame.editModeGlow then frame.editModeGlow:Show() end
                        if frame.editModeGlowFrame then 
                            frame.editModeGlowFrame:Show()
                            local parent = frame.editModeGlowFrame:GetParent()
                            local hasOnDragStart = frame.editModeGlowFrame:GetScript("OnDragStart") ~= nil
                            local strata = frame.editModeGlowFrame:GetFrameStrata()
                            local level = frame.editModeGlowFrame:GetFrameLevel()
                            local isMovable = frame.editModeGlowFrame:IsMovable()
                            -- DEBUG: print("|cff00FFFF[EditMode]|r Frame " .. i .. ": visible=" .. tostring(frame.editModeGlowFrame:IsVisible()) .. ", mouseEnabled=" .. tostring(frame.editModeGlowFrame:IsMouseEnabled()) .. ", hasOnDragStart=" .. tostring(hasOnDragStart) .. ", isMovable=" .. tostring(isMovable) .. ", strata=" .. strata .. ", level=" .. level)
                        end
                    end
                end
            end)
        end
    end)
end

function EM:MakeDraggable(frame, groupConfig)
    if not frame then return end
    
    local callID = math.random(1000, 9999)
    -- DEBUG: print("|cffCCFF00[EditMode " .. callID .. "]|r MakeDraggable START for " .. (groupConfig.dbPath or "unknown") .. ", frame=" .. tostring(frame))
    
    -- Accept any table or userdata - try to use it and let WoW handle errors
    local frameType = type(frame)
    if frameType ~= "table" and frameType ~= "userdata" then
        print("|cffFF0000[EDIT MODE ERROR]|r Invalid frame type (" .. frameType .. ") for " .. (groupConfig.dbPath or "unknown"))
        return
    end
    
    -- Add blue glow to indicate draggable (or update if it already exists)
    local glowFrame = frame.editModeGlowFrame
    
    if not glowFrame then
        -- Create a separate frame for the glow overlay
        glowFrame = CreateFrame("Frame", nil, frame)
        
        -- For DR icons, the wrapper frame in EditMode_DR.lua handles everything
        -- So we just create a simple glow that covers the whole frame
        if false and groupConfig.dbPath == "diminishingReturns.positioning" then
            -- Get DR settings from database
            local db = AC.DB and AC.DB.profile and AC.DB.profile.diminishingReturns
            if db then
                local pos = db.positioning or {}
                local sizing = db.sizing or {}
                local iconSize = tonumber(sizing.size) or 33
                local spacing = tonumber(pos.spacing) or 3
                local growth = pos.growthDirection or "Right"
                
                -- Calculate glow size based on number of DR categories (7 max)
                local maxIcons = 7
                local glowWidth, glowHeight
                
                if growth == "Right" or growth == "Left" then
                    -- Horizontal layout
                    glowWidth = (iconSize * maxIcons) + (spacing * (maxIcons - 1))
                    glowHeight = iconSize
                else
                    -- Vertical layout
                    glowWidth = iconSize
                    glowHeight = (iconSize * maxIcons) + (spacing * (maxIcons - 1))
                end
                
                glowFrame:SetSize(glowWidth, glowHeight)
                
                -- Position based on growth direction
                local baseX = pos.horizontal or 0
                local baseY = pos.vertical or 0
                
                if growth == "Right" then
                    glowFrame:SetPoint("TOPRIGHT", frame, "TOPRIGHT", baseX, baseY)
                elseif growth == "Left" then
                    glowFrame:SetPoint("TOPLEFT", frame, "TOPLEFT", baseX, baseY)
                elseif growth == "Up" then
                    glowFrame:SetPoint("TOPRIGHT", frame, "TOPRIGHT", baseX, baseY)
                elseif growth == "Down" then
                    glowFrame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", baseX, baseY)
                end
                
                -- Set strata/level so glow is above DR icons but below UI panels
                -- Use HIGH (not DIALOG) so UI panels stay on top
                glowFrame:SetFrameStrata("HIGH")
                glowFrame:SetFrameLevel(100)
            else
                -- Fallback if no database
                glowFrame:SetSize(150, 35)
                glowFrame:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 236, 0)
                glowFrame:SetFrameStrata("HIGH")
                glowFrame:SetFrameLevel(100)
            end
        else
            -- For other elements, glow covers the whole frame
            glowFrame:SetAllPoints(frame)
            -- Set appropriate strata for non-DR elements
            glowFrame:SetFrameStrata("HIGH")
            glowFrame:SetFrameLevel(50)
        end
        
        local glow = glowFrame:CreateTexture(nil, "OVERLAY")
        glow:SetAllPoints(glowFrame)
        glow:SetColorTexture(0.3, 0.5, 1.0, 0.3) -- Blue glow
        glow:SetBlendMode("ADD")
        
        -- Add border textures for clear visual indication
        local borderThickness = 2
        
        -- Top border
        local topBorder = glowFrame:CreateTexture(nil, "OVERLAY")
        topBorder:SetColorTexture(0.3, 0.6, 1.0, 1.0) -- Bright blue, fully opaque
        topBorder:SetPoint("TOPLEFT", glowFrame, "TOPLEFT", 0, 0)
        topBorder:SetPoint("TOPRIGHT", glowFrame, "TOPRIGHT", 0, 0)
        topBorder:SetHeight(borderThickness)
        
        -- Bottom border
        local bottomBorder = glowFrame:CreateTexture(nil, "OVERLAY")
        bottomBorder:SetColorTexture(0.3, 0.6, 1.0, 1.0)
        bottomBorder:SetPoint("BOTTOMLEFT", glowFrame, "BOTTOMLEFT", 0, 0)
        bottomBorder:SetPoint("BOTTOMRIGHT", glowFrame, "BOTTOMRIGHT", 0, 0)
        bottomBorder:SetHeight(borderThickness)
        
        -- Left border
        local leftBorder = glowFrame:CreateTexture(nil, "OVERLAY")
        leftBorder:SetColorTexture(0.3, 0.6, 1.0, 1.0)
        leftBorder:SetPoint("TOPLEFT", glowFrame, "TOPLEFT", 0, 0)
        leftBorder:SetPoint("BOTTOMLEFT", glowFrame, "BOTTOMLEFT", 0, 0)
        leftBorder:SetWidth(borderThickness)
        
        -- Right border
        local rightBorder = glowFrame:CreateTexture(nil, "OVERLAY")
        rightBorder:SetColorTexture(0.3, 0.6, 1.0, 1.0)
        rightBorder:SetPoint("TOPRIGHT", glowFrame, "TOPRIGHT", 0, 0)
        rightBorder:SetPoint("BOTTOMRIGHT", glowFrame, "BOTTOMRIGHT", 0, 0)
        rightBorder:SetWidth(borderThickness)
        
        frame.editModeGlow = glow
        frame.editModeGlowFrame = glowFrame
        frame.editModeGlowBorders = {topBorder, bottomBorder, leftBorder, rightBorder}
    else
        -- Glow frame already exists - show the borders that were hidden on Disable
        if frame.editModeGlowBorders then
            for _, border in ipairs(frame.editModeGlowBorders) do
                border:Show()
            end
        end
        
        -- CRITICAL FIX: Clear the editModeDraggable flag so it can be re-setup
        -- This happens when RefreshDRLayout doesn't destroy the glow frame
        -- Use rawset to bypass any metatable magic
        local oldValue = rawget(glowFrame, "editModeDraggable")
        -- DEBUG: if oldValue then
        --     print("|cffFF6600[EditMode]|r Clearing stale flag for " .. (groupConfig.dbPath or "unknown") .. ", was: " .. tostring(oldValue))
        -- end
        rawset(glowFrame, "editModeDraggable", nil)
        
        -- Glow frame already exists, just reposition it (for DR icons after refresh)
        if false and groupConfig.dbPath == "diminishingReturns.positioning" then
            local db = AC.DB and AC.DB.profile and AC.DB.profile.diminishingReturns
            if db then
                local pos = db.positioning or {}
                local sizing = db.sizing or {}
                local iconSize = tonumber(sizing.size) or 33
                local spacing = tonumber(pos.spacing) or 3
                local growth = pos.growthDirection or "Right"
                
                local maxIcons = 7
                local glowWidth, glowHeight
                
                if growth == "Right" or growth == "Left" then
                    glowWidth = (iconSize * maxIcons) + (spacing * (maxIcons - 1))
                    glowHeight = iconSize
                else
                    glowWidth = iconSize
                    glowHeight = (iconSize * maxIcons) + (spacing * (maxIcons - 1))
                end
                
                glowFrame:SetSize(glowWidth, glowHeight)
                
                local baseX = pos.horizontal or 0
                local baseY = pos.vertical or 0
                
                glowFrame:ClearAllPoints()
                if growth == "Right" then
                    glowFrame:SetPoint("TOPRIGHT", frame, "TOPRIGHT", baseX, baseY)
                elseif growth == "Left" then
                    glowFrame:SetPoint("TOPLEFT", frame, "TOPLEFT", baseX, baseY)
                elseif growth == "Up" then
                    glowFrame:SetPoint("TOPRIGHT", frame, "TOPRIGHT", baseX, baseY)
                elseif growth == "Down" then
                    glowFrame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", baseX, baseY)
                end
                
                -- Glow repositioned
            end
        end
    end
    
    -- Always show the glow
    frame.editModeGlow:Show()
    frame.editModeGlowFrame:Show()
    
    -- Make the frame itself draggable
    local draggableFrame = frame
    local mouseFrame = frame
    
    -- If already draggable, just ensure everything is enabled and return
    -- Use rawget to bypass WoW frame metatable magic
    local isDraggable = rawget(draggableFrame, "editModeDraggable")
    -- DEBUG: print("|cffCCCCCC[EditMode " .. callID .. "]|r Check draggable: " .. (groupConfig.dbPath or "unknown") .. ", rawget=" .. tostring(isDraggable))
    if isDraggable then
        -- Re-enable everything (in case it was disabled when exiting Edit Mode)
        draggableFrame:SetMovable(true)
        if mouseFrame ~= draggableFrame then
            mouseFrame:SetMovable(true)  -- For DR, also make the glow frame movable
        end
        mouseFrame:EnableMouse(true)
        mouseFrame:RegisterForDrag("LeftButton")
        if frame.editModeGlow then frame.editModeGlow:Show() end
        if frame.editModeGlowFrame then frame.editModeGlowFrame:Show() end
        -- DEBUG: print("|cffFFAA00[EditMode " .. callID .. "]|r MakeDraggable END (already draggable, re-enabled)")
        return
    end
    
    -- DEBUG: print("|cff00FF00[EditMode " .. callID .. "]|r Proceeding with setup...")
    
    -- DEBUG: print("|cff22AA44[EditMode]|r Setting up draggable for " .. (groupConfig.dbPath or "unknown"))
    
    rawset(draggableFrame, "editModeDraggable", true)
    draggableFrame:SetMovable(true)
    
    -- Enable mouse and drag on the mouseFrame (which might be the glow for DR icons)
    if mouseFrame ~= draggableFrame then
        mouseFrame:SetMovable(true)  -- For DR, also make the glow frame movable
    end
    mouseFrame:EnableMouse(true)
    mouseFrame:RegisterForDrag("LeftButton")
    -- DEBUG: print("|cff00FF00[EditMode]|r Movable=" .. tostring(draggableFrame:IsMovable()) .. ", MouseEnabled=" .. tostring(mouseFrame:IsMouseEnabled()))
    
    -- Store original scripts to restore later
    draggableFrame.originalOnDragStart = draggableFrame:GetScript("OnDragStart")
    draggableFrame.originalOnDragStop = draggableFrame:GetScript("OnDragStop")
    draggableFrame.originalOnUpdate = draggableFrame:GetScript("OnUpdate")
    
    -- Mark that THIS frame was touched by edit mode
    draggableFrame._emStoredScripts = true
    
    -- Store initial mouse position for offset calculation
    local dragStartX, dragStartY
    local initialOffsets = {}
    local isDragging = false
    
    mouseFrame:SetScript("OnDragStart", function(self)
        -- DEBUG: print("|cffFF00FF[EditMode]|r OnDragStart called! self=" .. tostring(self))
        -- The draggable frame IS the target frame now
        local targetFrame = frame
        isDragging = true
        
        -- Get mouse position at drag start FIRST
        local scale = targetFrame:GetEffectiveScale()
        local mouseX, mouseY = GetCursorPosition()
        dragStartX = mouseX / scale
        dragStartY = mouseY / scale
        
        -- Prevent one-frame snap on first drag if a layout refresh just happened
        -- Only do this if self is NOT the same as targetFrame (to avoid "anchor to itself" error)
        -- Match the target frame's current anchor to avoid jump
        if self ~= targetFrame then
            local p, rel, rp, x, y = targetFrame:GetPoint()
            self:ClearAllPoints()
            self:SetPoint(p or "TOPLEFT", rel or targetFrame, rp or "TOPLEFT", x or 0, y or 0)
        end
        
        -- Store initial offset of the TARGET frame (the one we're actually positioning)
        local point, relativeTo, relativePoint, xOfs, yOfs = targetFrame:GetPoint()
        initialOffsets.draggedFrame = {
            frame = targetFrame,
            point = point,
            relativeTo = relativeTo,
            relativePoint = relativePoint,
            x = xOfs or 0,
            y = yOfs or 0
        }
        
        -- Store initial offsets for all sibling frames in group
        local allFrames = groupConfig.selector()
        for i, siblingFrame in ipairs(allFrames) do
            local sPoint, sRelativeTo, sRelativePoint, sXOfs, sYOfs = siblingFrame:GetPoint()
            initialOffsets[i] = {
                frame = siblingFrame,
                point = sPoint,
                relativeTo = sRelativeTo,
                relativePoint = sRelativePoint,
                x = sXOfs or 0,
                y = sYOfs or 0
            }
        end
        
        -- DON'T use StartMoving() - we'll handle positioning manually
        -- This prevents the frame from jumping to mouse cursor
    end)
    
    -- Use OnUpdate to track mouse movement during drag
    mouseFrame:SetScript("OnUpdate", function(self)
        local targetFrame = self.dragTarget or frame
        if not isDragging then return end
        
        -- Calculate mouse delta
        local scale = self:GetEffectiveScale()
        local currentX, currentY = GetCursorPosition()
        currentX = currentX / scale
        currentY = currentY / scale
        
        local deltaX = currentX - dragStartX
        local deltaY = currentY - dragStartY
        
        -- Update ALL frames (including the dragged one) with the same delta
        for i, data in ipairs(initialOffsets) do
            data.frame:ClearAllPoints()
            data.frame:SetPoint(
                data.point,
                data.relativeTo,
                data.relativePoint,
                data.x + deltaX,
                data.y + deltaY
            )
        end
        
        -- Also update the dragged frame itself
        if initialOffsets.draggedFrame then
            local dragData = initialOffsets.draggedFrame
            self:ClearAllPoints()
            self:SetPoint(
                dragData.point,
                dragData.relativeTo,
                dragData.relativePoint,
                dragData.x + deltaX,
                dragData.y + deltaY
            )
        end
    end)
    
    mouseFrame:SetScript("OnDragStop", function(self)
        local targetFrame = self.dragTarget or frame
        isDragging = false
        
        -- Calculate final position from mouse delta
        local scale = self:GetEffectiveScale()
        local currentX, currentY = GetCursorPosition()
        currentX = currentX / scale
        currentY = currentY / scale
        
        local deltaX = currentX - dragStartX
        local deltaY = currentY - dragStartY
        
        -- Get the original position from the dragged frame specifically
        local originalData = initialOffsets.draggedFrame
        if originalData then
            -- Calculate final position
            local finalX = originalData.x + deltaX
            local finalY = originalData.y + deltaY
            
            -- Round to nearest pixel
            finalX = math.floor(finalX + 0.5)
            finalY = math.floor(finalY + 0.5)
            
            print("|cffFFAA00[EDIT MODE]|r Original: (" .. originalData.x .. ", " .. originalData.y .. "), Delta: (" .. math.floor(deltaX) .. ", " .. math.floor(deltaY) .. "), Final: (" .. finalX .. ", " .. finalY .. ")")
            
            -- Save position (this triggers refresh for ALL frames in group)
            SavePosition(groupConfig, finalX, finalY)
        else
            -- Fallback: use current position
            local point, relativeTo, relativePoint, offsetX, offsetY = self:GetPoint()
            if offsetX and offsetY then
                offsetX = math.floor(offsetX + 0.5)
                offsetY = math.floor(offsetY + 0.5)
                SavePosition(groupConfig, offsetX, offsetY)
            end
        end
        
        -- Clear stored offsets
        initialOffsets = {}
    end)
end

local function RemoveDraggable(frame)
    if not frame then return end
    
    -- DEBUG: print("|cffFF6600[EditMode]|r RemoveDraggable called on frame: " .. tostring(frame))
    
    -- Clear draggable from the frame itself
    if rawget(frame, "editModeDraggable") then
        -- DEBUG: print("|cffFF6600[EditMode]|r Clearing frame draggable")
        rawset(frame, "editModeDraggable", nil)
        frame:SetMovable(false)
        frame:EnableMouse(false)
        frame:RegisterForDrag()
    end
    
    -- For DR icons, also clear mouse/drag from the glow frame (even if it doesn't have the flag)
    if frame.editModeGlowFrame then
        -- DEBUG: print("|cffFF6600[EditMode]|r Clearing glow frame mouse/drag")
        frame.editModeGlowFrame:SetMovable(false)
        frame.editModeGlowFrame:EnableMouse(false)
        frame.editModeGlowFrame:RegisterForDrag()
    end
    
    -- Hide blue glow
    if frame.editModeGlow then
        frame.editModeGlow:Hide()
    end
    if frame.editModeGlowFrame then
        frame.editModeGlowFrame:Hide()
    end
    
    -- Restore ONLY if this exact frame had edit-mode scripts saved
    if frame._emStoredScripts then
        frame:SetScript("OnDragStart", frame.originalOnDragStart)
        frame:SetScript("OnDragStop", frame.originalOnDragStop)
        frame:SetScript("OnUpdate", frame.originalOnUpdate)
        frame.originalOnDragStart, frame.originalOnDragStop, frame.originalOnUpdate = nil, nil, nil
        frame._emStoredScripts = nil
    end
end

-- ============================================================================
-- VISUAL OVERLAY SYSTEM
-- ============================================================================

local function CreateEditModeOverlay()
    -- Create full-screen overlay
    local overlay = CreateFrame("Frame", "ArenaCoreEditModeOverlay", UIParent)
    overlay:SetAllPoints(UIParent)
    overlay:SetFrameStrata("MEDIUM") -- Changed from BACKGROUND to be visible over game world
    overlay:SetFrameLevel(1)
    
    -- Get cast bar texture from database
    local texturesDB = AC.DB and AC.DB.profile and AC.DB.profile.textures
    local castBarTexture = "Interface\\AddOns\\ArenaCore\\Media\\Frametextures\\texture1.tga"
    if texturesDB and texturesDB.castBarTexture then
        castBarTexture = texturesDB.castBarTexture
    end
    
    -- Solid purple base
    local tex = overlay:CreateTexture(nil, "BACKGROUND")
    tex:SetAllPoints()
    tex:SetTexture("Interface\\Tooltips\\UI-Tooltip-Background")
    tex:SetVertexColor(0.4, 0.15, 0.5, 0.5) -- Purple base
    
    -- Create diagonal stripe pattern using cast bar texture
    -- Cover entire screen with more stripes
    local screenWidth = GetScreenWidth()
    local screenHeight = GetScreenHeight()
    
    -- Calculate diagonal distance to cover entire screen
    local diagonal = math.sqrt(screenWidth^2 + screenHeight^2)
    local stripeSpacing = 30
    local stripeCount = math.ceil(diagonal / stripeSpacing) + 30 -- Extra stripes for full coverage
    
    for i = 1, stripeCount do
        local stripe = overlay:CreateTexture(nil, "ARTWORK")
        stripe:SetTexture(castBarTexture) -- Use your cast bar texture
        stripe:SetVertexColor(0.6, 0.25, 0.7, 0.4) -- Lighter purple for stripes
        stripe:SetBlendMode("ADD") -- Additive blending for nice overlay effect
        
        -- Position diagonal stripes to cover entire screen including corners
        local offset = (i - 1) * stripeSpacing - (diagonal / 2) - 300 -- Start well off-screen left
        stripe:SetSize(25, diagonal + 500) -- Make stripes as long as screen diagonal
        stripe:SetPoint("CENTER", overlay, "CENTER", offset * 0.707, offset * 0.707) -- Position along diagonal
        stripe:SetRotation(math.rad(45)) -- Rotate 45 degrees for diagonal
    end
    
    -- Create info popup with ArenaCore styling
    local popup = CreateFrame("Frame", nil, UIParent)
    popup:SetSize(280, 100)
    popup:SetPoint("TOP", UIParent, "TOP", 0, -100)
    popup:SetFrameStrata("DIALOG")
    popup:SetFrameLevel(1000)
    
    -- Use ArenaCore's dark texture styling (same as dispel window)
    local COLORS = AC.COLORS or {}
    
    -- Outer border
    local outerBorder = popup:CreateTexture(nil, "BACKGROUND")
    outerBorder:SetAllPoints()
    outerBorder:SetColorTexture(0.2, 0.2, 0.2, 1)
    
    -- Inner background (dark)
    local bg = popup:CreateTexture(nil, "BORDER")
    bg:SetPoint("TOPLEFT", 2, -2)
    bg:SetPoint("BOTTOMRIGHT", -2, 2)
    bg:SetColorTexture(0.08, 0.08, 0.08, 0.98)
    
    -- Accent line at top (purple)
    local accent = popup:CreateTexture(nil, "ARTWORK")
    accent:SetPoint("TOPLEFT", 2, -2)
    accent:SetPoint("TOPRIGHT", -2, -2)
    accent:SetHeight(2)
    accent:SetColorTexture(0.55, 0.35, 0.65, 1)
    
    -- Title
    local title = popup:CreateFontString(nil, "OVERLAY")
    title:SetFont("Interface/AddOns/ArenaCore/Media/Fonts/arenacore.ttf", 14, "OUTLINE")
    title:SetText("EDIT MODE ACTIVE")
    title:SetTextColor(1, 1, 0.3, 1) -- Yellow
    title:SetPoint("TOP", popup, "TOP", 0, -15)
    
    -- Info text
    local info = popup:CreateFontString(nil, "OVERLAY")
    info:SetFont("Interface/AddOns/ArenaCore/Media/Fonts/arenacore.ttf", 11)
    info:SetText("Click and drag any blue element\nto reposition it")
    info:SetTextColor(0.9, 0.9, 0.9, 1)
    info:SetPoint("TOP", title, "BOTTOM", 0, -8)
    info:SetJustifyH("CENTER")
    
    -- Exit button with ArenaCore purple styling (matches Save Settings button)
    local exitBtn = CreateFrame("Button", nil, popup)
    exitBtn:SetSize(120, 28)
    exitBtn:SetPoint("BOTTOM", popup, "BOTTOM", 0, 10)
    
    -- Background (purple)
    local exitBg = exitBtn:CreateTexture(nil, "BACKGROUND")
    exitBg:SetAllPoints()
    exitBg:SetColorTexture(0.545, 0.271, 1.000, 1) -- ArenaCore PRIMARY purple
    
    -- Border (darker for depth)
    local exitBorder = exitBtn:CreateTexture(nil, "BORDER")
    exitBorder:SetAllPoints()
    exitBorder:SetColorTexture(0.4, 0.2, 0.7, 1) -- Darker purple border
    exitBorder:SetPoint("TOPLEFT", 1, -1)
    exitBorder:SetPoint("BOTTOMRIGHT", -1, 1)
    
    -- Text (white, no outline)
    local exitText = exitBtn:CreateFontString(nil, "OVERLAY")
    exitText:SetFont("Interface/AddOns/ArenaCore/Media/Fonts/arenacore.ttf", 12) -- No outline
    exitText:SetText("EXIT EDIT MODE")
    exitText:SetTextColor(1, 1, 1, 1) -- Pure white
    exitText:SetPoint("CENTER")
    
    exitBtn:SetScript("OnClick", function()
        if AC.EditMode then
            AC.EditMode:Disable()
            
            -- Update the Edit Mode button in Arena Frames page
            if AC.UpdateEditModeButton then
                AC.UpdateEditModeButton()
            end
        end
    end)
    
    -- Hover effect (lighter purple)
    exitBtn:SetScript("OnEnter", function()
        exitBg:SetColorTexture(0.645, 0.371, 1.000, 1) -- Lighter purple on hover
    end)
    
    exitBtn:SetScript("OnLeave", function()
        exitBg:SetColorTexture(0.545, 0.271, 1.000, 1) -- Back to normal purple
    end)
    
    overlay.popup = popup
    return overlay
end

-- ============================================================================
-- PUBLIC API
-- ============================================================================

function EM:Enable()
    if self.isActive then return end
    
    -- Ensure test mode is active
    if not AC.testModeEnabled then
        print("|cffFF0000ArenaCore Edit Mode:|r Please enable Test Mode first (/ac test)")
        return
    end
    
    self.isActive = true
    
    -- Create visual overlay
    if not self.overlay then
        self.overlay = CreateEditModeOverlay()
    end
    self.overlay:Show()
    self.overlay.popup:Show()
    
    -- Make all element groups draggable
    for groupName, groupConfig in pairs(ELEMENT_GROUPS) do
        local frames = groupConfig.selector()
        for _, frame in ipairs(frames) do
            self:MakeDraggable(frame, groupConfig)
        end
        self.registeredFrames[groupName] = frames
    end
    
    print("|cff22AA44ArenaCore Edit Mode:|r ENABLED - Drag any blue element to reposition")
end

function EM:Disable()
    if not self.isActive then return end
    
    -- DEBUG: print("|cffFF0000[EditMode]|r Disable() called! Stack trace:")
    -- DEBUG: print(debugstack(2))
    
    self.isActive = false
    
    -- Hide visual overlay
    if self.overlay then
        self.overlay:Hide()
        self.overlay.popup:Hide()
    end
    
    -- Remove draggable from all registered frames
    for groupName, frames in pairs(self.registeredFrames) do
        for _, frame in ipairs(frames) do
            RemoveDraggable(frame)
            
            -- Also hide glow texture and borders
            if frame.editModeGlow then
                frame.editModeGlow:Hide()
            end
            if frame.editModeGlowBorders then
                for _, border in ipairs(frame.editModeGlowBorders) do
                    border:Hide()
                end
            end
        end
    end
    
    -- Clear registry
    self.registeredFrames = {}
    
    print("|cff22AA44ArenaCore Edit Mode:|r DISABLED - Frames locked")
end

function EM:Toggle()
    if self.isActive then
        self:Disable()
    else
        self:Enable()
    end
end

function EM:IsActive()
    return self.isActive
end

-- ============================================================================
-- SLASH COMMAND
-- ============================================================================

SLASH_ACEDITMODE1 = "/acedit"
SlashCmdList["ACEDITMODE"] = function(msg)
    msg = msg:lower():trim()
    
    if msg == "on" or msg == "enable" then
        EM:Enable()
    elseif msg == "off" or msg == "disable" then
        EM:Disable()
    elseif msg == "toggle" or msg == "" then
        EM:Toggle()
    elseif msg == "status" then
        if EM.isActive then
            print("|cff22AA44ArenaCore Edit Mode:|r Currently ENABLED")
        else
            print("|cffFFAA00ArenaCore Edit Mode:|r Currently DISABLED")
        end
    elseif msg == "help" then
        print("|cff22AA44ArenaCore Edit Mode Commands:|r")
        print("  /acedit - Toggle edit mode on/off")
        print("  /acedit on - Enable edit mode")
        print("  /acedit off - Disable edit mode")
        print("  /acedit status - Check if edit mode is active")
        print(" ")
        print("|cffFFAA00How it works:|r")
        print("  • Enable Test Mode first (/ac test)")
        print("  • Enable Edit Mode (/acedit)")
        print("  • Click and drag any element (trinket, cast bar, etc.)")
        print("  • All elements in that group move together")
        print("  • Changes save in real-time to the same database as sliders")
        print("  • Use /ac hide and /ac test to verify positions persist")
    else
        print("|cffFF0000ArenaCore Edit Mode:|r Unknown command. Type /acedit help for usage")
    end
end

-- ============================================================================
-- INITIALIZATION
-- ============================================================================

-- Hook into UI close to also disable Edit Mode
-- Use event system to wait for UI to be created
local hookFrame = CreateFrame("Frame")
hookFrame:RegisterEvent("ADDON_LOADED")
hookFrame:SetScript("OnEvent", function(self, event, addonName)
    if addonName == "ArenaCore" then
        -- Try multiple times to find the frame
        local attempts = 0
        local function TryHook()
            attempts = attempts + 1
            local configFrame = _G["ArenaCoreConfigFrame"]
            if configFrame then
                configFrame:HookScript("OnHide", function()
                    -- DEBUG: print("|cffFF00FF[EditMode]|r UI OnHide triggered! isActive=" .. tostring(EM.isActive))
                    if EM.isActive then
                        -- UI closed, disabling Edit Mode
                        -- DEBUG: print("|cffFF0000[EditMode]|r UI closed, calling Disable()")
                        EM:Disable()
                        -- Update button if it exists
                        if AC.UpdateEditModeButton then
                            AC.UpdateEditModeButton()
                        end
                    end
                    
                    -- Apply Z-order policy when panel hides
                    if AC.ZPolicy then
                        AC.ZPolicy:OnPanelHide()
                    end
                end)
                -- Hooked to UI close
            elseif attempts < 10 then
                -- Try again in 0.5 seconds
                C_Timer.After(0.5, TryHook)
            else
                -- DEBUG: Config frame not found - not critical, Edit Mode still works
                -- print("|cffFF0000ArenaCore Edit Mode:|r Could not find ArenaCoreConfigFrame after 10 attempts")
            end
        end
        TryHook()
        self:UnregisterEvent("ADDON_LOADED")
    end
end)

-- Disabled startup message for end users
-- print("|cff22AA44ArenaCore:|r Edit Mode loaded - Type /acedit help for usage")
