--------------------------------------------------------------------------------
-- Nanami-UI: Loot Display (拾取界面 + 已拾取提示)
--------------------------------------------------------------------------------

SFrames = SFrames or {}
SFrames.LootDisplay = SFrames.LootDisplay or {}

local LD = SFrames.LootDisplay

--------------------------------------------------------------------------------
-- Constants
--------------------------------------------------------------------------------
local ROW_HEIGHT   = 32
local ROW_WIDTH    = 180
local ROW_GAP      = 2
local ICON_SIZE    = 26
local TITLE_HEIGHT = 22

local ALERT_WIDTH    = 240
local ALERT_HEIGHT   = 32
local ALERT_GAP      = 3
local ALERT_ICON     = 24
local ALERT_FADE_DUR = 0.6
local ALERT_FLOAT    = 22
local ALERT_HOLD     = 3.5
local ALERT_STAGGER  = 0.25
local MAX_ALERTS     = 10

local QUALITY_COLORS = {
    [0] = { 0.62, 0.62, 0.62 },
    [1] = { 0.92, 0.92, 0.88 },
    [2] = { 0.12, 1.00, 0.00 },
    [3] = { 0.00, 0.44, 0.87 },
    [4] = { 0.64, 0.21, 0.93 },
    [5] = { 1.00, 0.50, 0.00 },
    [6] = { 0.90, 0.80, 0.50 },
}

-- Shared rounded backdrop template (matches rest of Nanami-UI)
local ROUND_BACKDROP = {
    bgFile   = "Interface\\Tooltips\\UI-Tooltip-Background",
    edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
    tile = true, tileSize = 16, edgeSize = 14,
    insets = { left = 3, right = 3, top = 3, bottom = 3 },
}

local ROUND_BACKDROP_SMALL = {
    bgFile   = "Interface\\Tooltips\\UI-Tooltip-Background",
    edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
    tile = true, tileSize = 16, edgeSize = 12,
    insets = { left = 2, right = 2, top = 2, bottom = 2 },
}

local ROUND_BACKDROP_SHADOW = {
    bgFile   = "Interface\\Tooltips\\UI-Tooltip-Background",
    edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
    tile = true, tileSize = 16, edgeSize = 16,
    insets = { left = 4, right = 4, top = 4, bottom = 4 },
}

local ICON_BACKDROP = {
    bgFile   = "Interface\\Tooltips\\UI-Tooltip-Background",
    edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
    tile = true, tileSize = 16, edgeSize = 10,
    insets = { left = 2, right = 2, top = 2, bottom = 2 },
}

local lootRows = {}
local activeAlerts = {}
local alertAnchor = nil
local alertPool = {}

--------------------------------------------------------------------------------
-- Helpers
--------------------------------------------------------------------------------
local function T()
    return SFrames.ActiveTheme or {}
end

local function Font()
    return (SFrames.GetFont and SFrames:GetFont()) or "Fonts\\ARIALN.TTF"
end

local function GetDB()
    if not SFramesDB then SFramesDB = {} end
    if type(SFramesDB.lootDisplay) ~= "table" then
        SFramesDB.lootDisplay = {
            enable = true,
            alertEnable = true,
            alertFadeDelay = ALERT_HOLD,
            scale = 1.0,
        }
    end
    return SFramesDB.lootDisplay
end

local function QColor(quality)
    local q = tonumber(quality) or 1
    local c = QUALITY_COLORS[q]
    if c then return c[1], c[2], c[3] end
    return 0.92, 0.92, 0.88
end

local function ColorHex(r, g, b)
    return string.format("%02x%02x%02x", r * 255, g * 255, b * 255)
end

local function GetItemTexture(itemIdOrLink)
    if not itemIdOrLink then return nil end
    local a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 = GetItemInfo(itemIdOrLink)
    if a10 and type(a10) == "string" then return a10 end
    if a9  and type(a9)  == "string" and string.find(a9, "Interface") then return a9 end
    if a8  and type(a8)  == "string" and string.find(a8, "Interface") then return a8 end
    return nil
end

local function ParseItemLink(link)
    if not link then return nil end
    local _, _, colorHex, itemId, itemName = string.find(link, "|c(%x+)|Hitem:(%d+).-|h%[(.-)%]|h|r")
    if not itemName then return nil end
    local id = tonumber(itemId) or 0
    local _, _, quality = GetItemInfo(id)
    return itemName, quality or 1, id
