--[[--------------------------------------------------------------------
  PaladinHolyPower – ui/components/slider.lua      (Clean Professional)

  • Adds click-to-edit value entry identical in feel to edit_handle.lua:
    - Click the value text → inline EditBox appears
    - Enter or focus lost commits if numeric (snap/clamp applied)
    - Invalid input safely reverts to the last value

  • No idle animations: all anims are event-driven.
----------------------------------------------------------------------]]

local PHP = _G.PaladinHolyPower
if not PHP then return end

local CONST = {
  WIDTH            = 160,
  HEIGHT           = 32,
  TITLE_COLOR      = { 1, 1, 1 },

  BAR_HEIGHT       = 12,
  BAR_COLOR        = { 0.22, 0.20, 0.14, 1 },
  BAR_BORDER       = { 0, 0, 0, 1 },
  BAR_BORDER_SIZE  = 1,

  -- Thumb styling (matches panel tabs/buttons vibe)
  THUMB_HEIGHT     = 12, -- default thumb height (usually BAR_HEIGHT)
  THUMB_WIDTH      = 10, -- default thumb width
  -- NOTE: We keep THUMB_H for compatibility but we no longer use it for hover.
  THUMB_N          = (PHP.TAB_COLOR    or { 1, 0.95, 0.75, 1 }),       -- idle (holy gold / or theme)
  THUMB_H          = (PHP.TAB_HOVER    or { 0.10, 0.09, 0.07, 0.98 }), -- legacy hover (unused)
  THUMB_P          = (PHP.TAB_SELECTED or { 0.13, 0.12, 0.10, 1.00 }), -- pressed/drag
  THUMB_BORDER_COLOR = { 0, 0, 0, 1 },
  THUMB_BORDER_SIZE  = 1,

  -- Ink (soft wash) + animation (same feel as tabs/buttons)
  INK_HOVER        = 0.06,
  INK_DRAG         = 0.12,
  SPEED            = 18,   -- higher = snappier

  VALUE_COLOR      = { 1, 1, 1 },
  VALUE_FONT       = "GameFontHighlightSmall",
}

local function clamp(v, min, max) return math.max(min, math.min(max, v)) end
local function lerp(a, b, t) return a + (b - a) * t end

