-- Shared pattern: title-bar-only drag + bottom-right resize grip (outside frame on UIParent).
-- Loaded before gui.lua; call RR_ConfigResizeGrip_Attach(opts) once after titleBg exists.
-- opts.onLiveResize(w, h): optional; clamped Größe bei jedem Live-Resize (wie rOrbs: Inhalt/CW mitziehen).

local function clamp(n, lo, hi)
  if n < lo then return lo end
  if n > hi then return hi end
  return n
end

function RR_ConfigResizeGrip_Attach(opts)
  if not opts or not opts.frame or not opts.titleBg or not opts.dbTable then return end
  local frame, titleBg, db = opts.frame, opts.titleBg, opts.dbTable
  if frame.__rrResizeGripAttached then return end
  frame.__rrResizeGripAttached = true

  local wk = opts.wKey or "guiFrameW"
  local hk = opts.hKey or "guiFrameH"
  local defW = opts.defW or 840
  local defH = opts.defH or 600
  local minW = opts.minW or math.max(320, math.floor(defW * 0.55))
  local maxW = opts.maxW or math.floor(defW * 1.6)
  local minH = opts.minH or math.max(280, math.floor(defH * 0.55))
  local maxH = opts.maxH or math.floor(defH * 1.5)
  local texPath = opts.texturePath
  if not texPath or texPath == "" then return end
  local gripName = opts.gripName or "RRConfigResizeGrip"
  local pr = (opts.primary and opts.primary[1]) or 0.9
  local pg = (opts.primary and opts.primary[2]) or 0.18
  local pb = (opts.primary and opts.primary[3]) or 0.18
  local hr = (opts.primaryHi and opts.primaryHi[1]) or 1
  local hg = (opts.primaryHi and opts.primaryHi[2]) or 0.42
  local hb = (opts.primaryHi and opts.primaryHi[3]) or 0.42
  local tip = opts.tooltipText

  frame:SetResizable(true)
  if frame.SetResizeBounds then
    frame:SetResizeBounds(minW, minH, maxW, maxH)
  end

  frame:RegisterForDrag()
  titleBg:EnableMouse(true)
  titleBg:RegisterForDrag("LeftButton")
  titleBg:SetScript("OnDragStart", function() frame:StartMoving() end)
  titleBg:SetScript("OnDragStop", function()
    frame:StopMovingOrSizing()
    if opts.onMoved then opts.onMoved() end
  end)

  local grip = CreateFrame("Button", gripName, UIParent)
  grip:EnableMouse(true)
  grip:SetSize(22, 22)
  grip:SetFrameStrata(frame:GetFrameStrata())
  grip:SetFrameLevel(frame:GetFrameLevel() + 55)
  grip:Hide()

  local function SyncGrip()
    if not grip or not frame then return end
    grip:ClearAllPoints()
    grip:SetPoint("TOPLEFT", frame, "BOTTOMRIGHT", 2, -2)
    local ps = frame:GetScale() or 1
    if ps > 0 then grip:SetScale(ps) end
  end

  local gt = grip:CreateTexture(nil, "OVERLAY")
  gt:SetAllPoints()
  gt:SetTexture(texPath)
  gt:SetVertexColor(pr, pg, pb, 0.9)

  grip:SetScript("OnEnter", function()
    gt:SetVertexColor(hr, hg, hb, 1)
    GameTooltip:SetOwner(grip, "ANCHOR_LEFT")
    GameTooltip:SetText(tip, 1, 1, 1)
    GameTooltip:Show()
  end)
  grip:SetScript("OnLeave", function()
    gt:SetVertexColor(pr, pg, pb, 0.9)
    GameTooltip:Hide()
  end)

  grip:RegisterForDrag("LeftButton")
  grip:SetScript("OnDragStart", function() frame:StartSizing("BOTTOMRIGHT") end)
  grip:SetScript("OnDragStop", function()
    frame:StopMovingOrSizing()
    db[wk] = clamp(math.floor(frame:GetWidth() + 0.5), minW, maxW)
    db[hk] = clamp(math.floor(frame:GetHeight() + 0.5), minH, maxH)
    if opts.onSaved then opts.onSaved() end
    SyncGrip()
  end)

  local function OnFrameSizeChanged()
    SyncGrip()
    if opts.onLiveResize then
      local w = clamp(math.floor(frame:GetWidth() + 0.5), minW, maxW)
      local h = clamp(math.floor(frame:GetHeight() + 0.5), minH, maxH)
      opts.onLiveResize(w, h)
    end
  end

  frame:HookScript("OnShow", function()
    SyncGrip()
    grip:Show()
  end)
  frame:HookScript("OnHide", function() grip:Hide() end)
  frame:HookScript("OnSizeChanged", OnFrameSizeChanged)
  titleBg:HookScript("OnDragStop", SyncGrip)

  local ssName = opts.syncScaleName
  if ssName and frame[ssName] and type(frame[ssName]) == "function" then
    local prevSync = frame[ssName]
    frame[ssName] = function()
      prevSync()
      SyncGrip()
    end
  end

  frame._rrConfigResizeGrip = grip
end