end

--------------------------------------------------------------------------------
-- ▸ LOOT FRAME (拾取窗口)
--------------------------------------------------------------------------------
local lootFrame = nil

local function CreateLootFrame()
    if lootFrame then return lootFrame end

    local th  = T()
    local bg  = th.panelBg     or { 0.06, 0.05, 0.09, 0.95 }
    local bd  = th.panelBorder or { 0.30, 0.25, 0.42, 0.90 }
    local acc = th.accent      or { 1, 0.5, 0.8, 0.98 }

    lootFrame = CreateFrame("Frame", "NanamiLootFrame", UIParent)
    lootFrame:SetFrameStrata("FULLSCREEN_DIALOG")
    lootFrame:SetFrameLevel(50)
    lootFrame:SetWidth(ROW_WIDTH + 14)
    lootFrame:SetHeight(TITLE_HEIGHT + 3 * (ROW_HEIGHT + ROW_GAP) + 10)
    lootFrame:SetPoint("TOPLEFT", UIParent, "TOPLEFT", 50, -200)
    lootFrame:SetClampedToScreen(true)
    lootFrame:SetMovable(true)
    lootFrame:EnableMouse(false)

    -- Shadow
    local shadow = CreateFrame("Frame", nil, lootFrame)
    shadow:SetPoint("TOPLEFT", lootFrame, "TOPLEFT", -5, 5)
    shadow:SetPoint("BOTTOMRIGHT", lootFrame, "BOTTOMRIGHT", 5, -5)
    shadow:SetFrameLevel(math.max(lootFrame:GetFrameLevel() - 1, 0))
    shadow:SetBackdrop(ROUND_BACKDROP_SHADOW)
    shadow:SetBackdropColor(0, 0, 0, 0.55)
    shadow:SetBackdropBorderColor(0, 0, 0, 0.40)
    shadow:EnableMouse(false)

    -- Background blocker: prevents clicks passing through to frames behind the loot window
    local blocker = CreateFrame("Frame", nil, lootFrame)
    blocker:SetAllPoints(lootFrame)
    blocker:SetFrameLevel(lootFrame:GetFrameLevel())
    blocker:EnableMouse(true)

    -- Main panel (rounded)
    lootFrame:SetBackdrop(ROUND_BACKDROP)
    lootFrame:SetBackdropColor(bg[1], bg[2], bg[3], bg[4] or 0.95)
    lootFrame:SetBackdropBorderColor(bd[1], bd[2], bd[3], bd[4] or 0.90)

    -- Top accent line
    local acLine = lootFrame:CreateTexture(nil, "ARTWORK")
    acLine:SetTexture("Interface\\Buttons\\WHITE8x8")
    acLine:SetHeight(2)
    acLine:SetPoint("TOPLEFT", lootFrame, "TOPLEFT", 5, -5)
    acLine:SetPoint("TOPRIGHT", lootFrame, "TOPRIGHT", -5, -5)
    acLine:SetVertexColor(acc[1], acc[2], acc[3], 0.65)

    -- Title bar: handles dragging the entire loot frame
    local titleBar = CreateFrame("Frame", nil, lootFrame)
    titleBar:SetHeight(TITLE_HEIGHT)
    titleBar:SetPoint("TOPLEFT", lootFrame, "TOPLEFT", 0, 0)
    titleBar:SetPoint("TOPRIGHT", lootFrame, "TOPRIGHT", 0, 0)
    titleBar:SetFrameLevel(lootFrame:GetFrameLevel() + 1)
    titleBar:EnableMouse(true)
    titleBar:RegisterForDrag("LeftButton")
    titleBar:SetScript("OnDragStart", function() lootFrame:StartMoving() end)
    titleBar:SetScript("OnDragStop", function() lootFrame:StopMovingOrSizing() end)

    -- Title text
    local titleFS = titleBar:CreateFontString(nil, "OVERLAY")
    titleFS:SetFont(Font(), 11, "OUTLINE")
    titleFS:SetPoint("TOPLEFT", lootFrame, "TOPLEFT", 10, -8)
    local tc = th.title or { 1, 0.88, 1 }
    titleFS:SetTextColor(tc[1], tc[2], tc[3], 0.95)
    titleFS:SetText("拾取")
    lootFrame._title = titleFS

    -- Close button
    local closeBtn = CreateFrame("Button", nil, lootFrame)
    closeBtn:SetWidth(18)
    closeBtn:SetHeight(18)
    closeBtn:SetPoint("TOPRIGHT", lootFrame, "TOPRIGHT", -5, -5)
    closeBtn:SetFrameLevel(lootFrame:GetFrameLevel() + 5)
    closeBtn:RegisterForClicks("LeftButtonUp")
    closeBtn:SetBackdrop(ROUND_BACKDROP_SMALL)
    local cbg = th.buttonBg or { 0.35, 0.08, 0.12, 0.85 }
    local cbd = th.buttonBorder or { 0.50, 0.18, 0.22, 0.80 }
    closeBtn:SetBackdropColor(cbg[1], cbg[2], cbg[3], cbg[4] or 0.85)
    closeBtn:SetBackdropBorderColor(cbd[1], cbd[2], cbd[3], cbd[4] or 0.80)
    local closeFS = closeBtn:CreateFontString(nil, "OVERLAY")
    closeFS:SetFont(Font(), 10, "OUTLINE")
    closeFS:SetPoint("CENTER", 0, 0)
    closeFS:SetText("×")
    closeFS:SetTextColor(0.9, 0.65, 0.65, 1)
    closeBtn:SetScript("OnClick", function() CloseLoot() end)
    closeBtn:SetScript("OnEnter", function()
        this:SetBackdropColor(0.55, 0.12, 0.15, 0.95)
        this:SetBackdropBorderColor(0.9, 0.30, 0.35, 1)
        closeFS:SetTextColor(1, 1, 1, 1)
    end)
    closeBtn:SetScript("OnLeave", function()
        this:SetBackdropColor(cbg[1], cbg[2], cbg[3], cbg[4] or 0.85)
        this:SetBackdropBorderColor(cbd[1], cbd[2], cbd[3], cbd[4] or 0.80)
        closeFS:SetTextColor(0.9, 0.65, 0.65, 1)
    end)

    lootFrame:Hide()
    return lootFrame
