-- Loot Wishlist - Sticky Summary Window
-- Uses LuckyUI for consistent dark/gold styling.

LootWishlist = LootWishlist or {}
LootWishlist.Summary = LootWishlist.Summary or {}

local Summary = LootWishlist.Summary
local frame, textFS
local isDragging = false

local UI = LuckyUI
local C  = UI.C

local function ensureFrame()
  if frame then return frame end
  frame = CreateFrame("Frame", "LootWishlistSummary", UIParent, "BackdropTemplate")
  frame:SetSize(320, 120)
  frame:SetPoint("TOPRIGHT", UIParent, "TOPRIGHT", -300, -220)
  frame:SetFrameStrata("MEDIUM")
  frame:SetClampedToScreen(true)
  frame:EnableMouse(true)
  frame:SetMovable(true)
  frame:RegisterForDrag("LeftButton")
  frame:SetScript("OnDragStart", function(self) self:StartMoving() end)
  frame:SetScript("OnDragStop", function(self)
    self:StopMovingOrSizing()
    if LootWishlistCharDB and self:GetPoint(1) then
      local p, rel, rp, x, y = self:GetPoint(1)
      LootWishlistCharDB.summaryWindow = {point=p, relative=rel and rel:GetName(), relativePoint=rp, x=x, y=y}
    end
  end)

  -- LuckyUI backdrop: dark bg with gold-muted border (subtle for sticky note)
  frame:SetBackdrop(UI.Backdrop)
  frame:SetBackdropColor(C.bgDark[1], C.bgDark[2], C.bgDark[3], 0.80)
  frame:SetBackdropBorderColor(C.goldMuted[1], C.goldMuted[2], C.goldMuted[3], 0.6)

  -- Text content
  textFS = frame:CreateFontString(nil, "OVERLAY")
  textFS:SetFont(UI.BODY_FONT, 11)
  textFS:SetTextColor(C.textLight[1], C.textLight[2], C.textLight[3])
  textFS:SetJustifyH("LEFT")
  textFS:SetJustifyV("TOP")
  textFS:SetPoint("TOPLEFT", frame, "TOPLEFT", 8, -8)
  textFS:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -8, -8)
  textFS:SetText("")

  -- Click anywhere to open full list
  frame:SetScript("OnMouseUp", function(self, button)
    if button == "LeftButton" and not isDragging then
      if LootWishlist.UI and LootWishlist.UI.open then LootWishlist.UI.open() end
    end
  end)
  frame:HookScript("OnDragStart", function() isDragging = true end)
  frame:HookScript("OnDragStop", function() isDragging = false end)

  -- Hover: brighten border, restore full alpha
  frame:SetScript("OnEnter", function(self)
    self:SetBackdropBorderColor(C.goldAccent[1], C.goldAccent[2], C.goldAccent[3], 0.8)
    self:SetAlpha(1.0)
  end)
  frame:SetScript("OnLeave", function(self)
    self:SetBackdropBorderColor(C.goldMuted[1], C.goldMuted[2], C.goldMuted[3], 0.6)
    local settings = LootWishlistDB and LootWishlistDB.settings
    local a = settings and settings.summaryUnhoveredAlpha
    if a == nil then a = 1.0 end
    self:SetAlpha(a)
  end)

  -- Restore position if saved
  local w = LootWishlistCharDB and LootWishlistCharDB.summaryWindow
  if w and w.point then
    frame:ClearAllPoints()
    frame:SetPoint(w.point, w.relative and _G[w.relative] or UIParent, w.relativePoint or w.point, w.x or 0, w.y or 0)
  end

  frame:Hide()
  return frame
end

