--[[--------------------------------------------------------------------
  PaladinHolyPower - ui/settings_panel/panel.lua
  Settings Panel: Main UI Entry Point, Left Sidebar Tabs, Frame Handling
----------------------------------------------------------------------]]

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

-- === Global knobs (kept tiny) ===
PHP.ACCENT_COLOR = PHP.ACCENT_COLOR or { 0.95, 0.90, 0.55, 1.00 }

local function InCombat()
  if type(InCombatLockdown) == "function" and InCombatLockdown() then return true end
  if UnitAffectingCombat and UnitAffectingCombat("player") then return true end
  return false
end

-- Sizes
local PANEL_W, PANEL_H  = 700, 400
local SIDEBAR_W         = 160
local HEADER_HEIGHT     = 45

-- Spacer: extra vertical gap inserted *after* the first ("Home") tab
local HOME_EXTRA_GAP    = 28  -- tweak to taste

-- === Dynamic Theme accessors (no caching) ===========================
local function WhiteTex()
  local T = PHP and PHP.Theme
  return (T and T.WhiteTex and T.WhiteTex()) or "Interface\\Buttons\\WHITE8x8"
end
local function PanelTex()
  local T = PHP and PHP.Theme
  return (T and T.Texture and T.Texture()) or "Interface\\AddOns\\PaladinHolyPower\\media\\icons\\background\\panel_1.png"
end
local function TintRoot()
  local T = PHP and PHP.Theme
  return (T and T.RootTint and T.RootTint()) or { 0.98, 0.98, 0.99, 0.75 }
end
local function TintHeader()
  local T = PHP and PHP.Theme
  return (T and T.HeaderTint and T.HeaderTint()) or { 0.95, 0.90, 0.55, 0.75 }
end
local function TintSidebar()
  local T = PHP and PHP.Theme
  return (T and T.SidebarTint and T.SidebarTint()) or { 0.95, 0.90, 0.55, 0.75 }
end
local function TintContent()
  local T = PHP and PHP.Theme
  return (T and T.ContentTint and T.ContentTint()) or { 0.95, 0.90, 0.55, 0.70 }
end
local function DividerThickness()
  local T = PHP and PHP.Theme
  return (T and T.DividerThickness and T.DividerThickness()) or 1
end

-- Media
local ICON_PATH  = "Interface\\AddOns\\PaladinHolyPower\\media\\paladin_holy_power.png"

-- Tabs list -> builders (your modules)
local tabNames = { "Home", "Holy Power", "Stats", "Information" }
local tabBuilders = {
  function(parent)
    if HomeTab and HomeTab.Build and PHP.settings and PHP.settings.HPL then
      HomeTab.Build(parent, PHP, PHP.settings.HPL)
    end
  end,
  function(parent)
    if HolyPowerTab and HolyPowerTab.Build and PHP.settings and PHP.settings.HP then
      HolyPowerTab.Build(parent, PHP, PHP.settings.HP)
    end
  end,
  function(parent)
    if StatsTab and StatsTab.Build and PHP.settings then
      StatsTab.Build(parent, PHP, PHP.settings)
    end
  end,
  function(parent)
    if InfoTab and InfoTab.Build and PHP.settings then
      InfoTab.Build(parent, PHP, PHP.settings)
    end
  end,
}

-- Colors for sidebar tabs
local COLOR_TAB_N = { 0.22, 0.20, 0.14, 1.00 }
local COLOR_TAB_A = { 0.13, 0.12, 0.10, 1.00 }
local TEXT_N      = { 1.00, 1.00, 1.00, 0.95 }
local TEXT_A      = { 1.00, 0.95, 0.75, 1.00 }

-- --- Minimal helpers (just what we need) ---
local PixelUtil = _G.PixelUtil
local function ApplyBG(frame, tint)
  frame:SetBackdrop({ bgFile = PanelTex() })
  frame:SetBackdropColor(tint[1], tint[2], tint[3], tint[4])
end

local function Recolor(tex)
  local c = PHP.ACCENT_COLOR or {1,1,1,1}
  tex:SetColorTexture(c[1], c[2], c[3], c[4])
end

