-- SPDX-License-Identifier: GPL-3.0-or-later
local ADDON_NAME = "DevourerRotationHelper"
local DRH = {}
_G[ADDON_NAME] = DRH

local AF = _G.AbstractFramework
if not AF then
    error(ADDON_NAME .. " requires AbstractFramework to be loaded first!")
    return
end

-- ============================================================================
-- 1. Database & Configuration
-- ============================================================================
-- Custom Fonts to prevent "Font Not Found" errors
local FONT_EXPRESSWAY = LibStub("LibSharedMedia-3.0", true) and 
                        LibStub("LibSharedMedia-3.0"):Fetch("font", "Expressway") or 
                        "Fonts\\FRIZQT__.TTF"

local ExpresswayNormal = CreateFont("DRH_ExpresswayNormal")
ExpresswayNormal:SetFont(FONT_EXPRESSWAY, 12, "OUTLINE")

local ExpresswaySmall = CreateFont("DRH_ExpresswaySmall")
ExpresswaySmall:SetFont(FONT_EXPRESSWAY, 10, "OUTLINE")

-- Base spells - will be extended with spellbook scan
local SPELL_DATABASE = {
    {spellID = 473662, name = "Consume"},
    {spellID = 1226019, name = "Reap"},
    {spellID = 1245412, name = "Voidblade"},
    {spellID = 1246167, name = "Void Strike"},
    {spellID = 1217605, name = "Void Metamorphosis"},
}

local DEFAULTS = {
    enabled = true,
    iconSize = 42,
    spacing = 4,
    iconsPerRow = 10,
    scale = 1.0,
    position = {point = "CENTER", x = 0, y = -200},
    rotation = {},
    minimap = {hide = false},
}

-- ============================================================================
-- 2. State & Variables
-- ============================================================================
local mainFrame, browserFrame, editButton
local rotationSorter
local widgetPool = {}
local keybindCache = {}
local dragPreviewIcon  -- Custom drag preview icon

-- ============================================================================
-- 3. Utility Functions
-- ============================================================================
local function SimplifyKeybind(key)
    if not key then return "" end
    key = key:upper()
    key = key:gsub("SHIFT", "s"):gsub("CTRL", "c"):gsub("ALT", "a"):gsub("STRG", "c")
    key = key:gsub("BUTTON", "M"):gsub("MOUSEWHEEL", "W")
    key = key:gsub("NUMPAD", "N"):gsub("PAGE", "P")
    key = key:gsub("-", ""):gsub("%s", "")
    return key
end

local function GetKeybindForSpell(spellID)
    if keybindCache[spellID] then return keybindCache[spellID] end
    local spellName = C_Spell.GetSpellInfo(spellID) and C_Spell.GetSpellInfo(spellID).name
    if not spellName then return nil end
    local key = GetBindingKey("SPELL " .. spellName)
    if key then
        keybindCache[spellID] = SimplifyKeybind(key)
        return keybindCache[spellID]
    end
    return nil
end

