local addonName, TOAST = ...

local TRACK_W = 4
local THUMB_MIN_H = 30
local WHEEL_STEP = 45
local SCROLL_SPEED = 10

function TOAST.CreateCustomScrollbar(scrollFrame, scrollChild)
    local track = CreateFrame("Frame", nil, scrollFrame)
    track:SetWidth(TRACK_W)
    track:SetPoint("TOPLEFT", scrollFrame, "TOPRIGHT", 4, 0)
    track:SetPoint("BOTTOMLEFT", scrollFrame, "BOTTOMRIGHT", 4, 0)

    local trackBg = track:CreateTexture(nil, "BACKGROUND")
    trackBg:SetAllPoints()
    trackBg:SetColorTexture(1, 1, 1, 0.03)

    local thumb = CreateFrame("Button", nil, track)
    thumb:SetWidth(TRACK_W)
    thumb:SetPoint("TOP", track, "TOP", 0, 0)

    local thumbBg = thumb:CreateTexture(nil, "OVERLAY")
    thumbBg:SetAllPoints()
    thumbBg:SetColorTexture(1, 1, 1, 0.25)

    thumb:SetScript("OnEnter", function() thumbBg:SetColorTexture(1, 1, 1, 0.4) end)
    thumb:SetScript("OnLeave", function() thumbBg:SetColorTexture(1, 1, 1, 0.25) end)

    local currentScroll = 0
    local targetScroll = 0
    local dragging = false
    local dragStartY, dragStartScroll

    local function UpdateThumb()
        local maxScroll = scrollFrame:GetVerticalScrollRange()
        if not maxScroll or maxScroll <= 0 then
            track:Hide()
            return
        end
        track:Show()

        local trackH = track:GetHeight()
        local visibleH = scrollFrame:GetHeight()
        local ratio = visibleH / (visibleH + maxScroll)
        local thumbH = math.max(THUMB_MIN_H, trackH * ratio)
        thumb:SetHeight(thumbH)

        local scrollRatio = currentScroll / maxScroll
        local offset = scrollRatio * (trackH - thumbH)
        thumb:ClearAllPoints()
        thumb:SetPoint("TOP", track, "TOP", 0, -offset)
    end

    -- currentScroll/targetScroll stay fractional for a smooth easing curve,
    -- but the scroll offset actually handed to the frame is snapped to whole
    -- pixels so row content (icons especially) doesn't shimmer mid-animation.
    local function ApplyScroll(value)
        scrollFrame:SetVerticalScroll(math.floor(value + 0.5))
    end

    local updater = CreateFrame("Frame")
    updater:Hide()
    updater:SetScript("OnUpdate", function(self, elapsed)
        local diff = targetScroll - currentScroll
        if math.abs(diff) < 0.5 then
            currentScroll = targetScroll
            ApplyScroll(currentScroll)
            UpdateThumb()
            self:Hide()
            return
        end
        currentScroll = currentScroll + diff * math.min(1, elapsed * SCROLL_SPEED)
        ApplyScroll(currentScroll)
        UpdateThumb()
    end)

    local function SetTargetScroll(value)
        local maxScroll = scrollFrame:GetVerticalScrollRange() or 0
        targetScroll = math.max(0, math.min(maxScroll, value))
        updater:Show()
    end

    scrollFrame:EnableMouseWheel(true)
    scrollFrame:SetScript("OnMouseWheel", function(self, delta)
        SetTargetScroll(targetScroll - delta * WHEEL_STEP)
    end)

    thumb:SetScript("OnMouseDown", function(self, button)
        if button ~= "LeftButton" then return end
        updater:Hide()
        dragging = true
        dragStartY = select(2, GetCursorPosition())
        dragStartScroll = currentScroll
    end)

    thumb:SetScript("OnMouseUp", function()
        dragging = false
    end)

    thumb:SetScript("OnUpdate", function(self, elapsed)
        if not dragging then return end
        local _, y = GetCursorPosition()
        local scale = track:GetEffectiveScale()
        local deltaY = (dragStartY - y) / scale

        local maxScroll = scrollFrame:GetVerticalScrollRange()
        local trackH = track:GetHeight()
        local thumbH = thumb:GetHeight()
        if not maxScroll or maxScroll <= 0 or trackH <= thumbH then return end

        local scrollDelta = deltaY * (maxScroll / (trackH - thumbH))
        currentScroll = math.max(0, math.min(maxScroll, dragStartScroll + scrollDelta))
        targetScroll = currentScroll
        ApplyScroll(currentScroll)
        UpdateThumb()
    end)

    scrollFrame:SetScript("OnScrollRangeChanged", function()
        currentScroll = scrollFrame:GetVerticalScroll()
        targetScroll = currentScroll
        UpdateThumb()
    end)

    local function ScrollToTop()
        currentScroll = 0
        targetScroll = 0
        updater:Hide()
        scrollFrame:SetVerticalScroll(0)
        UpdateThumb()
    end

    UpdateThumb()

    return track, thumb, ScrollToTop