local function DrawH(line, frame, yFromTop)
  line:ClearAllPoints()
  local thick = DividerThickness()
  if PixelUtil and PixelUtil.SetPoint then
    PixelUtil.SetPoint(line, "TOPLEFT",  frame, "TOPLEFT",  0, -yFromTop)
    PixelUtil.SetPoint(line, "TOPRIGHT", frame, "TOPRIGHT", 0, -yFromTop)
    PixelUtil.SetHeight(line, thick)
  else
    line:SetPoint("TOPLEFT",  frame, "TOPLEFT",  0, -yFromTop)
    line:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, -yFromTop)
    line:SetHeight(thick)
  end
end

local function DrawV(line, frame, xFromLeft, yTop, yBottom)
  line:ClearAllPoints()
  local thick = DividerThickness()
  if PixelUtil and PixelUtil.SetPoint then
    PixelUtil.SetPoint(line, "TOPLEFT",    frame, "TOPLEFT", xFromLeft, -yTop)
    PixelUtil.SetPoint(line, "BOTTOMLEFT", frame, "TOPLEFT", xFromLeft, -yBottom)
    PixelUtil.SetWidth(line, thick)
  else
    line:SetPoint("TOPLEFT",    frame, "TOPLEFT", xFromLeft, -yTop)
    line:SetPoint("BOTTOMLEFT", frame, "TOPLEFT", xFromLeft, -yBottom)
    line:SetWidth(thick)
  end
end

local function StopAnimators(root)
  if not root or not root.GetChildren then return end
  if root:GetScript("OnUpdate") then root:SetScript("OnUpdate", nil) end
  if root._gloss and root._gloss.GetAlpha then root._gloss:SetAlpha(0) end
  if root._ink   and root._ink.GetAlpha   then root._ink:SetAlpha(0)   end
  for i = 1, select("#", root:GetChildren()) do
    StopAnimators(select(i, root:GetChildren()))
  end
end

local function lerp(a, b, t) return a + (b - a) * t end

-- --- Sidebar Tab Button (stripe grows from CENTER) ---
local function CreateSidebarTabButton(parent, label)
  local white = WhiteTex()
  local btn = CreateFrame("Button", nil, parent, "BackdropTemplate")
  btn:SetSize(SIDEBAR_W - 16, 28)
  btn:SetBackdrop({ bgFile = white })
  btn:SetBackdropColor(COLOR_TAB_N[1], COLOR_TAB_N[2], COLOR_TAB_N[3], COLOR_TAB_N[4])
  btn.__active = false

  -- Left accent stripe
  local stripe = btn:CreateTexture(nil, "OVERLAY", nil, 3)
  stripe:SetTexture(white)
  local initialTopOffset = -((btn:GetHeight() or 28) / 2)
  stripe:SetPoint("TOPLEFT", btn, "TOPLEFT", 0, initialTopOffset)
  stripe:SetWidth(2)
  stripe:SetHeight(0)
  Recolor(stripe)
  stripe:SetAlpha(0)
  btn._stripe = stripe

  -- Ink + gloss
  local ink = btn:CreateTexture(nil, "BACKGROUND")
  ink:SetTexture(white)  ink:SetAllPoints(btn)
  ink:SetVertexColor(1,1,1,1)  ink:SetAlpha(0)
  btn._ink = ink

  local gloss = btn:CreateTexture(nil, "OVERLAY", nil, 1)
  gloss:SetAllPoints(btn)  gloss:SetTexture(white)  gloss:SetBlendMode("ADD")
  if gloss.SetGradient and CreateColor then
    gloss:SetGradient("VERTICAL", CreateColor(1,1,1,0.10), CreateColor(1,1,1,0.00))
  else
    gloss:SetVertexColor(1,1,1,0.05)
  end
  gloss:SetAlpha(0)
  btn._gloss = gloss

  -- Label
  local fs = btn:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  fs:SetPoint("LEFT", btn, "LEFT", 10, 0)
  fs:SetJustifyH("LEFT")
  fs:SetText(label or "")
  fs:SetTextColor(TEXT_N[1], TEXT_N[2], TEXT_N[3], TEXT_N[4])
  btn.Text = fs
  btn._labelPlain = label -- <— store original for gradient swap

  -- Animated state targets
  btn._state = {
    targetBG      = { COLOR_TAB_N[1], COLOR_TAB_N[2], COLOR_TAB_N[3], COLOR_TAB_N[4] },
    targetText    = { TEXT_N[1], TEXT_N[2], TEXT_N[3], TEXT_N[4] },
    inkAlpha      = 0,
    stripeAlpha   = 0,
    stripeHTarget = 0,
    speed         = 18,
  }

  local function RunAnim(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 18))

    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)

    if self.Text and self.Text.GetTextColor then
      local tr,tg,tb,ta = self.Text:GetTextColor()
      tr = lerp(tr, s.targetText[1], k); tg = lerp(tg, s.targetText[2], k)
      tb = lerp(tb, s.targetText[3], k); ta = lerp(ta, s.targetText[4], k)
      self.Text:SetTextColor(tr,tg,tb,ta)
    end

    self._ink:SetAlpha(lerp(self._ink:GetAlpha(), s.inkAlpha or 0, k))

    local btnH = self:GetHeight() or 28
    self._stripe:SetAlpha(lerp(self._stripe:GetAlpha(), s.stripeAlpha or 0, k))
    local curH = self._stripe:GetHeight() or 0
    local newH = lerp(curH, math.min(s.stripeHTarget or 0, btnH), k)
    local topOffset = -((btnH - newH) / 2)
    self._stripe:ClearAllPoints()
    self._stripe:SetPoint("TOPLEFT", self, "TOPLEFT", 0, topOffset)
    self._stripe:SetHeight(newH)

    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(self._ink:GetAlpha() - (s.inkAlpha or 0)) < 0.001
       and math.abs(newH - (s.stripeHTarget or 0)) < 0.5 then
      self:SetScript("OnUpdate", nil)
      self._animating = false
    end
  end

  local function Kick(self) self._animating = true; self:SetScript("OnUpdate", RunAnim) end
  btn.__Kick = Kick

  btn:SetScript("OnEnter", function(self)
    self._state.inkAlpha = self.__active and 0.08 or 0.06
    self._gloss:SetAlpha(1)
    Kick(self)
  end)
  btn:SetScript("OnLeave", function(self)
    self._state.inkAlpha = self.__active and 0.08 or 0
    self._gloss:SetAlpha(self.__active and 1 or 0)
    Kick(self)
  end)
  btn:SetScript("OnMouseDown", function(self)
    self._state.inkAlpha = self.__active and 0.10 or 0.12
    Kick(self)
  end)
  btn:SetScript("OnMouseUp", function(self)
    self._state.inkAlpha = self.__active and 0.08 or 0
    Kick(self)
  end)

  return btn
