local ADDON_NAME, RPAL = ...

-- Shared RPAL cursor tooltip -------------------------------------------------
-- This intentionally lives in its own module so the main UI chunk does not
-- accumulate more file-scope locals (WoW's Lua compiler has a 200-local cap).

local STAR="Interface\\AddOns\\ODYN\\Textures\\Talent\\atlas_stars.tga"
local SPARK="Interface\\AddOns\\ODYN\\Textures\\Talent\\sparkle.tga"
local GOLD={0.92,0.72,0.34}
local PALE={0.93,0.90,0.84}
local MUTED={0.62,0.61,0.68}
local tooltip
local activeConfig

local function Color(c,fallback)
    c=c or fallback or GOLD
    return c[1] or 1,c[2] or 1,c[3] or 1,c[4] or 1
end

local function Text(parent,size,color,font)
    local fs=parent:CreateFontString(nil,"OVERLAY")
    local baseSize=size or 10
    local fontPath=font or "Fonts\\FRIZQT__.TTF"
    fs:SetFont(fontPath,RPAL.GetScaledFontSize and RPAL.GetScaledFontSize(baseSize) or baseSize,"OUTLINE")
    if RPAL.RegisterScalableFontObject then RPAL.RegisterScalableFontObject(fs,fontPath,baseSize,"OUTLINE") end
    fs:SetTextColor(Color(color,PALE))
    fs:SetShadowColor(0,0,0,0.95)
    fs:SetShadowOffset(1,-1)
    fs:SetJustifyH("LEFT")
    fs:SetJustifyV("TOP")
    fs:SetWordWrap(true)
    return fs
end

local function Estimate(text,widthChars,lineHeight,minHeight)
    text=tostring(text or "")
    if text=="" then return 0 end
    local scale=RPAL.GetFontScale and RPAL.GetFontScale() or 1
    local effectiveChars=math.max(20,(widthChars or 48)/math.max(0.90,scale))
    local effectiveLine=(lineHeight or 13)*scale
    local lines=0
    for line in (text.."\n"):gmatch("(.-)\n") do
        lines=lines+math.max(1,math.ceil(math.max(1,#line)/effectiveChars))
    end
    return math.max((minHeight or lineHeight or 13)*scale,lines*effectiveLine)
end

local function EnsureTooltip()
    if tooltip then return tooltip end
    local f=CreateFrame("Frame","RPAL_PremiumCursorTooltip",UIParent,"BackdropTemplate")
    tooltip=f
    f:SetFrameStrata("TOOLTIP")
    f:SetFrameLevel(11000)
    f:SetToplevel(true)
    f:SetClampedToScreen(true)
    f:EnableMouse(false)
    f:SetSize(380,180)
    f:SetBackdrop({
        bgFile="Interface\\Buttons\\WHITE8X8",
        edgeFile="Interface\\Tooltips\\UI-Tooltip-Border",
        tile=false,tileSize=16,edgeSize=16,
        insets={left=4,right=4,top=4,bottom=4},
    })
    f:SetBackdropColor(0.018,0.014,0.034,0.992)
    f:SetBackdropBorderColor(GOLD[1],GOLD[2],GOLD[3],0.98)

    local stars=f:CreateTexture(nil,"BACKGROUND",nil,-2)
    stars:SetTexture(STAR);stars:SetAllPoints();stars:SetAlpha(0.15)
    f.stars=stars

    local wash=f:CreateTexture(nil,"BACKGROUND",nil,-1)
    wash:SetTexture(SPARK);wash:SetBlendMode("ADD")
    wash:SetPoint("TOPRIGHT",18,18);wash:SetSize(150,150);wash:SetAlpha(0.13)
    f.wash=wash

    f.eyebrow=Text(f,8,MUTED)
    f.eyebrow:SetPoint("TOPLEFT",17,-14);f.eyebrow:SetPoint("RIGHT",-17,0)

    f.title=Text(f,16,PALE,"Fonts\\FRIZQT__.TTF")
    f.title:SetPoint("TOPLEFT",17,-31);f.title:SetPoint("RIGHT",-17,0)

    f.rule=f:CreateTexture(nil,"ARTWORK")
    f.rule:SetTexture("Interface\\Buttons\\WHITE8X8")
    f.rule:SetHeight(1);f.rule:SetPoint("TOPLEFT",17,-58);f.rule:SetPoint("TOPRIGHT",-17,-58)

    f.body=Text(f,10,PALE)
    f.body:SetPoint("TOPLEFT",17,-70);f.body:SetPoint("RIGHT",-17,0)

    f.sectionLabel=Text(f,8,GOLD)
    f.section=Text(f,10,GOLD)

    f.detailLabel=Text(f,8,GOLD)
    f.detail=Text(f,9,PALE)

    f.footerRule=f:CreateTexture(nil,"ARTWORK")
    f.footerRule:SetTexture("Interface\\Buttons\\WHITE8X8");f.footerRule:SetHeight(1)
    f.footer=Text(f,8,MUTED)

    f:Hide()
    return f
end

local function PositionTooltip()
    local f=tooltip
    if not f or not f:IsShown() then return end
    local parentScale=UIParent:GetEffectiveScale() or 1
    local x,y=GetCursorPosition()
    x=(x/parentScale)+22
    y=(y/parentScale)+22
    f:ClearAllPoints()
    -- Bottom-left anchored to the cursor means the card grows into the
    -- cursor's upper-right quadrant. SetClampedToScreen protects edge cases.
    f:SetPoint("BOTTOMLEFT",UIParent,"BOTTOMLEFT",x,y)
end

local function MeasuredTextHeight(fontString,fallback)
    if fontString and type(fontString.GetStringHeight)=="function" then
        local ok,value=pcall(fontString.GetStringHeight,fontString)
        value=ok and tonumber(value) or nil
        if value and value>0 then return math.ceil(value)+2 end
    end
    return math.max(0,tonumber(fallback) or 0)
end

-- Cursor tooltips are also used to present the character's imported TRP
-- At First Glance entries. Those descriptions can be much longer than normal
-- ODYN help text, so the card must size itself to the rendered FontStrings.
-- The previous 430px hard cap left the body drawing below the tooltip border.
local function LayoutPass(config,width)
    local f=EnsureTooltip()
    local body=tostring(config.body or config.description or "")
    local section=tostring(config.section or config.effect or "")
    local detail=tostring(config.detail or "")
    local footer=tostring(config.footer or "")
    local chars=math.max(28,math.floor((width-34)/6.1))

    f:SetWidth(width)
    f.eyebrow:SetText(tostring(config.eyebrow or config.subtitle or "ODYN"))
    f.title:SetText(tostring(config.title or ""))

    -- Title/rule geometry is measured too, so a long Glance title cannot collide
    -- with the body or keep the old one-line rule position.
    f.title:ClearAllPoints();f.title:SetPoint("TOPLEFT",17,-31);f.title:SetPoint("RIGHT",-17,0)
    local titleH=MeasuredTextHeight(f.title,24)
    local ruleY=-31-titleH-7
    f.rule:ClearAllPoints();f.rule:SetPoint("TOPLEFT",17,ruleY);f.rule:SetPoint("TOPRIGHT",-17,ruleY)

    local y=ruleY-12
    f.body:SetText(body)
    f.body:ClearAllPoints();f.body:SetPoint("TOPLEFT",17,y);f.body:SetPoint("RIGHT",-17,0)
    local bodyH=MeasuredTextHeight(f.body,Estimate(body,chars,13,14))
    y=y-bodyH

    if section~="" then
        y=y-10
        f.sectionLabel:Show();f.section:Show()
        f.sectionLabel:SetText(string.upper(tostring(config.sectionTitle or "EFFECT")))
        f.sectionLabel:ClearAllPoints();f.sectionLabel:SetPoint("TOPLEFT",17,y)
        y=y-15
        f.section:SetText(section)
        f.section:ClearAllPoints();f.section:SetPoint("TOPLEFT",17,y);f.section:SetPoint("RIGHT",-17,0)
        y=y-MeasuredTextHeight(f.section,Estimate(section,chars,13,14))
    else
        f.sectionLabel:Hide();f.section:Hide()
    end

    if detail~="" then
        y=y-10
        f.detailLabel:Show();f.detail:Show()
        f.detailLabel:SetText(string.upper(tostring(config.detailTitle or "HOW IT WORKS")))
        f.detailLabel:ClearAllPoints();f.detailLabel:SetPoint("TOPLEFT",17,y)
        y=y-15
        f.detail:SetText(detail)
        f.detail:ClearAllPoints();f.detail:SetPoint("TOPLEFT",17,y);f.detail:SetPoint("RIGHT",-17,0)
        y=y-MeasuredTextHeight(f.detail,Estimate(detail,chars,12,13))
    else
        f.detailLabel:Hide();f.detail:Hide()
    end

    if footer~="" then
        y=y-12
        f.footerRule:Show();f.footer:Show()
        f.footerRule:ClearAllPoints();f.footerRule:SetPoint("TOPLEFT",17,y);f.footerRule:SetPoint("TOPRIGHT",-17,y)
        y=y-10
        f.footer:SetText(footer)
        f.footer:ClearAllPoints();f.footer:SetPoint("TOPLEFT",17,y);f.footer:SetPoint("RIGHT",-17,0)
        y=y-MeasuredTextHeight(f.footer,Estimate(footer,chars,11,12))
    else
        f.footerRule:Hide();f.footer:Hide()
    end

    return math.max(108,math.ceil((-y)+14))
end

local function Layout(config)
    local f=EnsureTooltip()
    local width=tonumber(config.width) or 380
    width=math.max(300,math.min(520,width))

    local parentW=(UIParent and UIParent.GetWidth and UIParent:GetWidth()) or 1280
    local parentH=(UIParent and UIParent.GetHeight and UIParent:GetHeight()) or 720
    local maxWidth=math.max(width,math.min(760,parentW-48))
    local comfortableHeight=math.max(430,parentH-44)

    local height=LayoutPass(config,width)
    -- If an exceptionally long Glance would be taller than the screen, widen
    -- the tooltip itself rather than shrinking its font or clipping the text.
    while height>comfortableHeight and width<maxWidth do
        width=math.min(maxWidth,width+70)
        height=LayoutPass(config,width)
    end

    -- No fixed vertical cap: the frame follows the actual rendered text.
    -- SetClampedToScreen then repositions the complete card at screen edges.
    f:SetHeight(height)
    f._rpalMeasuredWidth=width
    f._rpalMeasuredHeight=height
end

function RPAL.ShowCursorTooltip(config)
    config=config or {}
    activeConfig=config
    local f=EnsureTooltip()
    local accent=config.accent or GOLD
    local r,g,b=Color(accent,GOLD)

    -- Kill any legacy Blizzard tooltip left open by another RPAL control.
    if GameTooltip then GameTooltip:Hide() end

    Layout(config)
    f:SetBackdropBorderColor(r,g,b,0.98)
    f.rule:SetVertexColor(r,g,b,0.46)
    f.footerRule:SetVertexColor(r,g,b,0.24)
    f.eyebrow:SetTextColor(r,g,b,0.98)
    f.sectionLabel:SetTextColor(r,g,b,0.94)
    f.section:SetTextColor(r,g,b,1)
    f.detailLabel:SetTextColor(r,g,b,0.94)
    f.wash:SetVertexColor(r,g,b,1)
    if RPAL.ApplyTooltipTreatment then RPAL.ApplyTooltipTreatment(f,accent) end
    if config.footerColor then
        local fr,fg,fb,fa=Color(config.footerColor,MUTED)
        f.footer:SetTextColor(fr,fg,fb,fa)
    else
        f.footer:SetTextColor(MUTED[1],MUTED[2],MUTED[3],1)
    end

    f:SetAlpha(0)
    f._fade=0
    PositionTooltip()
    f:Show()
    f:SetScript("OnUpdate",function(self,elapsed)
        PositionTooltip()
        self._fade=(self._fade or 0)+(elapsed or 0)
        self:SetAlpha(math.min(1,self._fade/0.10))
    end)
    return f
end

function RPAL.RefreshCursorTooltipTreatment()
    if not tooltip or not tooltip:IsShown() then return false end
    local accent=(activeConfig and activeConfig.accent) or GOLD
    if RPAL.ApplyTooltipTreatment then RPAL.ApplyTooltipTreatment(tooltip,accent) end
    return true
end

function RPAL.HideCursorTooltip()
    activeConfig=nil
    if tooltip then
        tooltip:SetScript("OnUpdate",nil)
        tooltip:Hide()
    end
    if GameTooltip then GameTooltip:Hide() end
end

function RPAL.ShowSimpleCursorTooltip(title,body,accent,eyebrow,footer)
    return RPAL.ShowCursorTooltip({
        title=title,
        body=body,
        accent=accent,
        eyebrow=eyebrow or "ODYN",
        footer=footer,
        width=350,
    })
end