--[[--------------------------------------------------------------------
CreateSlider(
  name, label, minVal, maxVal, step, value,
  parent, x, y, setter, isPercent, tipTitle, tipText,
  thumbWidth, thumbHeight
)
----------------------------------------------------------------------]]
function PHP.CreateSlider(name, label, minVal, maxVal, step, value,
                          parent, x, y, setter, isPercent, tipTitle, tipText,
                          thumbWidth, thumbHeight)
  --------------------------------------------------------------------
  -- Container: holds slider and value label
  --------------------------------------------------------------------
  local container = CreateFrame("Frame", name .. "Container", parent)
  container:SetSize(CONST.WIDTH, CONST.HEIGHT + 18)
  container:SetPoint("TOPLEFT", parent, "TOPLEFT", x, y)

  --------------------------------------------------------------------
  -- Slider region: mouse-enabled, contains title/bar/thumb
  --------------------------------------------------------------------
  local slider = CreateFrame("Frame", name .. "Slider", container)
  slider:SetPoint("TOPLEFT", container, "TOPLEFT", 0, 0)
  slider:SetSize(CONST.WIDTH, CONST.HEIGHT)
  slider:EnableMouse(true)

  local function ShowTooltip()
    if tipTitle or tipText then
      GameTooltip:SetOwner(slider, "ANCHOR_TOP")
      GameTooltip:SetText(tipTitle or label or "", 1, 1, 1)
      if tipText and tipText ~= "" then
        GameTooltip:AddLine(tipText, 0.9, 0.9, 0.9, true)
      end
      GameTooltip:Show()
    end
  end
  local function HideTooltip() GameTooltip:Hide() end

  --------------------------------------------------------------------
  -- Title (centered)
  --------------------------------------------------------------------
  local title = slider:CreateFontString(nil, "OVERLAY", "GameFontNormal")
  title:SetPoint("TOP", slider, "TOP", 0, 0)
  title:SetTextColor(unpack(CONST.TITLE_COLOR))
  title:SetJustifyH("CENTER")
  title:SetText(label)

  --------------------------------------------------------------------
  -- Bar (background)
  --------------------------------------------------------------------
  local bar = CreateFrame("Frame", nil, slider, "BackdropTemplate")
  bar:SetPoint("TOP", title, "BOTTOM", 0, -4)
  bar:SetSize(CONST.WIDTH, CONST.BAR_HEIGHT)
  bar:SetBackdrop({
    bgFile   = "Interface\\Buttons\\WHITE8x8",
    edgeFile = "Interface\\Buttons\\WHITE8x8",
    edgeSize = CONST.BAR_BORDER_SIZE,
  })
  bar:SetBackdropColor(unpack(CONST.BAR_COLOR))
  bar:SetBackdropBorderColor(unpack(CONST.BAR_BORDER))
  bar:SetFrameLevel(slider:GetFrameLevel() + 1)

  --------------------------------------------------------------------
  -- Thumb (movable indicator) — animated to match tab/button style
  --------------------------------------------------------------------
  local TW = math.max(1, tonumber(thumbWidth)  or CONST.THUMB_WIDTH)
  local TH = math.max(1, tonumber(thumbHeight) or CONST.THUMB_HEIGHT)

  local thumb = CreateFrame("Frame", nil, bar, "BackdropTemplate")
  thumb:SetSize(TW, TH)
  thumb:SetBackdrop({
    bgFile   = "Interface\\Buttons\\WHITE8x8",
    edgeFile = "Interface\\Buttons\\WHITE8x8",
    edgeSize = CONST.THUMB_BORDER_SIZE,
  })
  thumb:SetBackdropColor(unpack(CONST.THUMB_N))
  thumb:SetBackdropBorderColor(unpack(CONST.THUMB_BORDER_COLOR))
  thumb:SetFrameLevel(bar:GetFrameLevel() + 2)

  local ink = thumb:CreateTexture(nil, "BACKGROUND")
  ink:SetTexture("Interface\\Buttons\\WHITE8x8")
  ink:SetAllPoints(thumb)
  ink:SetVertexColor(1, 1, 1)
  ink:SetAlpha(0) -- visible only on hover/drag

  local gloss = thumb:CreateTexture(nil, "OVERLAY")
  gloss:SetTexture("Interface\\Buttons\\WHITE8x8")
  gloss:SetAllPoints(thumb)
  gloss:SetBlendMode("ADD")
  if gloss.SetGradient and CreateColor then
    gloss:SetGradient("VERTICAL",
      CreateColor(1, 1, 1, 0.10),  -- white glass
      CreateColor(1, 1, 1, 0.00))  -- fade out
  else
    gloss:SetVertexColor(1, 1, 1, 0.05)
  end
  gloss:SetAlpha(0) -- visible only on hover

  -- Animated state for thumb
  thumb._state = {
    targetBG = { unpack(CONST.THUMB_N) },
    inkAlpha = 0,
    speed    = CONST.SPEED,
  }

  -- Event-driven animator for thumb (no idle OnUpdate)
  local function __ThumbRunAnim(self, elapsed)
    local s = self._state
    if not s then self:SetScript("OnUpdate", nil); self._animating=false; return end
    local k = math.min(1, (elapsed or 0) * (s.speed or CONST.SPEED))

    -- Lerp backdrop color
    local r,g,b,a = self:GetBackdropColor()
    r = lerp(r, s.targetBG[1], k)
    g = lerp(g, s.targetBG[2], k)
    b = lerp(b, s.targetBG[3], k)
    a = lerp(a, s.targetBG[4], k)
    self:SetBackdropColor(r,g,b,a)

    -- Lerp ink alpha
    local ia = ink:GetAlpha()
    ink:SetAlpha(lerp(ia, s.inkAlpha or 0, k))

    if math.abs(r - s.targetBG[1]) < 0.001
       and math.abs(g - s.targetBG[2]) < 0.001
       and math.abs(b - s.targetBG[3]) < 0.001
       and math.abs(a - s.targetBG[4]) < 0.001
       and math.abs(ink:GetAlpha() - (s.inkAlpha or 0)) < 0.001 then
      self:SetScript("OnUpdate", nil)
      self._animating = false
    end
  end
  local function __ThumbKick()
    if thumb._animating then return end
    thumb._animating = true
    thumb:SetScript("OnUpdate", __ThumbRunAnim)
  end

  --------------------------------------------------------------------
  -- Value label (below)
  --------------------------------------------------------------------
  local valueText = container:CreateFontString(nil, "OVERLAY", CONST.VALUE_FONT)
  valueText:SetPoint("TOP", slider, "BOTTOM", 0, -2)
  valueText:SetTextColor(unpack(CONST.VALUE_COLOR))

  --------------------------------------------------------------------
  -- Slider value logic
  --------------------------------------------------------------------
  local function snap(v)
    return math.floor((v - minVal) / step + 0.5) * step + minVal
  end

  local curValue = value or minVal
  local dragging = false

  -- Recompute thumb position using the actual bar width
  local function positionThumbFromValue(val)
    local pct = clamp((val - minVal) / (maxVal - minVal), 0, 1)
    local barW = bar:GetWidth() or CONST.WIDTH
    local usable = math.max(0, barW - TW)
    thumb:ClearAllPoints()
    thumb:SetPoint("LEFT", bar, "LEFT", pct * usable, 0)
  end

  local function setValue(val, fireSetter)
    val = clamp(snap(val), minVal, maxVal)
    curValue = val
    positionThumbFromValue(val)
    valueText:SetText(isPercent and (val .. "%") or tostring(val))
    if fireSetter and setter then setter(val) end
  end
  setValue(curValue, false)

  -- Helper: cursor over thumb mat
  local function IsCursorOverThumb()
    local cx, cy = GetCursorPosition()
    local scale = thumb:GetEffectiveScale()
    local l, b, w, h = thumb:GetLeft(), thumb:GetBottom(), thumb:GetWidth(), thumb:GetHeight()
    if not (l and b and w and h and scale) then return false end
    cx, cy = cx / scale, cy / scale
    return cx >= l and cx <= l + w and cy >= b and cy <= b + h
  end

  -- Drag logic (uses current TW so width changes are respected live)
  local function updateFromCursor()
    local barLeft = bar:GetLeft()
    local barW    = bar:GetWidth()
    local scale   = bar:GetEffectiveScale()
    if not (barLeft and barW and scale) then return end
    local cursorX = GetCursorPosition() / scale
    local usable  = math.max(0, barW - TW)
    local pct     = clamp((cursorX - barLeft - TW / 2) / usable, 0, 1)
    local newValue = minVal + pct * (maxVal - minVal)
    setValue(newValue, true)
  end

  -- Hover-state updater (thumb adopts hover/idle visuals)
  local function HoverUpdate()
    if dragging then return end
    local s = thumb._state
    if IsCursorOverThumb() then
      -- Keep base color, add ink + gloss (no dark hover plate)
      s.targetBG = { CONST.THUMB_N[1], CONST.THUMB_N[2], CONST.THUMB_N[3], CONST.THUMB_N[4] }
      s.inkAlpha = CONST.INK_HOVER
      gloss:SetAlpha(1)
    else
      -- Idle
      s.targetBG = { CONST.THUMB_N[1], CONST.THUMB_N[2], CONST.THUMB_N[3], CONST.THUMB_N[4] }
      s.inkAlpha = 0
      gloss:SetAlpha(0)
    end
    if __ThumbKick then __ThumbKick() end
  end

  --------------------------------------------------------------------
  -- Interaction scripts (map to animated thumb states)
  --------------------------------------------------------------------
  slider:SetScript("OnMouseDown", function(self, btn)
    if btn == "LeftButton" then
      dragging = true
      -- Pressed/drag style (gloss off, deeper ink, pressed color)
      local s = thumb._state
      s.targetBG = { CONST.THUMB_P[1], CONST.THUMB_P[2], CONST.THUMB_P[3], CONST.THUMB_P[4] }
      s.inkAlpha = CONST.INK_DRAG
      gloss:SetAlpha(0)
      __ThumbKick()
      -- Start drag tracking on the slider OnUpdate (thumb anim runs independently)
      self:SetScript("OnUpdate", updateFromCursor)
    end
  end)

  slider:SetScript("OnMouseUp", function(self, btn)
    if btn == "LeftButton" then
      dragging = false
      -- Return to hover or idle depending on pointer
      HoverUpdate()
      if self:IsMouseOver() then
        self:SetScript("OnUpdate", HoverUpdate)
      else
        self:SetScript("OnUpdate", nil)
      end
    end
  end)

  slider:SetScript("OnMouseWheel", function(_, delta)
    local inc = step * (delta > 0 and 1 or -1)
    setValue(curValue + inc, true)
  end)

  slider:SetScript("OnEnter", function(self)
    ShowTooltip()
    HoverUpdate()
    self:SetScript("OnUpdate", HoverUpdate)
  end)

  slider:SetScript("OnLeave", function(self)
    HideTooltip()
    self:SetScript("OnUpdate", nil)
    local s = thumb._state
    s.targetBG = { CONST.THUMB_N[1], CONST.THUMB_N[2], CONST.THUMB_N[3], CONST.THUMB_N[4] }
    s.inkAlpha = 0
    gloss:SetAlpha(0)
    __ThumbKick()
  end)

  -- Safety: detach animations when hidden
  container:SetScript("OnHide", function()
    slider:SetScript("OnUpdate", nil)
    thumb:SetScript("OnUpdate", nil)
    thumb._animating = false
  end)

  --------------------------------------------------------------------
  -- Click-to-edit value (same UX as edit_handle.lua)
  --------------------------------------------------------------------
  valueText:EnableMouse(true)

  local valueEdit = CreateFrame("EditBox", nil, container, "BackdropTemplate")
  valueEdit:SetFontObject(CONST.VALUE_FONT)
  valueEdit:SetAutoFocus(false)
  valueEdit:SetJustifyH("CENTER")
  valueEdit:SetPoint("TOP", slider, "BOTTOM", 0, -2)
  valueEdit:SetSize(56, 18)  -- compact box
  valueEdit:SetBackdrop({
    bgFile   = "Interface\\Buttons\\WHITE8x8",
    edgeFile = "Interface\\Buttons\\WHITE8x8",
    edgeSize = 1,
  })
  valueEdit:SetBackdropColor(0.157, 0.157, 0.157, 0.85)
  valueEdit:SetBackdropBorderColor(0, 0, 0, 1)
  valueEdit:SetTextColor(1, 1, 1, 1)
  valueEdit:Hide()

  local function commitEdit(self)
    local raw = (self:GetText() or ""):gsub("%s+", ""):gsub("%%","")
    local num = tonumber(raw)
    if num then
      setValue(num, true)  -- snap + clamp + setter
    else
      -- revert if invalid
      valueText:SetText(isPercent and (curValue .. "%") or tostring(curValue))
    end
    self:Hide()
    valueText:Show()
    self:ClearFocus()
  end

  valueEdit:SetScript("OnEnterPressed", commitEdit)
  valueEdit:SetScript("OnEditFocusLost", commitEdit)

  valueText:SetScript("OnMouseUp", function()
    valueText:Hide()
    valueEdit:Show()
    valueEdit:SetText(tostring(curValue))  -- numeric entry (no %)
    valueEdit:HighlightText()
    valueEdit:SetFocus()
  end)

  --------------------------------------------------------------------
  -- Public API
  --------------------------------------------------------------------
  container.valueText = valueText
  container.valueEdit = valueEdit
  container.bar       = bar
  container.title     = title
  container.thumb     = thumb

  container.GetValue = function() return curValue end
  container.SetValue = function(_, v) setValue(v, true) end

  -- Live thumb size controls
  local function ApplyThumbSize(newW, newH)
    if newW then TW = math.max(1, tonumber(newW) or TW) end
    if newH then TH = math.max(1, tonumber(newH) or TH) end
    thumb:SetSize(TW, TH)
    positionThumbFromValue(curValue) -- keep it clamped within bar
  end

  container.SetThumbWidth  = function(_, newW) ApplyThumbSize(newW, nil) end
  container.SetThumbHeight = function(_, newH) ApplyThumbSize(nil, newH) end
  container.SetThumbSize   = function(_, newW, newH) ApplyThumbSize(newW, newH) end

  return container
end