end

--------------------------------------------------------------------------------
-- Loot row
--------------------------------------------------------------------------------
local function CreateLootRow(parent, index)
    local th      = T()
    local slotBg  = th.slotBg     or { 0.07, 0.06, 0.10, 0.85 }
    local slotBd  = th.slotBorder or { 0.18, 0.16, 0.28, 0.60 }
    local hoverBd = th.slotHover  or { 0.38, 0.40, 0.90 }
    local acc     = th.accent     or { 1, 0.5, 0.8 }

    local row = CreateFrame("Button", "NanamiLootRow" .. index, parent)
    row:SetWidth(ROW_WIDTH)
    row:SetHeight(ROW_HEIGHT)
    row:SetFrameLevel(parent:GetFrameLevel() + 2)
    row:RegisterForClicks("LeftButtonUp")

    row:SetBackdrop(ROUND_BACKDROP_SMALL)
    row:SetBackdropColor(slotBg[1], slotBg[2], slotBg[3], slotBg[4] or 0.85)
    row:SetBackdropBorderColor(slotBd[1], slotBd[2], slotBd[3], slotBd[4] or 0.60)

    -- Left quality accent bar
    local qBar = row:CreateTexture(nil, "OVERLAY")
    qBar:SetTexture("Interface\\Buttons\\WHITE8X8")
    qBar:SetWidth(2)
    qBar:SetPoint("TOPLEFT", row, "TOPLEFT", 3, -3)
    qBar:SetPoint("BOTTOMLEFT", row, "BOTTOMLEFT", 3, 3)
    qBar:SetVertexColor(1, 1, 1, 0.6)
    row.qBar = qBar

    -- Icon frame (rounded border)
    local iconFrame = CreateFrame("Frame", nil, row)
    iconFrame:SetWidth(ICON_SIZE + 4)
    iconFrame:SetHeight(ICON_SIZE + 4)
    iconFrame:SetPoint("LEFT", row, "LEFT", 7, 0)
    iconFrame:SetFrameLevel(row:GetFrameLevel() + 1)
    iconFrame:SetBackdrop(ICON_BACKDROP)
    iconFrame:SetBackdropColor(0, 0, 0, 0.60)
    iconFrame:SetBackdropBorderColor(slotBd[1], slotBd[2], slotBd[3], 0.70)
    iconFrame:EnableMouse(false)
    row.iconFrame = iconFrame

    local icon = iconFrame:CreateTexture(nil, "ARTWORK")
    icon:SetPoint("TOPLEFT", iconFrame, "TOPLEFT", 2, -2)
    icon:SetPoint("BOTTOMRIGHT", iconFrame, "BOTTOMRIGHT", -2, 2)
    icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
    row.icon = icon

    -- Name
    local nameFS = row:CreateFontString(nil, "OVERLAY")
    nameFS:SetFont(Font(), 10, "OUTLINE")
    nameFS:SetPoint("LEFT", iconFrame, "RIGHT", 4, 0)
    nameFS:SetPoint("RIGHT", row, "RIGHT", -6, 0)
    nameFS:SetJustifyH("LEFT")
    row.nameFS = nameFS

    -- Count (bottom-right of icon)
    local countFS = row:CreateFontString(nil, "OVERLAY")
    countFS:SetFont(Font(), 8, "OUTLINE")
    countFS:SetPoint("BOTTOMRIGHT", iconFrame, "BOTTOMRIGHT", -2, 2)
    countFS:SetJustifyH("RIGHT")
    countFS:SetTextColor(1, 1, 1, 0.95)
    row.countFS = countFS

    row._slotBg = slotBg
    row._slotBd = slotBd
    row._hoverBd = hoverBd
    row._acc = acc
    row:EnableMouse(false)

    row:Hide()
    return row
