local NEWS_VERSION = "0.9 [ALPHA]"
local NEWS_TITLE_R, NEWS_TITLE_G, NEWS_TITLE_B, NEWS_TITLE_A = 0.60, 0.90, 1.00, 1.0
local NEWS_BULLET = string.char(226, 128, 162) .. " "
local updateNewsWindow

local NEWS_ENTRY = {
  version = "Version 0.9 [ALPHA] - 2026-05-26",
  message = "Welcome to the Alpha Testing :)",
  sections = {},
}

local function ResolveApiFunction(name)
  local api = rawget(_G, "LIDCOUNCIL_API")
  if type(api) == "table" and type(api[name]) == "function" then
    return api[name]
  end
  local fallback = rawget(_G, name)
  if type(fallback) == "function" then
    return fallback
  end
  return nil
end

local function Print(msg)
  local printFn = ResolveApiFunction("LIDCOUNCIL_Print")
  if printFn then
    printFn(msg)
    return
  end
  if DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.AddMessage then
    DEFAULT_CHAT_FRAME:AddMessage("|cff66ccff[LidCouncil]|r " .. tostring(msg))
  end
end

local function RootDB()
  local getRoot = ResolveApiFunction("LIDCOUNCIL_RootDB")
  if type(getRoot) == "function" then
    local ok, root = pcall(getRoot)
    if ok and type(root) == "table" then
      root.ui = root.ui or {}
      return root
    end
  end
  _G.LidCouncilDB = _G.LidCouncilDB or {}
  _G.LidCouncilDB.ui = _G.LidCouncilDB.ui or {}
  return _G.LidCouncilDB
end

local function GetNewsLine(win, index)
  win.newsLines = win.newsLines or {}
  local fs = win.newsLines[index]
  if not fs then
    fs = win.content:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    fs:SetJustifyH("LEFT")
    win.newsLines[index] = fs
  end
  return fs
end

local function HideUnusedNewsLines(win, fromIndex)
  local lines = win.newsLines or {}
  for i = fromIndex, #lines do
    lines[i]:Hide()
  end
end

local function LayoutNewsWindow(win)
  if not win or not win.content then return end

  local width = (win.content:GetWidth() or 0)
  if width < 220 then width = 220 end

  local lineIndex, y = 1, 0

  local versionLine = GetNewsLine(win, lineIndex)
  lineIndex = lineIndex + 1
  versionLine:ClearAllPoints()
  versionLine:SetPoint("TOPLEFT", win.content, "TOPLEFT", 0, y)
  versionLine:SetWidth(width)
  versionLine:SetText(NEWS_ENTRY.version or "")
  do
    local vf, _, vflags = versionLine:GetFont()
    versionLine:SetFont(vf, 16, vflags)
  end
  versionLine:SetTextColor(NEWS_TITLE_R, NEWS_TITLE_G, NEWS_TITLE_B, NEWS_TITLE_A)
  versionLine:Show()
  y = y - ((versionLine:GetStringHeight() or 0) + 10)

  if type(NEWS_ENTRY.message) == "string" and NEWS_ENTRY.message ~= "" then
    local messageLine = GetNewsLine(win, lineIndex)
    lineIndex = lineIndex + 1
    messageLine:ClearAllPoints()
    messageLine:SetPoint("TOPLEFT", win.content, "TOPLEFT", 0, y)
    messageLine:SetWidth(width)
    messageLine:SetText(NEWS_ENTRY.message)
    do
      local mf, _, mflags = messageLine:GetFont()
      messageLine:SetFont(mf, 13, mflags)
    end
    messageLine:SetTextColor(0.9, 0.9, 0.9, 1.0)
    messageLine:Show()
    y = y - ((messageLine:GetStringHeight() or 0) + 12)
  end

  for _, section in ipairs(NEWS_ENTRY.sections or {}) do
    local sectionLine = GetNewsLine(win, lineIndex)
    lineIndex = lineIndex + 1
    sectionLine:ClearAllPoints()
    sectionLine:SetPoint("TOPLEFT", win.content, "TOPLEFT", 0, y)
    sectionLine:SetWidth(width)
    sectionLine:SetText(section.title or "")
    do
      local sf, _, sflags = sectionLine:GetFont()
      sectionLine:SetFont(sf, 14, sflags)
    end
    sectionLine:SetTextColor(NEWS_TITLE_R, NEWS_TITLE_G, NEWS_TITLE_B, NEWS_TITLE_A)
    sectionLine:Show()
    y = y - ((sectionLine:GetStringHeight() or 0) + 4)

    for _, bulletText in ipairs(section.bullets or {}) do
      local bulletLine = GetNewsLine(win, lineIndex)
      lineIndex = lineIndex + 1
      bulletLine:ClearAllPoints()
      bulletLine:SetPoint("TOPLEFT", win.content, "TOPLEFT", 8, y)
      bulletLine:SetWidth(width - 8)
      bulletLine:SetText(NEWS_BULLET .. tostring(bulletText))
      do
        local bf, _, bflags = bulletLine:GetFont()
        bulletLine:SetFont(bf, 13, bflags)
      end
      bulletLine:SetTextColor(0.9, 0.9, 0.9, 1.0)
      bulletLine:Show()
      y = y - ((bulletLine:GetStringHeight() or 0) + 2)
    end

    y = y - 8
  end

  HideUnusedNewsLines(win, lineIndex)
  win.content:SetHeight(math.max(1, -y))