-- ============================================================================
-- 4. Spellbook Scanner
-- ============================================================================
local function ScanPlayerSpellbook()
    -- Track which spells we've already added to avoid duplicates
    local knownSpellIDs = {}
    local allSpells = {}
    local spellsByCategory = {}  -- Track spells organized by category
    
    -- Special Devourer spells to always include
    local specialDevourerSpells = {1245453, 1217610, 1245470, 1245483}
    
    -- Initialize Devourer category
    spellsByCategory["Devourer"] = {}
    
    -- Add special Devourer spells first
    for _, spellID in ipairs(specialDevourerSpells) do
        local spellInfo = C_Spell.GetSpellInfo(spellID)
        if spellInfo and spellInfo.name then
            local spellData = {
                spellID = spellID,
                name = spellInfo.name,
                category = "Devourer"
            }
            table.insert(allSpells, spellData)
            table.insert(spellsByCategory["Devourer"], spellData)
            knownSpellIDs[spellID] = true
        end
    end
    
    -- Get total number of tabs
    local numSpellTabs = C_SpellBook.GetNumSpellBookSkillLines()
    
    AF.Print("=== Starting Spellbook Scan ===")
    AF.Print("Found " .. numSpellTabs .. " spellbook tabs")
    
    for tabIndex = 1, numSpellTabs do
        local skillLineInfo = C_SpellBook.GetSpellBookSkillLineInfo(tabIndex)
        
        if skillLineInfo then
            local tabName = skillLineInfo.name or "Unknown"
            local offset = skillLineInfo.itemIndexOffset
            local numSlots = skillLineInfo.numSpellBookItems
            local shouldDraw = skillLineInfo.shouldDraw
            
            AF.Print(string.format("Tab %d: '%s' | Offset: %d | Slots: %d | ShouldDraw: %s", 
                tabIndex, tabName, offset, numSlots, tostring(shouldDraw)))
            
            -- Skip professions and General tab
            local isProfession = tabName:match("Profession") ~= nil
            local isGeneral = tabName == "General" or tabName:match("General") ~= nil
            
            if not isProfession and not isGeneral then
                local spellsFoundInTab = 0
                
                -- Initialize category if it doesn't exist
                if not spellsByCategory[tabName] then
                    spellsByCategory[tabName] = {}
                end
                
                for slotIndex = offset + 1, offset + numSlots do
                    local spellBookItemInfo = C_SpellBook.GetSpellBookItemInfo(slotIndex, Enum.SpellBookSpellBank.Player)
                    
                    if spellBookItemInfo then
                        local itemType = spellBookItemInfo.itemType
                        local spellID = spellBookItemInfo.spellID
                        
                        -- Debug: Print what we find
                        if itemType == Enum.SpellBookItemType.Spell then
                            if spellID and not knownSpellIDs[spellID] then
                                local spellInfo = C_Spell.GetSpellInfo(spellID)
                                if spellInfo and spellInfo.name then
                                    local spellData = {
                                        spellID = spellID,
                                        name = spellInfo.name,
                                        category = tabName
                                    }
                                    table.insert(allSpells, spellData)
                                    table.insert(spellsByCategory[tabName], spellData)
                                    knownSpellIDs[spellID] = true
                                    spellsFoundInTab = spellsFoundInTab + 1
                                end
                            end
                            
                        elseif itemType == Enum.SpellBookItemType.FutureSpell then
                            if spellID and not knownSpellIDs[spellID] then
                                local spellInfo = C_Spell.GetSpellInfo(spellID)
                                if spellInfo and spellInfo.name then
                                    local spellData = {
                                        spellID = spellID,
                                        name = spellInfo.name,
                                        category = tabName
                                    }
                                    table.insert(allSpells, spellData)
                                    table.insert(spellsByCategory[tabName], spellData)
                                    knownSpellIDs[spellID] = true
                                    spellsFoundInTab = spellsFoundInTab + 1
                                end
                            end
                            
                        elseif itemType == Enum.SpellBookItemType.Flyout then
                            local flyoutID = spellBookItemInfo.actionID
                            if flyoutID then
                                local _, _, numFlyoutSlots, isKnown = GetFlyoutInfo(flyoutID)
                                if isKnown and numFlyoutSlots then
                                    for flyoutSlot = 1, numFlyoutSlots do
                                        local flyoutSpellID, overrideSpellID, isKnownSlot = GetFlyoutSlotInfo(flyoutID, flyoutSlot)
                                        local actualSpellID = overrideSpellID or flyoutSpellID
                                        
                                        if actualSpellID and isKnownSlot and not knownSpellIDs[actualSpellID] then
                                            local spellInfo = C_Spell.GetSpellInfo(actualSpellID)
                                            if spellInfo and spellInfo.name then
                                                local spellData = {
                                                    spellID = actualSpellID,
                                                    name = spellInfo.name,
                                                    category = tabName
                                                }
                                                table.insert(allSpells, spellData)
                                                table.insert(spellsByCategory[tabName], spellData)
                                                knownSpellIDs[actualSpellID] = true
                                                spellsFoundInTab = spellsFoundInTab + 1
                                            end
                                        end
                                    end
                                end
                            end
                        end
                    end
                end
                
                AF.Print(string.format("  -> Found %d spells in '%s'", spellsFoundInTab, tabName))
            else
                if isProfession then
                    AF.Print("  -> Skipped (Profession)")
                else
                    AF.Print("  -> Skipped (General)")
                end
            end
        end
    end
    
    -- Sort each category alphabetically
    for category, spells in pairs(spellsByCategory) do
        table.sort(spells, function(a, b)
            return a.name < b.name
        end)
    end
    
    -- Sort all spells by category first, then by name
    table.sort(allSpells, function(a, b)
        if a.category == b.category then
            return a.name < b.name
        end
        return a.category < b.category
    end)
    
    SPELL_DATABASE = allSpells
    DRH.SpellsByCategory = spellsByCategory  -- Store categorized version globally
    
    AF.Print("=== Scan Complete ===")
    AF.Print(string.format("Total spells found: %d", #SPELL_DATABASE))
    
    -- Count categories manually
    local categoryCount = 0
    for _ in pairs(spellsByCategory) do
        categoryCount = categoryCount + 1
    end
    AF.Print(string.format("Categories: %d", categoryCount))
    
    -- Print category breakdown
    for category, spells in pairs(spellsByCategory) do
        AF.Print(string.format("  %s: %d spells", category, #spells))
    end
end

-- ============================================================================
-- 5. Rotation UI Logic
-- ============================================================================
local function CreateDragPreviewIcon()
    if dragPreviewIcon then return dragPreviewIcon end
    
    -- Create a simple icon frame that follows the cursor
    dragPreviewIcon = CreateFrame("Frame", "DRH_DragPreview", UIParent)
    AF.SetSize(dragPreviewIcon, 40, 40)
    dragPreviewIcon:SetFrameStrata("TOOLTIP")
    dragPreviewIcon:SetFrameLevel(100)
    
    -- Create the icon texture
    local icon = dragPreviewIcon:CreateTexture(nil, "ARTWORK")
    dragPreviewIcon.icon = icon
    icon:SetAllPoints(dragPreviewIcon)
    icon:SetTexCoord(0.07, 0.93, 0.07, 0.93)  -- Standard icon cropping
    
    -- Create insertion line indicator (vertical line between icons)
    dragPreviewIcon.insertLine = CreateFrame("Frame", nil, UIParent)
    dragPreviewIcon.insertLine:SetFrameStrata("TOOLTIP")  -- Changed to TOOLTIP for better visibility
    dragPreviewIcon.insertLine:SetFrameLevel(10)
    
    local tex = dragPreviewIcon.insertLine:CreateTexture(nil, "OVERLAY")
    tex:SetAllPoints()
    tex:SetColorTexture(0.5, 1, 0, 1.0)  -- Bright yellow-green at 100% opacity for maximum visibility
    dragPreviewIcon.insertLine.tex = tex
    
    dragPreviewIcon.insertLine:Hide()
    dragPreviewIcon:Hide()
    
    return dragPreviewIcon
end

local function CreateRotationWidget()
    local btn = AF.CreateIconButton(nil, nil, 40, 40)
    
    btn.stepText = AF.CreateFontString(btn, "", "white", ExpresswaySmall)
    AF.SetPoint(btn.stepText, "BOTTOMRIGHT", -2, 2)
    
    btn.keybindText = AF.CreateFontString(btn, "", "orange", ExpresswaySmall)
    AF.SetPoint(btn.keybindText, "TOPLEFT", 2, -2)

    btn.update = function(self, index)
        self.stepText:SetText(index)
        self.keybindText:SetText(GetKeybindForSpell(self.value.spellID) or "")
        
        -- Update tooltip to show spell info
        if self.value and self.value.spellID then
            self:SetScript("OnEnter", function(widget)
                GameTooltip:SetOwner(widget, "ANCHOR_RIGHT")
                GameTooltip:SetSpellByID(widget.value.spellID)
                GameTooltip:Show()
            end)
            self:SetScript("OnLeave", function()
                GameTooltip:Hide()
            end)
        end
    end
    
    -- Mark this widget so DragSorter won't hook it
    btn._dragSorterHooked = true
    btn.disabled = true  -- Prevent DragSorter from processing
    
    -- Custom drag handling for icon-only preview
    btn:SetScript("OnMouseDown", function(self, button)
        if button == "LeftButton" then
            local preview = CreateDragPreviewIcon()
            -- Use the icon that's already set on this button instead of fetching again
            local spellTexture = self.tipIcon or C_Spell.GetSpellTexture(self.value.spellID)
            preview.icon:SetTexture(spellTexture)
            preview:Show()
            preview:SetPoint("CENTER", UIParent, "BOTTOMLEFT", 0, 0)
            
            preview:SetScript("OnUpdate", function(self)
                local x, y = GetCursorPosition()
                local scale = UIParent:GetEffectiveScale()
                self:SetPoint("CENTER", UIParent, "BOTTOMLEFT", x / scale, y / scale)
                
                -- Find insertion point between icons
                if rotationSorter and rotationSorter.slots then
                    local db = DevourerRotationHelperDB
                    local sourceIndex = self.sourceWidget and self.sourceWidget.index
                    local insertIndex = nil
                    local insertSlot = nil
                    
                    -- Check each slot to find where to insert
                    for i, slot in ipairs(rotationSorter.slots) do
                        if slot:IsMouseOver() and i ~= sourceIndex then
                            insertIndex = i
                            insertSlot = slot
                            break
                        end
                    end
                    
                    if insertIndex and insertSlot then
                        -- Calculate position for insertion line
                        local lineWidth = 6  -- Thicker line for better visibility
                        local lineHeight = db.iconSize + 12  -- Even taller than icon
                        
                        self.insertLine:SetSize(lineWidth, lineHeight)
                        self.insertLine:ClearAllPoints()
                        
                        -- Determine if we're inserting before or after based on horizontal position
                        local slotLeft = insertSlot:GetLeft()
                        local slotRight = insertSlot:GetRight()
                        local cursorX = x / scale
                        local slotCenter = (slotLeft + slotRight) / 2
                        
                        if cursorX < slotCenter then
                            -- Insert before this slot (on the left side)
                            self.insertLine:SetPoint("CENTER", insertSlot, "LEFT", -db.spacing / 2, 0)
                        else
                            -- Insert after this slot (on the right side)
                            self.insertLine:SetPoint("CENTER", insertSlot, "RIGHT", db.spacing / 2, 0)
                        end
                        
                        self.insertLine:Show()
                    else
                        self.insertLine:Hide()
                    end
                end
            end)
            preview.sourceWidget = self
        end
    end)
    
    btn:SetScript("OnMouseUp", function(self, button)
        if button == "LeftButton" and dragPreviewIcon and dragPreviewIcon:IsShown() then
            dragPreviewIcon:Hide()
            dragPreviewIcon.insertLine:Hide()
            dragPreviewIcon:SetScript("OnUpdate", nil)
            
            -- Find target slot and determine insertion position
            if dragPreviewIcon.sourceWidget and rotationSorter then
                local sourceIndex = dragPreviewIcon.sourceWidget.index
                local db = DevourerRotationHelperDB
                
                for i, slot in ipairs(rotationSorter.slots) do
                    if slot:IsMouseOver() and i ~= sourceIndex then
                        local x, y = GetCursorPosition()
                        local scale = UIParent:GetEffectiveScale()
                        local cursorX = x / scale
                        
                        local slotLeft = slot:GetLeft()
                        local slotRight = slot:GetRight()
                        local slotCenter = (slotLeft + slotRight) / 2
                        
                        local targetIndex = i
                        -- If cursor is on right side of slot, insert after
                        if cursorX >= slotCenter then
                            targetIndex = i + 1
                        end
                        
                        -- Adjust target index if dragging from before the target
                        if sourceIndex < targetIndex then
                            targetIndex = targetIndex - 1
                        end
                        
                        if targetIndex ~= sourceIndex then
                            AF.MoveElementToIndex(DevourerRotationHelperDB.rotation, sourceIndex, targetIndex)
                            DRH.RebuildRotationDisplay()
                        end
                        break
                    end
                end
            end
            dragPreviewIcon.sourceWidget = nil
        end
    end)

    btn:RegisterForClicks("RightButtonUp")
    btn:HookScript("OnClick", function(self, button)
        if button == "RightButton" then
            local db = DevourerRotationHelperDB.rotation
            for i, val in ipairs(db) do
                if val == self.value then table.remove(db, i) break end
            end
            DRH.RebuildRotationDisplay()
        end
    end)
    
    -- Re-enable the button visually (it's only disabled for DragSorter)
    btn:SetEnabled(true)
    
    return btn
end

function DRH.RebuildRotationDisplay()
    if not rotationSorter then return end
    local db = DevourerRotationHelperDB
    
    if rotationSorter.widgets then
        for _, w in ipairs(rotationSorter.widgets) do 
            w:Hide()
            table.insert(widgetPool, w) 
        end
    end

    local widgets = {}
    for _, spellData in ipairs(db.rotation) do
        local w = table.remove(widgetPool) or CreateRotationWidget()
        w.value = spellData
        w.tipText = spellData.name
        w.tipIcon = C_Spell.GetSpellTexture(spellData.spellID)
        w:SetIcon(w.tipIcon)
        w:Show()
        table.insert(widgets, w)
    end

    rotationSorter.slotWidth = db.iconSize
    rotationSorter.slotHeight = db.iconSize
    rotationSorter.slotSpacing = db.spacing
    rotationSorter:SetWidgets(widgets, true)
    rotationSorter:SetConfigTable(db.rotation)

    for i, slot in ipairs(rotationSorter.slots) do
        AF.ClearPoints(slot)
        local col = (i - 1) % db.iconsPerRow
        local row = math.floor((i - 1) / db.iconsPerRow)
        AF.SetPoint(slot, "TOPLEFT", rotationSorter, "TOPLEFT", 
            col * (db.iconSize + db.spacing), 
            -row * (db.iconSize + db.spacing))
        AF.SetSize(slot, db.iconSize, db.iconSize)
    end

    -- Dynamic sizing with proper margins
    local numSpells = #db.rotation
    if numSpells == 0 then numSpells = 1 end -- Minimum 1 to prevent zero-size
    
    local rows = math.ceil(numSpells / db.iconsPerRow)
    local cols = math.min(numSpells, db.iconsPerRow)
    
    -- Calculate content size
    local contentWidth = cols * db.iconSize + (cols - 1) * db.spacing
    local contentHeight = rows * db.iconSize + (rows - 1) * db.spacing
    
    -- Add margins: left(10) + right(10) for width, top(25 header) + bottom(10) for height
    local frameWidth = contentWidth + 20
    local frameHeight = contentHeight + 35  -- Reduced from 42 to match new spacing
    
    -- Minimum size to prevent header elements from overlapping
    -- Need space for: title + slider(80) + edit(40) + close(20) + spacing
    local minWidth = 200
    local minHeight = 80
    
    frameWidth = math.max(frameWidth, minWidth)
    frameHeight = math.max(frameHeight, minHeight)
    
    AF.SetSize(mainFrame, frameWidth, frameHeight)
end

-- ============================================================================
-- 6. Browser & Settings Frame
-- ============================================================================
local function CreateBrowserFrame()
    -- Toggle behavior: if already exists and shown, hide it
    if browserFrame then
        browserFrame:SetShown(not browserFrame:IsShown())
        return
    end
    
    -- Fixed sizing for scrollable content
    local windowWidth = 400
    local windowHeight = 500
    
    browserFrame = AF.CreateHeaderedFrame(UIParent, "DRH_Browser", "Add Spells", windowWidth, windowHeight)
    AF.SetPoint(browserFrame, "CENTER", 250, 0)

    -- Clear Rotation Button
    local resetBtn = AF.CreateButton(browserFrame, "Clear Rotation", "accent")
    AF.SetSize(resetBtn, 110, 22)
    AF.SetPoint(resetBtn, "TOPRIGHT", -15, -35)
    resetBtn:SetScript("OnClick", function()
        DevourerRotationHelperDB.rotation = {}
        DRH.RebuildRotationDisplay()
        AF.Print("Rotation Cleared")
    end)

    -- Spell Browser Header
    local spellHeader = AF.CreateFontString(browserFrame, "Click to Add:", "accent", ExpresswayNormal)
    AF.SetPoint(spellHeader, "TOPLEFT", 20, -35)

    -- Create scroll frame for spell content
    local scrollFrame = CreateFrame("ScrollFrame", "DRH_SpellScrollFrame", browserFrame, "UIPanelScrollFrameTemplate")
    scrollFrame:SetPoint("TOPLEFT", 20, -60)
    scrollFrame:SetPoint("BOTTOMRIGHT", -35, 15)
    
    -- Create content frame inside scroll frame
    local scrollChild = CreateFrame("Frame", nil, scrollFrame)
    scrollFrame:SetScrollChild(scrollChild)
    scrollChild:SetWidth(scrollFrame:GetWidth())
    
    local yOffset = 0
    local iconSize = 40
    local iconSpacing = 4
    local iconsPerRow = 8
    local categorySpacing = 30
    
    -- Get sorted category names
    local categoryNames = {}
    for categoryName, _ in pairs(DRH.SpellsByCategory or {}) do
        table.insert(categoryNames, categoryName)
    end
    table.sort(categoryNames)
    
    -- Build UI organized by categories
    for _, categoryName in ipairs(categoryNames) do
        local spells = DRH.SpellsByCategory[categoryName]
        
        if spells and #spells > 0 then
            -- Category Header
            local categoryHeader = AF.CreateFontString(scrollChild, categoryName, "accent", ExpresswayNormal)
            AF.SetPoint(categoryHeader, "TOPLEFT", 0, yOffset)
            yOffset = yOffset - 22
            
            -- Create spell buttons for this category
            for i, data in ipairs(spells) do
                local b = AF.CreateIconButton(scrollChild, nil, iconSize, iconSize)
                b:SetIcon(C_Spell.GetSpellTexture(data.spellID))
                
                -- Setup spell tooltip on hover
                b:SetScript("OnEnter", function(self)
                    GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
                    GameTooltip:SetSpellByID(data.spellID)
                    GameTooltip:Show()
                end)
                b:SetScript("OnLeave", function()
                    GameTooltip:Hide()
                end)
                
                -- Store spell data on button for drag/drop
                b.spellData = data
                
                -- Enable drag and drop
                b:SetScript("OnMouseDown", function(self, button)
                    if button == "LeftButton" then
                        local preview = CreateDragPreviewIcon()
                        local spellTexture = C_Spell.GetSpellTexture(self.spellData.spellID)
                        preview.icon:SetTexture(spellTexture)
                        preview.spellData = self.spellData  -- Store the spell data
                        preview.fromBrowser = true  -- Mark as coming from browser
                        preview:Show()
                        preview:SetPoint("CENTER", UIParent, "BOTTOMLEFT", 0, 0)
                        
                        preview:SetScript("OnUpdate", function(self)
                            local x, y = GetCursorPosition()
                            local scale = UIParent:GetEffectiveScale()
                            self:SetPoint("CENTER", UIParent, "BOTTOMLEFT", x / scale, y / scale)
                            
                            -- Find insertion point in rotation
                            if rotationSorter and rotationSorter.slots then
                                local db = DevourerRotationHelperDB
                                local insertIndex = nil
                                local insertSlot = nil
                                
                                -- Check each slot to find where to insert
                                for i, slot in ipairs(rotationSorter.slots) do
                                    if slot:IsMouseOver() then
                                        insertIndex = i
                                        insertSlot = slot
                                        break
                                    end
                                end
                                
                                -- Also check if hovering over the main rotation frame (for empty rotations)
                                if not insertIndex and mainFrame and mainFrame:IsMouseOver() then
                                    insertIndex = #db.rotation + 1
                                    insertSlot = rotationSorter.slots[1]  -- Use first slot as reference
                                end
                                
                                if insertIndex and insertSlot then
                                    -- Calculate position for insertion line
                                    local lineWidth = 6
                                    local lineHeight = db.iconSize + 12
                                    
                                    self.insertLine:SetSize(lineWidth, lineHeight)
                                    self.insertLine:ClearAllPoints()
                                    
                                    -- Determine if we're inserting before or after based on horizontal position
                                    local slotLeft = insertSlot:GetLeft()
                                    local slotRight = insertSlot:GetRight()
                                    local cursorX = x / scale
                                    local slotCenter = (slotLeft + slotRight) / 2
                                    
                                    if cursorX < slotCenter or insertIndex > #db.rotation then
                                        -- Insert before this slot (on the left side) or at the end
                                        self.insertLine:SetPoint("CENTER", insertSlot, "LEFT", -db.spacing / 2, 0)
                                    else
                                        -- Insert after this slot (on the right side)
                                        self.insertLine:SetPoint("CENTER", insertSlot, "RIGHT", db.spacing / 2, 0)
                                    end
                                    
                                    self.insertLine:Show()
                                else
                                    self.insertLine:Hide()
                                end
                            end
                        end)
                    end
                end)
                
                b:SetScript("OnMouseUp", function(self, button)
                    if button == "LeftButton" and dragPreviewIcon and dragPreviewIcon:IsShown() then
                        dragPreviewIcon:Hide()
                        dragPreviewIcon.insertLine:Hide()
                        dragPreviewIcon:SetScript("OnUpdate", nil)
                        
                        -- Add spell to rotation at appropriate position
                        if dragPreviewIcon.fromBrowser and dragPreviewIcon.spellData then
                            local db = DevourerRotationHelperDB
                            local insertIndex = nil
                            
                            -- Find where to insert
                            if rotationSorter then
                                for i, slot in ipairs(rotationSorter.slots) do
                                    if slot:IsMouseOver() then
                                        local x, y = GetCursorPosition()
                                        local scale = UIParent:GetEffectiveScale()
                                        local cursorX = x / scale
                                        
                                        local slotLeft = slot:GetLeft()
                                        local slotRight = slot:GetRight()
                                        local slotCenter = (slotLeft + slotRight) / 2
                                        
                                        if cursorX < slotCenter then
                                            insertIndex = i
                                        else
                                            insertIndex = i + 1
                                        end
                                        break
                                    end
                                end
                            end
                            
                            -- If hovering over main frame but no specific slot, add to end
                            if not insertIndex and mainFrame and mainFrame:IsMouseOver() then
                                insertIndex = #db.rotation + 1
                            end
                            
                            -- Insert the spell
                            if insertIndex then
                                table.insert(db.rotation, insertIndex, {
                                    spellID = dragPreviewIcon.spellData.spellID,
                                    name = dragPreviewIcon.spellData.name
                                })
                                DRH.RebuildRotationDisplay()
                                AF.Print("Added: " .. dragPreviewIcon.spellData.name)
                            end
                        end
                        
                        dragPreviewIcon.fromBrowser = nil
                        dragPreviewIcon.spellData = nil
                    end
                end)
                
                -- Keep click functionality as backup
                b:RegisterForClicks("LeftButtonUp")
                b:SetScript("OnClick", function(self)
                    -- Only trigger if we didn't just finish a drag
                    if not dragPreviewIcon or not dragPreviewIcon:IsShown() then
                        table.insert(DevourerRotationHelperDB.rotation, {spellID = data.spellID, name = data.name})
                        DRH.RebuildRotationDisplay()
                        AF.Print("Added: " .. data.name)
                    end
                end)
                
                local col = (i - 1) % iconsPerRow
                local row = math.floor((i - 1) / iconsPerRow)
                AF.SetPoint(b, "TOPLEFT", col * (iconSize + iconSpacing), yOffset - row * (iconSize + iconSpacing))
            end
            
            -- Calculate height needed for this category's spells
            local rows = math.ceil(#spells / iconsPerRow)
            local categoryHeight = rows * (iconSize + iconSpacing)
            yOffset = yOffset - categoryHeight - categorySpacing
        end
    end
    
    -- Set the scroll child height based on total content
    scrollChild:SetHeight(math.abs(yOffset) + 20)
    
    -- Show the frame after creation
    browserFrame:Show()
end

-- ============================================================================
-- 7. Initialization & Events
-- ============================================================================
local function CreateMainFrame()
    local db = DevourerRotationHelperDB
    mainFrame = AF.CreateHeaderedFrame(UIParent, "DRH_MainFrame", "Devourer Rotation", 200, 100)
    AF.SetPoint(mainFrame, db.position.point, db.position.x, db.position.y)
    mainFrame:SetScale(db.scale)
    
    -- Create Edit Button in Header (positioned before close button)
    editButton = AF.CreateButton(mainFrame.header, "Edit", "accent", 40, 18)
    AF.SetPoint(editButton, "TOPRIGHT", mainFrame.header.closeBtn, "TOPLEFT", -4, -1)
    editButton:SetScript("OnClick", function()
        CreateBrowserFrame()
    end)
    
    -- Create Scale Slider in Header (compact horizontal slider)
    local scaleSlider = AF.CreateSlider(mainFrame.header, "", 80, 0.5, 2.0, 0.1, false, false)
    AF.SetPoint(scaleSlider, "TOPRIGHT", editButton, "TOPLEFT", -4, 0)
    scaleSlider:SetValue(db.scale)
    scaleSlider:SetEditBoxShown(false)  -- Hide the number display
    
    -- Set the callback using the proper method
    scaleSlider:SetAfterValueChanged(function(val)
        DevourerRotationHelperDB.scale = val
        mainFrame:SetScale(val)
    end)
    
    -- Set tooltip
    scaleSlider:SetTooltip("UI Scale", string.format("Current: %.1fx", db.scale))
    
    -- Adjust title positioning - just set left anchor, let it flow naturally
    AF.ClearPoints(mainFrame.header.text)
    AF.SetPoint(mainFrame.header.text, "LEFT", 8, 0)
    AF.SetPoint(mainFrame.header.text, "RIGHT", scaleSlider, "LEFT", -10, 0)
    
    rotationSorter = AF.CreateDragSorter(mainFrame, "DRH_Sorter", db.spacing, db.iconSize, db.iconSize, "HORIZONTAL")
    AF.SetPoint(rotationSorter, "TOPLEFT", 10, -25)  -- Reduced from -32 to minimize gap
    
    rotationSorter:SetCallback(function(newConfig) 
        DevourerRotationHelperDB.rotation = newConfig 
    end)

    mainFrame:HookScript("OnDragStop", function(self)
        local p, _, _, x, y = self:GetPoint()
        db.position = {point = p, x = x, y = y}
    end)
end

-- REMOVED: All slash commands as requested

AF.CreateBasicEventHandler(function(self, event, arg1)
    if event == "ADDON_LOADED" and arg1 == ADDON_NAME then
        DevourerRotationHelperDB = DevourerRotationHelperDB or {}
        for k, v in pairs(DEFAULTS) do
            if DevourerRotationHelperDB[k] == nil then DevourerRotationHelperDB[k] = v end
        end
        if #DevourerRotationHelperDB.rotation == 0 then
            DevourerRotationHelperDB.rotation = {{spellID = 473662, name = "Consume"}}
        end
        
    elseif event == "PLAYER_LOGIN" then
        -- Scan spellbook on login to populate available spells
        -- Note: If you learn new spells, use /drh scan or the Rescan button to update
        ScanPlayerSpellbook()
        
        CreateMainFrame()
        DRH.RebuildRotationDisplay()
        
        -- SIMPLIFIED: Minimap button with cleaner tooltip and right-click support
        AF.NewMinimapButton(ADDON_NAME, "Interface\\Icons\\Spell_Shadow_Shadesofdarkness", 
            DevourerRotationHelperDB.minimap, 
            function(button) 
                if button == "RightButton" then
                    CreateBrowserFrame()
                else
                    if mainFrame then
                        mainFrame:SetShown(not mainFrame:IsShown())
                    end
                end
            end, 
            {
                "Left-Click: Toggle Window", 
                "Right-Click: Edit Rotation"
            })

    elseif event == "UPDATE_BINDINGS" then
        wipe(keybindCache)
        DRH.RebuildRotationDisplay()
    end
end, "ADDON_LOADED", "PLAYER_LOGIN", "UPDATE_BINDINGS")