end

--------------------------------------------------------------------------------
-- Update loot frame
--------------------------------------------------------------------------------
local function UpdateLootFrame()
    local db = GetDB()
    if not db.enable then return end

    local numItems = GetNumLootItems()
    if not numItems or numItems == 0 then
        if lootFrame then lootFrame:Hide() end
        return
    end

    CreateLootFrame()

    local validSlots = {}
    for i = 1, numItems do
        local texture, itemName, quantity, quality = GetLootSlotInfo(i)
        if texture then
            table.insert(validSlots, i)
        end
    end

    local numValid = table.getn(validSlots)
    if numValid == 0 then
        if lootFrame then lootFrame:Hide() end
        return
    end

    local totalH = TITLE_HEIGHT + (numValid * (ROW_HEIGHT + ROW_GAP)) + 10
    lootFrame:SetWidth(ROW_WIDTH + 14)
    lootFrame:SetHeight(totalH)
    lootFrame:SetScale(db.scale or 1.0)

    while table.getn(lootRows) < numValid do
        local idx = table.getn(lootRows) + 1
        lootRows[idx] = CreateLootRow(lootFrame, idx)
    end

    for i = 1, table.getn(lootRows) do lootRows[i]:Hide() end

    for displayIdx = 1, numValid do
        local slotIdx = validSlots[displayIdx]
        local row = lootRows[displayIdx]
        if not row then break end

        row:ClearAllPoints()
        row:SetPoint("TOPLEFT", lootFrame, "TOPLEFT", 7, -(TITLE_HEIGHT + 2 + (displayIdx - 1) * (ROW_HEIGHT + ROW_GAP)))
        row:SetWidth(ROW_WIDTH)

        local texture, itemName, quantity, quality = GetLootSlotInfo(slotIdx)
        row.slotIndex = slotIdx

        row.icon:SetTexture(texture or "Interface\\Icons\\INV_Misc_QuestionMark")

        local r, g, b = QColor(quality)
        row._qualColor = { r, g, b }
        row.qBar:SetVertexColor(r, g, b, 0.90)
        row.iconFrame:SetBackdropBorderColor(r, g, b, 0.65)
        row:SetBackdropBorderColor(r, g, b, 0.30)

        if itemName then
            row.nameFS:SetText("|cff" .. ColorHex(r, g, b) .. itemName .. "|r")
        else
            row.nameFS:SetText("")
        end

        if quantity and quantity > 1 then
            row.countFS:SetText(tostring(quantity))
        else
            row.countFS:SetText("")
        end

        row:Show()

        -- Overlay the Blizzard LootButton on top for click handling
        local maxBtns = LOOTFRAME_NUMITEMS or 4
        if displayIdx <= maxBtns then
            local blizzBtn = _G["LootButton" .. displayIdx]
            if blizzBtn then
                blizzBtn:SetID(slotIdx)
                blizzBtn:SetParent(lootFrame)
                blizzBtn:ClearAllPoints()
                blizzBtn:SetAllPoints(row)
                blizzBtn:SetFrameStrata("FULLSCREEN_DIALOG")
                blizzBtn:SetFrameLevel(row:GetFrameLevel() + 10)
                blizzBtn:SetAlpha(0)
                blizzBtn:EnableMouse(true)
                blizzBtn:Show()

                local rowRef = row
                blizzBtn._nanamiRow = rowRef
                blizzBtn:SetScript("OnEnter", function()
                    local rw = this._nanamiRow
                    if rw and rw._acc then
                        rw:SetBackdropBorderColor(rw._acc[1], rw._acc[2], rw._acc[3], 0.85)
                        rw:SetBackdropColor(rw._hoverBd[1], rw._hoverBd[2], rw._hoverBd[3], 0.35)
                    end
                    if rw and rw.slotIndex then
                        GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
                        if LootSlotIsItem(rw.slotIndex) then
                            GameTooltip:SetLootItem(rw.slotIndex)
                        else
                            local t, n = GetLootSlotInfo(rw.slotIndex)
                            if n then GameTooltip:SetText(n) end
                        end
                        GameTooltip:Show()
                    end
                end)
                blizzBtn:SetScript("OnLeave", function()
                    local rw = this._nanamiRow
                    if rw and rw._slotBg then
                        rw:SetBackdropColor(rw._slotBg[1], rw._slotBg[2], rw._slotBg[3], rw._slotBg[4] or 0.85)
                        if rw._qualColor then
                            rw:SetBackdropBorderColor(rw._qualColor[1], rw._qualColor[2], rw._qualColor[3], 0.35)
                        else
                            rw:SetBackdropBorderColor(rw._slotBd[1], rw._slotBd[2], rw._slotBd[3], rw._slotBd[4] or 0.60)
                        end
                    end
                    GameTooltip:Hide()
                end)
            end
        end
    end

    -- Hide unused Blizzard buttons
    local maxBtns = LOOTFRAME_NUMITEMS or 4
    for i = numValid + 1, maxBtns do
        local blizzBtn = _G["LootButton" .. i]
        if blizzBtn then blizzBtn:Hide() end
    end

    -- Position: use saved mover position if exists, otherwise follow cursor
    if not lootFrame._posApplied then
        local hasSaved = false
        if SFrames.Movers and SFrames.Movers.ApplyPosition then
            hasSaved = SFrames.Movers:ApplyPosition("LootFrame", lootFrame,
                "TOPLEFT", "UIParent", "TOPLEFT", 50, -200)
        end
        if hasSaved then
            lootFrame._posApplied = true
        end
    end
    if not lootFrame._posApplied then
        local cx, cy = GetCursorPosition()
        local uiS = UIParent:GetEffectiveScale()
        lootFrame:ClearAllPoints()
        lootFrame:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", cx / uiS - 30, cy / uiS + 16)
    end

    lootFrame:Show()
