local ADDON_NAME, ns = ...
local WF = ns.WF

WF.UI = WF.UI or {}
WF.UI.HelpPages = WF.UI.HelpPages or {}
WF.UI.HelpPages.OverviewFarmTimer = WF.UI.HelpPages.OverviewFarmTimer or {}

local Modules = WF.UI.HelpPages.OverviewFarmTimer

function Modules.EnsureCore(ctx, env)
  local FT = WF.FarmTimer
  if not FT then
    FT = {}
    WF.FarmTimer = FT
  end

  if not FT.cfg then
    FT.cfg = {
      kill = "1:45",
      loot = "0:15",
      grace = "0:05",
      loop = true,
      party = false,
      hud = true,
      hudUnlock = false,
      warn = 10,
    }
  end

  FT.state = FT.state or { running = false, paused = false, pauseRem = nil, phase = "Kill", endsAt = 0, warned = false }

  if FT._coreInited then
    return FT
  end
  FT._coreInited = true

  local C4 = env.C4
  local TEXT = env.TEXT
  local MUTED = env.MUTED
  local ACCENT = env.ACCENT

local function _Trim(s)
  s = tostring(s or "")
  s = s:gsub("^%s+", ""):gsub("%s+$", "")
  return s
end
  
function FT:ParseTime(s)
  s = _Trim(s)
  if s == "" then return 0 end
  
  local a, b, c = s:match("^(%d+)%:(%d+)%:(%d+)$")
  if a then
    return (tonumber(a) or 0) * 3600 + (tonumber(b) or 0) * 60 + (tonumber(c) or 0)
  end
  
  local m, ss = s:match("^(%d+)%:(%d+)$")
  if m then
    return (tonumber(m) or 0) * 60 + (tonumber(ss) or 0)
  end
  
  local n = tonumber(s)
  if n then return math.floor(n + 0.00001) end
  return 0
end
  
function FT:FmtClock(sec)
  sec = tonumber(sec) or 0
  if sec < 0 then sec = 0 end
  sec = math.floor(sec + 0.00001)
  local m = math.floor(sec / 60)
  local s = sec % 60
  return string.format("%d:%02d", m, s)
end
  

function FT:_EnsureTicker()
  if FT._ticker then return end
  local f = CreateFrame("Frame")
  f:Hide()
  f:SetScript("OnUpdate", function(_, _)
    FT:Tick()
  end)
  FT._ticker = f
end

function FT:_SetPhase(phase, dur)
  self.state.phase = phase or "Kill"
  self.state.endsAt = (GetTime() or 0) + (tonumber(dur) or 0)
  self.state.warned = false
  self:UpdateUI(true)
end
  
function FT:Start()
  local cfg = self.cfg or {}
  local k = self:ParseTime(cfg.kill)
  local l = self:ParseTime(cfg.loot)
  local g = self:ParseTime(cfg.grace)
  
  if k < 1 then k = 1 end
  if l < 0 then l = 0 end
  if g < 0 then g = 0 end
  
  self.state.running = true
  self.state.paused = false
  self.state.pauseRem = nil
  self.state.k = k
  self.state.l = l
  self.state.g = g
  
  self:_EnsureTicker()
  self._ticker:Show()
  
  if cfg.hud then
    self:_ShowHUD(true)
  else
    self:_ShowHUD(false)
  end
  
  self:_SetPhase("Kill", k)
  local msg = self:_PhaseStartMsg("Kill")
  self:_RaidWarn(msg)
  self:_GroupAnnounce(msg)
end
  
function FT:Stop()
  self.state.running = false
  self.state.paused = false
  self.state.pauseRem = nil
  self.state.warned = false
  if self._ticker then self._ticker:Hide() end
  self:_ShowHUD(false)
  self:UpdateUI(true)
end
  
function FT:Pause()
  if not (self.state and self.state.running) then return end
  if self.state.paused then return end
  
  local now = GetTime() or 0
  local rem = (self.state.endsAt or 0) - now
  if rem < 0 then rem = 0 end
  
  self.state.paused = true
  self.state.pauseRem = rem
  
  if self._ticker then self._ticker:Hide() end
  self:UpdateUI(true)