-- Helper: order by instance (raids first, alpha), and bosses by EJ order
local encounterOrderCache = {}
local function getEncounterOrder(instanceID)
  if not instanceID then return nil end
  if encounterOrderCache[instanceID] then return encounterOrderCache[instanceID] end
  local EJ_GetEncounterInfoByIndex = _G["EJ_GetEncounterInfoByIndex"]
  if type(EJ_GetEncounterInfoByIndex) ~= "function" then return nil end
  local order
  local EJ_SelectInstance = _G["EJ_SelectInstance"]
  local prevInstance = (EncounterJournal and EncounterJournal.instanceID) or nil
  if type(EJ_SelectInstance) == "function" then
    pcall(EJ_SelectInstance, instanceID)
    order = { id = {}, name = {} }
    for idx = 1, 200 do
      local name, _, encounterID = EJ_GetEncounterInfoByIndex(idx)
      if not name then break end
      if encounterID then order.id[encounterID] = idx end
      if name then order.name[name:lower()] = idx end
    end
    if prevInstance and prevInstance ~= instanceID then pcall(EJ_SelectInstance, prevInstance) end
  end
  if not order or not next(order) then
    order = { id = {}, name = {} }
    for idx = 1, 200 do
      local name, _, encounterID = EJ_GetEncounterInfoByIndex(idx, instanceID)
      if not name then break end
      if encounterID then order.id[encounterID] = idx end
      if name then order.name[name:lower()] = idx end
    end
  end
  encounterOrderCache[instanceID] = order
  return order
end