end

local function CloseLootFrame()
    -- Return Blizzard buttons to LootFrame
    local maxBtns = LOOTFRAME_NUMITEMS or 4
    for i = 1, maxBtns do
        local blizzBtn = _G["LootButton" .. i]
        if blizzBtn and LootFrame then
            blizzBtn:SetParent(LootFrame)
            blizzBtn:SetAlpha(1)
            blizzBtn:Hide()
            blizzBtn._nanamiRow = nil
        end
    end
    if lootFrame then lootFrame:Hide() end
    for i = 1, table.getn(lootRows) do lootRows[i]:Hide() end
end

--------------------------------------------------------------------------------
-- ▸ LOOT ALERTS (已拾取提示)
--------------------------------------------------------------------------------
local function CreateAlertAnchor()
    if alertAnchor then return alertAnchor end

    alertAnchor = CreateFrame("Frame", "NanamiLootAlertAnchor", UIParent)
    alertAnchor:SetWidth(ALERT_WIDTH)
    alertAnchor:SetHeight(ALERT_HEIGHT)
    alertAnchor:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", 40, 340)
    alertAnchor:EnableMouse(false)

    if SFrames.Movers and SFrames.Movers.ApplyPosition then
        SFrames.Movers:ApplyPosition("LootAlert", alertAnchor,
            "BOTTOMLEFT", "UIParent", "BOTTOMLEFT", 40, 340)
    end
    return alertAnchor