end
  
function FT:Resume()
  if not (self.state and self.state.running) then return end
  if not self.state.paused then return end
  
  local now = GetTime() or 0
  local rem = tonumber(self.state.pauseRem) or 0
  if rem < 0 then rem = 0 end
  
  self.state.paused = false
  self.state.pauseRem = nil
  self.state.endsAt = now + rem
  
  self:_EnsureTicker()
  if self._ticker then self._ticker:Show() end
  self:UpdateUI(true)
end
  
function FT:NextPhase()
  local st = self.state
  local cfg = self.cfg or {}
  if st.phase == "Kill" then
    if (st.l or 0) > 0 then
      self:_SetPhase("Loot", st.l)
      local msg = self:_PhaseStartMsg("Loot")
      self:_RaidWarn(msg)
      self:_GroupAnnounce(msg)
      return
    end
    if (st.g or 0) > 0 then
      self:_SetPhase("Grace", st.g)
      local msg = self:_PhaseStartMsg("Grace")
      self:_RaidWarn(msg)
      self:_GroupAnnounce(msg)
      return
    end
    if cfg.loop then
      self:_SetPhase("Kill", st.k)
      local msg = self:_PhaseStartMsg("Kill")
      self:_RaidWarn(msg)
      self:_GroupAnnounce(msg)
    else
      self:Stop()
    end
    return
  end
  
  if st.phase == "Loot" then
    if (st.g or 0) > 0 then
      self:_SetPhase("Grace", st.g)
      local msg = self:_PhaseStartMsg("Grace")
      self:_RaidWarn(msg)
      self:_GroupAnnounce(msg)
      return
    end
    if cfg.loop then
      self:_SetPhase("Kill", st.k)
      local msg = self:_PhaseStartMsg("Kill")
      self:_RaidWarn(msg)
      self:_GroupAnnounce(msg)
    else
      self:Stop()
    end
    return
  end
  
  -- Grace -> back to Kill (loop) or stop
  if cfg.loop then
    self:_SetPhase("Kill", st.k)
    local msg = self:_PhaseStartMsg("Kill")
    self:_RaidWarn(msg)
    self:_GroupAnnounce(msg)
  else
    self:Stop()
  end
end
  
