-------------------------------------------------------------------------------
--  EllesmereUI_koKR_Plus / TooltipScale.lua
--  엘스미어 설정창/위대한 금고 등 위젯 툴팁 *배율*(SetScale). 텍스트 번역은
--  번역 본체(Core.lua) 담당. settingsTipScale × widgetScale.
--  전역 노출: _G.EllesmereUI_KR_ApplyTipScale (WidgetScale·번역본이 호출).
-------------------------------------------------------------------------------
---@diagnostic disable: undefined-global
local NS = _G.EUIKorPlus
if not NS then return end
local GetDB = NS.GetDB
local TIPSCALE_MIN, TIPSCALE_MAX = NS.RANGE.TIP[1], NS.RANGE.TIP[2]
local _euiTipFrame             -- 결정적 확정 싱글톤만 캐시
local _tipScanBudget = 120     -- wantText 없는 헛스캔 예산(무한 walk 방지)
local function _FindEUITipFrame(wantText)
    if _euiTipFrame then return _euiTipFrame end
    if not (UIParent and UIParent.GetChildren) then return nil end
    local hasWant = type(wantText) == "string" and wantText ~= ""
    if not hasWant then
        if _tipScanBudget <= 0 then return nil end
        _tipScanBudget = _tipScanBudget - 1
    end
    local heuristic
    for _, c in ipairs({ UIParent:GetChildren() }) do
        if type(c) == "table" and c.GetObjectType then
            local okN, nm = pcall(c.GetName, c)
            local okT, ot = pcall(c.GetObjectType, c)
            if okN and nm == nil and okT and ot == "Frame" then
                local okS, isTT = pcall(function() return c:GetFrameStrata() == "TOOLTIP" end)
                local tx = c.text
                local okX = type(tx) == "table" and tx.GetObjectType
                    and select(1, pcall(tx.GetObjectType, tx)) ~= nil
                if okS and isTT and okX then
                    local okO, ox = pcall(tx.GetObjectType, tx)
                    if okO and ox == "FontString" then
                        if hasWant then
                            local okG, shown = pcall(tx.GetText, tx)
                            if okG and shown == wantText then
                                _euiTipFrame = c  -- 내용 일치 = 결정적, 영구 캐시
                                return c
                            end
                        end
                        heuristic = heuristic or c
                    end
                end
            end
        end
    end
    -- 결정적 실패: 휴리스틱은 *반환만*, 캐시 안 함(오프레임 방지).
    return heuristic
end

-- 툴팁 크기 배율(1.0~2.0). settingsTipScale × widgetScale.
-- (widgetScale 도 곱해서 위젯 팝업 배율 옵션이 툴팁에도 동일 적용되도록 통합.)
local function _TipScale()
    local v = GetDB().settingsTipScale or 1.0
    if type(v) ~= "number" then v = 1.0 end
    if v < TIPSCALE_MIN then v = TIPSCALE_MIN end
    if v > TIPSCALE_MAX then v = TIPSCALE_MAX end
    local w = GetDB().widgetScale or 1.0
    if type(w) ~= "number" then w = 1.0 end
    return v * w
end

-- (위젯 툴팁 *텍스트 번역*은 Core.lua 로 이전 — HookShowWidgetTooltip /
--  PatchTooltipFrame / _ScanTipSingleton / _trTooltipText. 여기는 *스케일* 만.)

-- ★ 핵심: EUI 의 ShowWidgetTooltip 은 표시 때 SetScale(opts.scale or 1), 숨길 때
--   HideWidgetTooltip 이 *SetScale(1) 먼저* → 1.5에서 1로 순간 축소되며 페이드
--   ("작아지면서 사라짐"). 또 설정창 옵션은 *로컬* ShowWidgetTooltip 을 써서
--   필드 래퍼/opts.scale 을 안 탐. → 해결: *싱글톤 프레임의 SetScale 자체를
--   후크* 해 배율을 항상 강제. 그러면 ① 모든 경로(설정창·계산기) 커버 ②
--   숨길 때 1로 못 내려가 잔상 없음 ③ 표시 때도 자동 적용.
--   (배율 1.0=끔일 땐 강제 안 함 → 네이티브 동작 유지.)
local function _HookTipScaleEnforce(f)
    if not f or not f.SetScale then return end
    -- 매번 현재 배율 강제 (idempotent — 같은 값이면 no-op).
    -- 후크 미설치라면 설치, 설치된 상태라면 즉시 SetScale 만 적용.
    if not f.__cimTipSEnf then
        f.__cimTipSEnf = true
        hooksecurefunc(f, "SetScale", function(self, s)
            if self.__cimTipSReent then return end
            local want = _TipScale()
            if want ~= 1 and s ~= want then
                self.__cimTipSReent = true
                pcall(self.SetScale, self, want)
                self.__cimTipSReent = false
            end
        end)
    end
    local want = _TipScale()
    if want ~= 1 then pcall(f.SetScale, f, want) end