end

local function CreateAlertFrame()
    local th  = T()
    local idx = table.getn(alertPool) + 1
    local bg  = th.panelBg     or { 0.06, 0.05, 0.09, 0.92 }
    local bd  = th.panelBorder or { 0.30, 0.25, 0.42, 0.80 }

    local f = CreateFrame("Frame", "NanamiLootAlert" .. idx, UIParent)
    f:SetFrameStrata("HIGH")
    f:SetFrameLevel(20)
    f:SetWidth(ALERT_WIDTH)
    f:SetHeight(ALERT_HEIGHT)

    -- Rounded backdrop matching UI theme
    f:SetBackdrop(ROUND_BACKDROP_SMALL)
    f:SetBackdropColor(bg[1], bg[2], bg[3], bg[4] or 0.92)
    f:SetBackdropBorderColor(bd[1], bd[2], bd[3], bd[4] or 0.80)

    -- Left quality accent bar
    local qBar = f:CreateTexture(nil, "OVERLAY")
    qBar:SetTexture("Interface\\Buttons\\WHITE8X8")
    qBar:SetWidth(2)
    qBar:SetPoint("TOPLEFT", f, "TOPLEFT", 3, -3)
    qBar:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", 3, 3)
    qBar:SetVertexColor(1, 1, 1, 0.7)
    f.qBar = qBar

    -- Icon with rounded border
    local iconFrame = CreateFrame("Frame", nil, f)
    iconFrame:SetWidth(ALERT_ICON + 4)
    iconFrame:SetHeight(ALERT_ICON + 4)
    iconFrame:SetPoint("LEFT", f, "LEFT", 7, 0)
    iconFrame:SetFrameLevel(f:GetFrameLevel() + 1)
    iconFrame:SetBackdrop(ICON_BACKDROP)
    iconFrame:SetBackdropColor(0, 0, 0, 0.55)
    iconFrame:SetBackdropBorderColor(0.25, 0.22, 0.30, 0.6)
    f.iconFrame = iconFrame

    local icon = iconFrame:CreateTexture(nil, "ARTWORK")
    icon:SetPoint("TOPLEFT", iconFrame, "TOPLEFT", 2, -2)
    icon:SetPoint("BOTTOMRIGHT", iconFrame, "BOTTOMRIGHT", -2, 2)
    icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
    f.icon = icon

    -- Name
    local nameFS = f:CreateFontString(nil, "OVERLAY")
    nameFS:SetFont(Font(), 10, "OUTLINE")
    nameFS:SetPoint("LEFT", iconFrame, "RIGHT", 5, 0)
    nameFS:SetPoint("RIGHT", f, "RIGHT", -30, 0)
    nameFS:SetJustifyH("LEFT")
    f.nameFS = nameFS

    -- Count (right side)
    local countFS = f:CreateFontString(nil, "OVERLAY")
    countFS:SetFont(Font(), 10, "OUTLINE")
    countFS:SetPoint("RIGHT", f, "RIGHT", -6, 0)
    countFS:SetJustifyH("RIGHT")
    local dim = th.dimText or { 0.55, 0.55, 0.60 }
    countFS:SetTextColor(dim[1], dim[2], dim[3], 0.95)
    f.countFS = countFS

    f:Hide()
    table.insert(alertPool, f)
    return f
end

local function GetAlertFrame()
    for i = 1, table.getn(alertPool) do
        if not alertPool[i]._inUse then return alertPool[i] end
    end
    return CreateAlertFrame()
end

local function LayoutAlerts()
    CreateAlertAnchor()
    for i = 1, table.getn(activeAlerts) do
        local af = activeAlerts[i]
        if af._fadeState ~= "fading" then
            af:ClearAllPoints()
            af:SetPoint("BOTTOMLEFT", alertAnchor, "BOTTOMLEFT", 0, (i - 1) * (ALERT_HEIGHT + ALERT_GAP))
        end
    end
end

local function RemoveAlert(frame)
    frame._inUse = false
    frame:SetAlpha(0)
    frame:Hide()
    frame:SetScript("OnUpdate", nil)
    local newActive = {}
    for i = 1, table.getn(activeAlerts) do
        if activeAlerts[i] ~= frame then
            table.insert(newActive, activeAlerts[i])
        end
    end
    activeAlerts = newActive
    LayoutAlerts()