end

function TOAST.CreateCloseButton(parent, onClickFn)
    local btn = CreateFrame("Button", nil, parent)
    btn:SetSize(24, 24)
    btn:SetPoint("TOPRIGHT", parent, "TOPRIGHT", -8, -8)
    btn:SetFrameLevel(parent:GetFrameLevel() + 5)

    local label = btn:CreateFontString(nil, "OVERLAY")
    label:SetFont(TOAST.FONT_PATH, 16, "")
    label:SetPoint("CENTER", 0, 1)
    label:SetText("\195\151")  -- unicode multiply sign, niet x
    label:SetTextColor(1, 1, 1, 0.4)

    btn:SetScript("OnEnter", function()
        label:SetTextColor(1, 1, 1, 0.8)
    end)
    btn:SetScript("OnLeave", function()
        label:SetTextColor(1, 1, 1, 0.4)
    end)
    btn:SetScript("OnClick", onClickFn)

    return btn
end

-- Split gold divider with a centered anchor medallion: left line, medallion,
-- right line, spanning [leftX, rightX] at vertical offset y (all relative to
-- parent's TOPLEFT). Shared by the leaderboard and dashboard headers so both
-- speak the same nautical divider language.
--
-- options:
--   medallionSize (default 32), gap (default 6) between line and medallion,
--   lineHeight (default 2, the leaderboard's original thickness — shared so
--   every divider using this helper is guaranteed the same thickness),
--   lineColor (default TOAST gold), lineAlpha (default 1),
--   aboveFrame — if set, the divider is leveled above this frame so a banner
--   texture or card background can't draw over the medallion.
function TOAST.CreateAnchorDivider(parent, leftX, rightX, y, options)
    options = options or {}
    local medallionSize = options.medallionSize or 32
    local gap = options.gap or 6
    local lineHeight = options.lineHeight or 2
    local lineColor = options.lineColor or { 0.88, 0.75, 0.36 }
    local lineAlpha = options.lineAlpha or 1

    local dividerFrame = CreateFrame("Frame", nil, parent)
    dividerFrame:SetAllPoints(parent)
    if options.aboveFrame then
        dividerFrame:SetFrameLevel(options.aboveFrame:GetFrameLevel() + 1)
    end

    local medallion = dividerFrame:CreateTexture(nil, "OVERLAY")
    medallion:SetTexture("Interface\\AddOns\\TOAST\\media\\dividers\\anchor_medallion.tga")
    medallion:SetSize(medallionSize, medallionSize)
    medallion:SetPoint("CENTER", dividerFrame, "TOPLEFT", (leftX + rightX) / 2, y)

    local leftLine = dividerFrame:CreateTexture(nil, "ARTWORK")
    leftLine:SetColorTexture(lineColor[1], lineColor[2], lineColor[3], lineAlpha)
    leftLine:SetHeight(lineHeight)
    leftLine:SetPoint("LEFT", dividerFrame, "TOPLEFT", leftX, y)
    leftLine:SetPoint("RIGHT", medallion, "LEFT", -gap, 0)

    local rightLine = dividerFrame:CreateTexture(nil, "ARTWORK")
    rightLine:SetColorTexture(lineColor[1], lineColor[2], lineColor[3], lineAlpha)
    rightLine:SetHeight(lineHeight)
    rightLine:SetPoint("LEFT", medallion, "RIGHT", gap, 0)
    rightLine:SetPoint("RIGHT", dividerFrame, "TOPLEFT", rightX, y)

    return dividerFrame, medallion, leftLine, rightLine
end