end

-- UIParent 의 무명 TOOLTIP-strata + .text 프레임(= EUI 위젯 툴팁 싱글톤)을 찾아
-- SetScale 강제 후크 설치. 여러 개여도 모두. (GameTooltip 등 명명 제외 → 안전.)
-- 글로벌 노출: Core.lua 의 _ScanTipSingleton ticker 에서 호출 → 추가기능 안 들어가도
-- 첫 hover 즉시 singleton 잡아 스케일 적용.
local _ApplyTipScale  -- forward decl
_G.EllesmereUI_KR_ApplyTipScale = function() if _ApplyTipScale then pcall(_ApplyTipScale) end end
_ApplyTipScale = function(_wantText)
    if not (UIParent and UIParent.GetChildren) then return end
    local ok, kids = pcall(function() return { UIParent:GetChildren() } end)
    if not ok or type(kids) ~= "table" then return end
    for _, c in ipairs(kids) do
        if type(c) == "table" and c.GetObjectType then
            local okN, nm = pcall(c.GetName, c)
            local okT, ot = pcall(c.GetObjectType, c)
            if okN and nm == nil and okT and ot == "Frame" then
                -- ★ strata 비교를 pcall 안에서 — 일부 보안 프레임(상점 등)은 strata 가
                --   secret string 이라 raw 비교 시 throw(taint 컨텍스트).
                local okS, isTT = pcall(function() return c:GetFrameStrata() == "TOOLTIP" end)
                local tx = c.text
                if okS and isTT and type(tx) == "table" and tx.GetObjectType then
                    _HookTipScaleEnforce(c)
                    _G.__cimTipSingletonHooked = true  -- 싱글톤 확보 → 로그인 ticker 종료 신호
                end
            end
        end
    end
end

-- EllesmereUI.ShowWidgetTooltip (Widgets.lua:5255 = local ShowWidgetTooltip
-- 노출). 위젯 일부는 이 네임스페이스 필드를 호출(예: EUI__General_Options
-- .lua:193 "Optimizes your graphics settings for maximum FPS ...").
--
-- hooksecurefunc 는 사후 후크라 *인자(text)를 못 바꿈* → 번역 불가.
-- 함수 자체를 래퍼로 교체해 *배율(opts.scale)* 만 주입(번역은 Core 담당).
-- 툴팁은 비보안 프레임 표시 함수 → 교체해도 taint 무관(안전). _orig 는 항상 호출.
local function _InstallTipHook()
    if _G.__cimTipHookInstalled then return end
    if not (EllesmereUI and type(EllesmereUI.ShowWidgetTooltip) == "function") then
        return
    end
    _G.__cimTipHookInstalled = true
    local _orig = EllesmereUI.ShowWidgetTooltip
    EllesmereUI.ShowWidgetTooltip = function(label, text, opts)
        -- ★ EUI ShowWidgetTooltip 은 *opts.scale* 을 직접 지원(Widgets.lua:1447
        --   tt:SetScale(opts.scale or 1)). 직접 SetScale 하면 EUI 가 매 표시마다
        --   1 로 리셋해 경쟁→잔상/불일치. opts.scale 로 넘기면 EUI 가 알아서 처리.
        local sc = _TipScale()
        if type(sc) == "number" and sc > 1 then
            if type(opts) ~= "table" then opts = {} end
            opts.scale = sc
        end
        _orig(label, text, opts)
        -- 래퍼를 안 거치는 로컬 경로 툴팁 배율도 커버.
        pcall(_ApplyTipScale)
    end
end

-- ============================================================
--  팝업 섹션 + 진입점 등록
-- ============================================================
if NS.RegisterSection then
    NS.RegisterSection({
        order = 30, col = 0, row = 1, title = "설정창 툴팁 크기",
        desc  = "엘스미어 설정·위대한 금고 등 툴팁 배율.",
        build = function(popup, descFS)
            local R = NS.RANGE.TIP
            NS.MakeStepperRow(popup, descFS, {
                get = function() return GetDB().settingsTipScale or 1.0 end,
                set = function(v) GetDB().settingsTipScale = math.floor(v * 10 + 0.5) / 10 end,
                fmt = function(v) return string.format("배율 %.1fx", v) end,
                min = R[1], max = R[2], step = R[3],
                onChange = function() pcall(_ApplyTipScale) end,
            })
        end,
    })
    NS.RegisterOnShow(function() pcall(_ApplyTipScale) end)   -- K메뉴 열 때 재적용
end
if NS.RegisterInstall then
    NS.RegisterInstall(function()
        _InstallTipHook()
        pcall(_ApplyTipScale)
    end)
end