end

local function StartAlertFade(frame, delay)
    frame._fadeState   = "waiting"
    frame._fadeElapsed = 0
    frame._fadeDelay   = delay

    frame:SetScript("OnUpdate", function()
        this._fadeElapsed = (this._fadeElapsed or 0) + arg1

        if this._fadeState == "waiting" then
            if this._fadeElapsed >= this._fadeDelay then
                this._fadeState = "fading"
                this._fadeElapsed = 0
                this._baseY = 0
                for idx = 1, table.getn(activeAlerts) do
                    if activeAlerts[idx] == this then
                        this._baseY = (idx - 1) * (ALERT_HEIGHT + ALERT_GAP)
                        break
                    end
                end
            end
        elseif this._fadeState == "fading" then
            local p = this._fadeElapsed / ALERT_FADE_DUR
            if p >= 1 then
                RemoveAlert(this)
            else
                this:SetAlpha(1 - p)
                this:ClearAllPoints()
                this:SetPoint("BOTTOMLEFT", alertAnchor, "BOTTOMLEFT",
                    0, this._baseY + p * ALERT_FLOAT)
            end
        end
    end)
end

local function PruneAlerts()
    while table.getn(activeAlerts) > MAX_ALERTS do
        RemoveAlert(activeAlerts[1])
    end
end

local function ShowLootAlert(texture, name, quality, quantity, link)
    local db = GetDB()
    if not db.alertEnable then return end

    for i = 1, table.getn(activeAlerts) do
        local af = activeAlerts[i]
        if af._itemName == name and af._fadeState == "waiting" then
            af._quantity = (af._quantity or 1) + (quantity or 1)
            if af._quantity > 1 then
                af.countFS:SetText("x" .. af._quantity)
            end
            af._fadeElapsed = 0
            return
        end
    end

    PruneAlerts()
    CreateAlertAnchor()

    local f = GetAlertFrame()
    f._inUse    = true
    f._itemName = name
    f._quantity = quantity or 1
    f._link     = link

    -- Set icon texture
    local iconTex = texture or "Interface\\Icons\\INV_Misc_QuestionMark"
    f.icon:SetTexture(iconTex)

    local r, g, b = QColor(quality)
    f.qBar:SetVertexColor(r, g, b, 0.90)
    f.iconFrame:SetBackdropBorderColor(r, g, b, 0.60)

    f.nameFS:SetText("|cff" .. ColorHex(r, g, b) .. (name or "???") .. "|r")

    if f._quantity > 1 then
        f.countFS:SetText("x" .. f._quantity)
    else
        f.countFS:SetText("")
    end

    -- Re-apply theme backdrop colors (pool reuse)
    local th = T()
    local bg = th.panelBg or { 0.06, 0.05, 0.09, 0.92 }
    local bd = th.panelBorder or { 0.30, 0.25, 0.42, 0.80 }
    f:SetBackdropColor(bg[1], bg[2], bg[3], bg[4] or 0.92)
    f:SetBackdropBorderColor(bd[1], bd[2], bd[3], bd[4] or 0.80)

    f:SetAlpha(1)
    f:Show()

    table.insert(activeAlerts, f)
    LayoutAlerts()

    local hold = db.alertFadeDelay or ALERT_HOLD
    local stagger = table.getn(activeAlerts) * ALERT_STAGGER
    StartAlertFade(f, hold + stagger)
end