local function buildSummaryLines()
  local items = LootWishlist.GetTracked()
  if not items or not next(items) then return {} end
  local function diffTag(name, id)
    if name and name ~= "" then
      local n = name:lower()
      if n:find("raid finder") or n:find("lfr") then return "LFR" end
      if n:find("normal") then return "N" end
      if n:find("heroic") then return "H" end
      if n:find("mythic%+") or n:find("keystone") then return "+" end
      if n:find("mythic") then return "M" end
    end
    if id then
      local map = { [1] = "N", [2] = "H", [8] = "+", [23] = "M", [24] = "TW", [14] = "N", [15] = "H", [16] = "M", [17] = "LFR" }
      return map[id]
    end
    return nil
  end
  local function joinTags(set)
    local arr = {}
    for k in pairs(set) do table.insert(arr, k) end
    table.sort(arr, function(a,b)
      local order = { LFR=1, N=2, H=3, ["+"]=4, M=5 }
      local oa = order[a] or 99
      local ob = order[b] or 99
      if oa ~= ob then return oa < ob end
      return a < b
    end)
    return table.concat(arr, ", ")
  end
  -- Group by instance
  local groups = {}
  for key, info in pairs(items) do
    local inst = info.dungeon or "Unknown"
    local g = groups[inst]
    if not g then g = { name = inst, isRaid = info.isRaid and true or false, items = {}, instanceID = info.instanceID }; groups[inst] = g end
    if info.isRaid then g.isRaid = true end
    if info.instanceID and not g.instanceID then g.instanceID = info.instanceID end
    table.insert(g.items, { key = key, id = info.id or tonumber(key) or 0, info = info })
  end
  local ordered = {}
  for name, g in pairs(groups) do table.insert(ordered, { name = name, g = g }) end
  table.sort(ordered, function(a,b)
    if a.g.isRaid ~= b.g.isRaid then return a.g.isRaid end
    return a.name < b.name
  end)

  -- Use LuckyUI WoW color codes
  local WC = UI.WC
  local lines = {}
  for _, entry in ipairs(ordered) do
    local g = entry.g
    if g.isRaid then
      table.insert(lines, string.format("%s%s%s", WC.goldPrimary, entry.name, WC.reset))
      local bossGroups = {}
      for _, it in ipairs(g.items) do
        local bname = (it.info.boss and it.info.boss ~= "") and it.info.boss or "Unknown Boss"
        local encID = it.info.encounterID or -1
        if not bossGroups[bname] then bossGroups[bname] = {encounterID = encID, items = {}} end
        if encID ~= -1 then bossGroups[bname].encounterID = encID end
        table.insert(bossGroups[bname].items, it)
      end
      local bossOrdered = {}
      for bname, data in pairs(bossGroups) do table.insert(bossOrdered, { name = bname, items = data.items, encounterID = data.encounterID or -1 }) end
      local orderMap = getEncounterOrder(g.instanceID)
      table.sort(bossOrdered, function(a,b)
        local ao = orderMap and (orderMap.id[a.encounterID] or orderMap.name[a.name:lower()]) or nil
        local bo = orderMap and (orderMap.id[b.encounterID] or orderMap.name[b.name:lower()]) or nil
        if ao and bo and ao ~= bo then return ao < bo end
        if ao and not bo then return true end
        if bo and not ao then return false end
        return a.name < b.name
      end)
      for _, b in ipairs(bossOrdered) do
        local diffs = {}
        for _, it in ipairs(b.items) do
          local tag = diffTag(it.info.difficultyName, it.info.difficultyID)
          if tag then diffs[tag] = true end
        end
        local tagText = next(diffs) and (" " .. WC.textMuted .. "[" .. joinTags(diffs) .. "]" .. WC.reset) or ""
        table.insert(lines, string.format("  - %s (%d)%s", b.name, #b.items, tagText))
      end
    else
      local diffs = {}
      for _, it in ipairs(g.items) do
        local tag = diffTag(it.info.difficultyName, it.info.difficultyID)
        if tag then diffs[tag] = true end
      end
      local tagText = next(diffs) and (" " .. WC.textMuted .. "[" .. joinTags(diffs) .. "]" .. WC.reset) or ""
      table.insert(lines, string.format("%s%s%s (%d)%s", WC.goldPrimary, entry.name, WC.reset, #g.items, tagText))
    end
  end
  return lines
end

local function shouldAutoHide()
  local settings = LootWishlistDB and LootWishlistDB.settings
  if not settings or settings.hideSummaryInCombatAndMythicPlus == false then return false end
  if InCombatLockdown() then return true end
  if C_ChallengeMode and C_ChallengeMode.IsChallengeModeActive and C_ChallengeMode.IsChallengeModeActive() then
    return true
  end
  return false
end

local function refresh()
  local f = ensureFrame()
  local settings = LootWishlistDB and LootWishlistDB.settings
  if settings and settings.hideSummaryWindow then f:Hide(); return end
  if shouldAutoHide() then f:Hide(); return end
  local lines = buildSummaryLines()
  if not next(lines) then f:Hide(); return end
  local content = table.concat(lines, "\n")
  textFS:SetText(content)
  local width = 300
  if textFS.GetStringWidth then width = math.max(200, math.min(300, textFS:GetStringWidth() + 24)) end
  frame:SetWidth(width)
  local height = 30 + (textFS.GetStringHeight and textFS:GetStringHeight() or 60)
  frame:SetHeight(height)
  -- Apply unhovered alpha (unless mouse is currently over the frame)
  local a = settings and settings.summaryUnhoveredAlpha
  if a == nil then a = 1.0 end
  if frame:IsMouseOver() then
    frame:SetAlpha(1.0)
  else
    frame:SetAlpha(a)
  end
  f:Show()
end

Summary.refresh = refresh

function Summary.showIfNeeded()
  refresh()
end

-- Auto-hide on combat / Mythic+ transitions
local autoHideWatcher = CreateFrame("Frame")
autoHideWatcher:RegisterEvent("PLAYER_REGEN_DISABLED")
autoHideWatcher:RegisterEvent("PLAYER_REGEN_ENABLED")
autoHideWatcher:RegisterEvent("CHALLENGE_MODE_START")
autoHideWatcher:RegisterEvent("CHALLENGE_MODE_COMPLETED")
autoHideWatcher:RegisterEvent("CHALLENGE_MODE_RESET")
autoHideWatcher:RegisterEvent("PLAYER_ENTERING_WORLD")
autoHideWatcher:SetScript("OnEvent", function() refresh() end)