end

local function EnsureUpdateNewsWindow()
  if updateNewsWindow and updateNewsWindow.GetObjectType then
    return updateNewsWindow
  end

  local win = CreateFrame("Frame", "LIDCOUNCIL_UpdateNewsWindow", UIParent, "BackdropTemplate")
  win:SetSize(560, 320)
  win:SetPoint("CENTER", UIParent, "CENTER", 0, -70)
  win:SetFrameStrata("DIALOG")
  win:SetFrameLevel(200)
  win:SetClampedToScreen(true)
  win:SetMovable(true)
  win:EnableMouse(true)
  win:RegisterForDrag("LeftButton")
  win:SetScript("OnDragStart", function(self)
    self:StartMoving()
  end)
  win:SetScript("OnDragStop", function(self)
    self:StopMovingOrSizing()
  end)

  if win.SetBackdrop then
    win:SetBackdrop({
      bgFile = "Interface/Buttons/WHITE8x8",
      edgeFile = "Interface/Buttons/WHITE8x8",
      tile = false,
      edgeSize = 1,
      insets = { left = 1, right = 1, top = 1, bottom = 1 },
    })
    win:SetBackdropColor(0.03, 0.03, 0.04, 0.95)
    win:SetBackdropBorderColor(0.20, 0.22, 0.28, 0.95)
  end

  local logo = win:CreateTexture(nil, "ARTWORK")
  logo:SetPoint("TOPLEFT", win, "TOPLEFT", 16, -16)
  logo:SetSize(56, 56)
  logo:SetTexture("Interface\\AddOns\\LidCouncil\\Media\\LidCouncil\\Logos\\LidCouncil_HeaderLogo.tga")

  local title = win:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
  title:SetPoint("TOPLEFT", win, "TOPLEFT", 82, -24)
  title:SetTextColor(NEWS_TITLE_R, NEWS_TITLE_G, NEWS_TITLE_B, NEWS_TITLE_A)
  title:SetText("LidCouncil Update News")

  local content = CreateFrame("Frame", nil, win)
  content:SetPoint("TOPLEFT", win, "TOPLEFT", 18, -102)
  content:SetPoint("TOPRIGHT", win, "TOPRIGHT", -18, -102)
  content:SetHeight(10)
  win.content = content

  local closeBtn = CreateFrame("Button", nil, win, "UIPanelButtonTemplate")
  closeBtn:SetSize(140, 22)
  closeBtn:SetPoint("BOTTOM", win, "BOTTOM", 0, 16)
  closeBtn:SetText("Cool! Thanks!")
  closeBtn:SetScript("OnClick", function()
    win:Hide()
  end)

  win:SetScript("OnSizeChanged", function(self)
    pcall(function()
      LayoutNewsWindow(self)
    end)
  end)

  LayoutNewsWindow(win)
  updateNewsWindow = win
  return win
end

local function ShowUpdateNewsDialog()
  local win = EnsureUpdateNewsWindow()
  if not win then return nil end
  win:Show()
  if win.Raise then
    win:Raise()
  end
  return win
end

local function UpdateNews_OnLogin()
  local root = RootDB()
  local ui = root.ui
  if ui.updateNewsSeenVersion == NEWS_VERSION then
    return false
  end
  ui.updateNewsPendingVersion = NEWS_VERSION
  if ui.updateNewsNoticeVersion ~= NEWS_VERSION then
    Print("Update " .. NEWS_VERSION .. " available. Open /lidcouncil to review the changes once.")
    ui.updateNewsNoticeVersion = NEWS_VERSION
  end
  return true
end

local function UpdateNews_OnEditorOpen()
  local root = RootDB()
  local ui = root.ui
  if ui.updateNewsSeenVersion == NEWS_VERSION then
    return false
  end
  if ui.updateNewsPendingVersion ~= NEWS_VERSION then
    return false
  end

  local shown = ShowUpdateNewsDialog()
  if shown then
    ui.updateNewsSeenVersion = NEWS_VERSION
    ui.updateNewsPendingVersion = nil
  end
  return shown and true or false
end

local function ShowUpdateNews()
  local shown = ShowUpdateNewsDialog()
  if shown then
    local root = RootDB()
    local ui = root.ui
    if ui.updateNewsPendingVersion == NEWS_VERSION then
      ui.updateNewsSeenVersion = NEWS_VERSION
      ui.updateNewsPendingVersion = nil
    end
  end
  return shown and true or false
end

local function Publish(name, value)
  _G[name] = value
  local api = rawget(_G, "LIDCOUNCIL_API")
  if type(api) == "table" then
    api[name] = value
  end
end

Publish("LIDCOUNCIL_UpdateNews_OnLogin", UpdateNews_OnLogin)
Publish("LIDCOUNCIL_UpdateNews_OnEditorOpen", UpdateNews_OnEditorOpen)
Publish("LIDCOUNCIL_ShowUpdateNews", ShowUpdateNews)