--------------------------------------------------------------------------------
-- Parse CHAT_MSG_LOOT
--------------------------------------------------------------------------------
local function ParseLootMessage(msg)
    if not msg then return end

    local _, _, link, countStr = string.find(msg, "(|c%x+|Hitem.-%[.-%]|h|r)x(%d+)")
    if not link then
        _, _, link = string.find(msg, "(|c%x+|Hitem.-%[.-%]|h|r)")
    end

    if link then
        local itemName, quality, itemId = ParseItemLink(link)
        if itemName then
            local count = tonumber(countStr) or 1
            -- Try full link first (most reliable), then itemId, then itemString
            local tex = GetItemTexture(link)
            if not tex and itemId and itemId > 0 then
                tex = GetItemTexture(itemId)
            end
            if not tex and itemId and itemId > 0 then
                tex = GetItemTexture("item:" .. itemId .. ":0:0:0")
            end
            ShowLootAlert(tex, itemName, quality, count, link)
        end
        return
    end

    -- Money
    local isMoney = false
    if string.find(msg, "铜") or string.find(msg, "银") or string.find(msg, "金")
       or string.find(msg, "[Cc]opper") or string.find(msg, "[Ss]ilver") or string.find(msg, "[Gg]old") then
        if string.find(msg, "拾取") or string.find(msg, "获得") or string.find(msg, "loot") or string.find(msg, "receive") then
            isMoney = true
        end
    end

    if isMoney then
        local cleanMsg = string.gsub(msg, "|c%x+", "")
        cleanMsg = string.gsub(cleanMsg, "|r", "")
        local _, _, moneyPart = string.find(cleanMsg, "[：:]%s*(.+)$")
        if not moneyPart then
            _, _, moneyPart = string.find(cleanMsg, "loot%s+(.+)$")
        end
        if not moneyPart then
            _, _, moneyPart = string.find(cleanMsg, "获得了?%s*(.+)$")
        end
        if moneyPart then
            moneyPart = string.gsub(moneyPart, "[%.。]+$", "")
            ShowLootAlert("Interface\\Icons\\INV_Misc_Coin_01", moneyPart, 1, 1, nil)
        end
    end
end

--------------------------------------------------------------------------------
-- Initialize
--------------------------------------------------------------------------------
function LD:Initialize()
    local db = GetDB()
    if not db.enable then return end

    CreateLootFrame()
    CreateAlertAnchor()

    -- Apply saved positions so frames have valid coordinates for the Mover system
    if SFrames.Movers and SFrames.Movers.ApplyPosition then
        local applied = SFrames.Movers:ApplyPosition("LootFrame", lootFrame,
            "TOPLEFT", "UIParent", "TOPLEFT", 50, -200)
        if applied then lootFrame._posApplied = true end

        SFrames.Movers:ApplyPosition("LootAlert", alertAnchor,
            "BOTTOMLEFT", "UIParent", "BOTTOMLEFT", 40, 340)
    end

    if SFrames.Movers and SFrames.Movers.RegisterMover then
        SFrames.Movers:RegisterMover("LootFrame", lootFrame, "拾取窗口",
            "TOPLEFT", "UIParent", "TOPLEFT", 50, -200)
        SFrames.Movers:RegisterMover("LootAlert", alertAnchor, "已拾取提示",
            "BOTTOMLEFT", "UIParent", "BOTTOMLEFT", 40, 340)
    end

    SFrames:RegisterEvent("LOOT_OPENED", function()
        if GetDB().enable then UpdateLootFrame() end
    end)

    SFrames:RegisterEvent("LOOT_SLOT_CLEARED", function()
        if GetDB().enable and lootFrame and lootFrame:IsShown() then
            UpdateLootFrame()
        end
    end)

    SFrames:RegisterEvent("LOOT_CLOSED", function()
        CloseLootFrame()
    end)

    SFrames:RegisterEvent("CHAT_MSG_LOOT", function()
        local playerName = UnitName("player")
        if not playerName then return end
        local msg = arg1 or ""
        if string.find(msg, playerName) or string.find(msg, "你获得") or string.find(msg, "你拾取") or string.find(msg, "You receive") then
            ParseLootMessage(msg)
        end
    end)

    local function HideBlizzardLoot()
        if LootFrame then
            LootFrame:EnableMouse(false)
            LootFrame:SetAlpha(0)
            LootFrame:ClearAllPoints()
            LootFrame:SetPoint("TOPLEFT", UIParent, "TOPLEFT", -10000, 10000)
            local origShow = LootFrame.Show
            LootFrame.Show = function(self)
                origShow(self)
                self:EnableMouse(false)
                self:SetAlpha(0)
                self:ClearAllPoints()
                self:SetPoint("TOPLEFT", UIParent, "TOPLEFT", -10000, 10000)
            end
        end
    end
    HideBlizzardLoot()

    local lootHook = CreateFrame("Frame")
    lootHook:RegisterEvent("ADDON_LOADED")
    lootHook:SetScript("OnEvent", function()
        if arg1 == "Blizzard_Loot" then HideBlizzardLoot() end
    end)
end