end

-- Active tab controller
local function SetActiveTabFactory(tabs, panels, built)
  local activeIndex = 1
  return function(index)
    local prev = activeIndex
    if panels[prev] and prev ~= index then panels[prev]:Hide() end

    if not built[index] and tabBuilders[index] then
      tabBuilders[index](panels[index]); built[index] = true
    end
    if panels[index] and not panels[index]:IsShown() then panels[index]:Show() end

    for i, btn in ipairs(tabs) do
      btn._state = btn._state or {
        targetBG      = { unpack(COLOR_TAB_N) },
        targetText    = { unpack(TEXT_N) },
        inkAlpha      = 0, stripeAlpha = 0, stripeHTarget = 0, speed = 18,
      }
      local active = (i == index)
      btn.__active = active
      local s = btn._state

      if active then
        s.targetBG      = { COLOR_TAB_A[1], COLOR_TAB_A[2], COLOR_TAB_A[3], COLOR_TAB_A[4] }
        s.targetText    = { TEXT_A[1], TEXT_A[2], TEXT_A[3], TEXT_A[4] }
        s.inkAlpha      = 0.08; s.stripeAlpha = 1
        s.stripeHTarget = btn:GetHeight() or 28
        btn._gloss:SetAlpha(1)
      else
        s.targetBG      = { COLOR_TAB_N[1], COLOR_TAB_N[2], COLOR_TAB_N[3], COLOR_TAB_N[4] }
        s.targetText    = { TEXT_N[1], TEXT_N[2], TEXT_N[3], TEXT_N[4] }
        s.inkAlpha      = 0; s.stripeAlpha = 0
        s.stripeHTarget = 0
        btn._gloss:SetAlpha( btn:IsMouseOver() and 1 or 0 )
      end

      -- Apply gradient text when active, plain when inactive (read Theme at call time)
      if btn.Text and btn._labelPlain and PHP and PHP.Theme and PHP.Theme.ApplyGradientText then
        if btn.__active then
          PHP.Theme.ApplyGradientText(btn.Text, btn._labelPlain, nil, nil, { outline = true })
        else
          btn.Text:SetText(btn._labelPlain)
        end
      end

      if btn.__Kick then btn:__Kick() end
    end

    activeIndex = index
  end