function FT:UpdateUI(force)
  local st = self.state
  if not st then return end
  
  local phase = st.phase or "Kill"
  local rem = 0
  
  if st.running then
    if st.paused then
      rem = tonumber(st.pauseRem)
      if not rem then
        rem = (st.endsAt or 0) - (GetTime() or 0)
      end
    else
      rem = (st.endsAt or 0) - (GetTime() or 0)
    end
  end
  
  if rem < 0 then rem = 0 end
  
  local ar, ag, ab = C4(ACCENT, TEXT)
  
  local mr, mg, mb = C4(MUTED, MUTED)
  local now = GetTime() or 0
  local pulse = (math.floor(now * 2) % 2) == 0
  
  if self._uiStatus and self._uiStatus.SetText then
    if st.running then
      local ar8 = math.floor((ar or 0) * 255 + 0.5)
      local ag8 = math.floor((ag or 0) * 255 + 0.5)
      local ab8 = math.floor((ab or 0) * 255 + 0.5)
      local mr8 = math.floor((mr or 0) * 255 + 0.5)
      local mg8 = math.floor((mg or 0) * 255 + 0.5)
      local mb8 = math.floor((mb or 0) * 255 + 0.5)
  
      local timeCode
      if st.paused then
        local pa = pulse and 255 or 140
        timeCode = string.format("|c%02x%02x%02x%02x", pa, mr8, mg8, mb8)
      else
        timeCode = string.format("|cff%02x%02x%02x", ar8, ag8, ab8)
      end
  
      local pausedCode = string.format("|cff%02x%02x%02x", mr8, mg8, mb8)
      local line = tostring(phase) .. " • " .. timeCode .. self:FmtClock(rem) .. "|r"
      if st.paused then
        line = line .. " • " .. pausedCode .. "Paused|r"
      end
  
      self._uiStatus:SetText(line)
      if self._uiStatus.SetTextColor then
        self._uiStatus:SetTextColor(C4(TEXT, TEXT))
      end
    else
      self._uiStatus:SetText("")
      if self._uiStatus.SetTextColor then
        self._uiStatus:SetTextColor(C4(MUTED, MUTED))
      end
    end
  end
  
  -- update overview buttons (Start -> Pause/Resume + Stop)
  if self._uiLayoutButtons then
    local key = 0
    if st.running then key = 10 end
    if st.paused then key = key + 1 end
  
    if force or (self._uiBtnState ~= key) then
      self._uiBtnState = key
      self._uiLayoutButtons(st.running)
    end
  end
  
  if self._uiStart and self._uiStart.SetText then
    if st.running then
      if st.paused then
        self._uiStart:SetText("Resume")
      else
        self._uiStart:SetText("Pause")
      end
    else
      self._uiStart:SetText("Start Timer")
    end
  end
  
  if self._uiStop then
    if st.running then
      if self._uiStop.Show then self._uiStop:Show() end
    else
      if self._uiStop.Hide then self._uiStop:Hide() end
    end
  end
  
  -- HUD update
  if self.hud then
    if st.running then
      if self.hud.title and self.hud.title.SetText then
        self.hud.title:SetText("WF Timer")
      end
  
      if self.hud.phaseText and self.hud.phaseText.SetText then
        if phase and phase ~= "" then
          self.hud.phaseText:SetText("Phase: " .. tostring(phase))
        else
          self.hud.phaseText:SetText("")
        end
      end
  
      if self.hud.stateText and self.hud.stateText.SetText then
        if st.paused then
          self.hud.stateText:SetText("Paused")
        else
          self.hud.stateText:SetText("")
        end
      end
  
      if self.hud.timeText and self.hud.timeText.SetText then
        self.hud.timeText:SetText(self:FmtClock(rem))
        if self.hud.timeText.SetTextColor then
          if st.paused then
            self.hud.timeText:SetTextColor(mr, mg, mb, 0.88)
          else
            self.hud.timeText:SetTextColor(ar, ag, ab, 1)
          end
        end
      end
  
      if self.hud.btnPause and self.hud.btnPause.txt and self.hud.btnPause.txt.SetText then
        if st.paused then
          self.hud.btnPause.txt:SetText("Resume")
        else
          self.hud.btnPause.txt:SetText("Pause")
        end
      end
  
      if self.hud.btnPause then
        if self.hud.btnPause.Show then self.hud.btnPause:Show() end
      end
      if self.hud.btnStop then
        if self.hud.btnStop.Show then self.hud.btnStop:Show() end
      end
    else
      if self.hud.phaseText and self.hud.phaseText.SetText then
        self.hud.phaseText:SetText("")
      end
      if self.hud.stateText and self.hud.stateText.SetText then
        self.hud.stateText:SetText("")
      end
      if self.hud.btnPause then
        if self.hud.btnPause.Hide then self.hud.btnPause:Hide() end
      end
      if self.hud.btnStop then
        if self.hud.btnStop.Hide then self.hud.btnStop:Hide() end
      end
    end
  end
end
  
function FT:Tick()
  if not (self.state and self.state.running) then return end
  if self.state.paused then
    self:UpdateUI(false)
    return
  end
  
  local now = GetTime() or 0
  local rem = (self.state.endsAt or 0) - now
  if rem < 0 then rem = 0 end
  
  local warnAt = tonumber((self.cfg and self.cfg.warn) or 10) or 10
  if warnAt < 1 then warnAt = 1 end
  
  if (not self.state.warned) and rem <= warnAt then
    self.state.warned = true
    local msg = self:_PhaseWarnMsg(self.state.phase, warnAt)
    self:_RaidWarn(msg)
    self:_GroupAnnounce(msg)
    self:_DoFlash()
  end
  
  if rem <= 0 then
    self:NextPhase()
    return
  end
  
  self:UpdateUI(false)
end

  return FT
end