end

-- ====================================================================
-- Build/Show panel
-- ====================================================================
function PHP.ShowSettingsPanel()
  if not PHP.settings then return end

  if PHP.SettingsPanel then
    if PHP.SettingsPanel:IsShown() then
      PHP.SettingsPanel:Hide()
    else
      if InCombat() then return end
      PHP.SettingsPanel:Show()
    end
    return
  end

  if InCombat() then return end

  -- Root
  local opt = CreateFrame("Frame", "PaladinHolyPowerOptions", UIParent, "BackdropTemplate")
  opt:SetSize(PANEL_W, PANEL_H)
  opt:SetPoint("CENTER")
  ApplyBG(opt, TintRoot())
  opt:SetFrameStrata("DIALOG")
  opt:SetMovable(true); opt:EnableMouse(true)
  opt:RegisterForDrag("LeftButton")
  opt:SetScript("OnDragStart", opt.StartMoving)
  opt:SetScript("OnDragStop",  opt.StopMovingOrSizing)
  if UISpecialFrames then table.insert(UISpecialFrames, opt:GetName()) end

  -- Header
  local header = CreateFrame("Frame", nil, opt, "BackdropTemplate")
  header:SetPoint("TOPLEFT", 0, 0)
  header:SetPoint("TOPRIGHT", 0, 0)
  header:SetHeight(HEADER_HEIGHT)
  ApplyBG(header, TintHeader())

  -- Icon + title
  local icon = header:CreateTexture(nil, "ARTWORK")
  icon:SetSize(32, 32)
  icon:SetPoint("TOPLEFT", 10, -((HEADER_HEIGHT - 32) / 2))
  icon:SetTexture(ICON_PATH)

  local title = header:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
  title:SetPoint("LEFT", icon, "RIGHT", 10, 0)

  -- === Header text gradient from Theme ===
  -- Uses Theme's current gradient endpoints (left/right) and helper for font edge.
  do
    local text = "Paladin Holy Power"
    if PHP and PHP.Theme and PHP.Theme.ApplyGradientText then
      PHP.Theme.ApplyGradientText(title, text, nil, nil, { sizeDelta = 8, outline = true, shadowA = 0.9 })
    else
      -- Fallback: plain text with bigger outlined font
      local f, sz, fl = title:GetFont()
      title:SetFont(f, (tonumber(sz) or 14) + 8, (fl and fl ~= "") and fl or "OUTLINE")
      title:SetText(text)
    end
  end

  -- Edit button (optional)
  if Buttons and Buttons.AddButton then
    local editBtn = Buttons.AddButton(header, PHP, PHP.settings, 0, 0, "edit_mode")
    if editBtn then editBtn:ClearAllPoints(); editBtn:SetPoint("TOPRIGHT", -40, -12) end
  end

  -- Close button
  local close = CreateFrame("Frame", nil, opt)
  close:SetSize(14, 14)
  close:SetPoint("TOPRIGHT", -6, -6)
  close:EnableMouse(true)
  local l1 = close:CreateTexture(nil, "OVERLAY"); l1:SetTexture(WhiteTex()); l1:SetVertexColor(1,1,1,1); l1:SetSize(2,14); l1:SetPoint("CENTER"); l1:SetRotation(math.rad(45))
  local l2 = close:CreateTexture(nil, "OVERLAY"); l2:SetTexture(WhiteTex()); l2:SetVertexColor(1,1,1,1); l2:SetSize(2,14); l2:SetPoint("CENTER"); l2:SetRotation(math.rad(-45))
  close:SetScript("OnEnter", function() l1:SetVertexColor(.85,.85,.85); l2:SetVertexColor(.85,.85,.85) end)
  close:SetScript("OnLeave", function() l1:SetVertexColor(1,1,1,1);     l2:SetVertexColor(1,1,1,1)     end)
  close:SetScript("OnMouseUp", function() opt:Hide() end)

  -- Body containers
  local body = CreateFrame("Frame", nil, opt)
  body:SetPoint("TOPLEFT", 0, -HEADER_HEIGHT)
  body:SetPoint("BOTTOMRIGHT", 0, 0)

  local sidebar = CreateFrame("Frame", nil, body, "BackdropTemplate")
  sidebar:SetPoint("TOPLEFT", 0, 0)
  sidebar:SetPoint("BOTTOMLEFT", 0, 0)
  sidebar:SetWidth(SIDEBAR_W)
  ApplyBG(sidebar, TintSidebar())

  local content = CreateFrame("Frame", nil, body, "BackdropTemplate")
  content:SetPoint("TOPLEFT", SIDEBAR_W, 0)
  content:SetPoint("BOTTOMRIGHT", 0, 0)
  ApplyBG(content, TintContent())

  -- Tabs + Panels
  local tabs, panels, built = {}, {}, {}
  local function AddTab(name, builder)
    local idx = #tabs + 1
    local b = CreateSidebarTabButton(sidebar, name)

    -- Base vertical layout is 8px top padding, 32px step per tab.
    -- We add a one-time HOME_EXTRA_GAP after the first tab.
    local y = -8 - (idx - 1) * 32
    if idx >= 2 then y = y - HOME_EXTRA_GAP end

    b:SetPoint("TOPLEFT", sidebar, "TOPLEFT", 8, y)
    tabs[idx] = b

    local p = CreateFrame("Frame", nil, content)
    p:SetAllPoints(); p:Hide()
    panels[idx] = p
    p.Build = function() if builder then builder(p) end end
  end

  AddTab(tabNames[1], tabBuilders[1])
  AddTab(tabNames[2], tabBuilders[2])
  AddTab(tabNames[3], tabBuilders[3])
  AddTab(tabNames[4], tabBuilders[4])

  local SetActive = SetActiveTabFactory(tabs, panels, built)
  for i = 1, #tabs do
    local idx = i
    tabs[i]:SetScript("OnClick", function()
      if not built[idx] then panels[idx].Build(); built[idx] = true end
      SetActive(idx)
    end)
  end

  -- Build + select first
  if not built[1] then panels[1].Build(); built[1] = true end
  panels[1]:Show()
  for i, btn in ipairs(tabs) do
    local active = (i == 1)
    btn.__active = active
    local s = btn._state
    if active then
      s.targetBG      = { COLOR_TAB_A[1], COLOR_TAB_A[2], COLOR_TAB_A[3], COLOR_TAB_A[4] }
      s.targetText    = { TEXT_A[1], TEXT_A[2], TEXT_A[3], TEXT_A[4] }
      s.inkAlpha      = 0.08; s.stripeAlpha = 1
      s.stripeHTarget = btn:GetHeight() or 28
      btn._gloss:SetAlpha(1)
    else
      s.targetBG      = { COLOR_TAB_N[1], COLOR_TAB_N[2], COLOR_TAB_N[3], COLOR_TAB_N[4] }
      s.targetText    = { TEXT_N[1], TEXT_N[2], TEXT_N[3], TEXT_N[4] }
      s.inkAlpha      = 0; s.stripeAlpha = 0
      s.stripeHTarget = 0
      btn._gloss:SetAlpha(0)
    end

    if btn.Text and btn._labelPlain and PHP and PHP.Theme and PHP.Theme.ApplyGradientText then
      if btn.__active then
        PHP.Theme.ApplyGradientText(btn.Text, btn._labelPlain, nil, nil, { outline = true })
      else
        btn.Text:SetText(btn._labelPlain)
      end
    end

    if btn.__Kick then btn:__Kick() end
  end

  -- Lifecycle
  opt:SetScript("OnShow", function() PHP._SettingsPanelOpen = true end)
  opt:SetScript("OnHide", function()
    PHP._SettingsPanelOpen = false
    if PHP.HideAllEditHandles then pcall(PHP.HideAllEditHandles) end
    PHP.EditModeActive = false
    PHP._ActiveHPSubTab = nil
    if PHP.UpdateHPTracker      then pcall(PHP.UpdateHPTracker) end
    if PHP._HPL_ApplyVisibility then pcall(PHP._HPL_ApplyVisibility) end
    StopAnimators(opt)
  end)

  PHP.SettingsPanel = opt

  -- Auto-close on entering combat
  if not PHP._settingsPanelCombatFrame then
    local f = CreateFrame("Frame")
    f:RegisterEvent("PLAYER_REGEN_DISABLED")
    f:SetScript("OnEvent", function()
      if PHP.SettingsPanel and PHP.SettingsPanel:IsShown() then PHP.SettingsPanel:Hide() end
    end)
    PHP._settingsPanelCombatFrame = f
  end

  opt:Show()
end