local API = rawget(_G, "LIDCOUNCIL_API")
local INTERNAL_API = type(API) == "table" and type(API.__internal) == "table" and API.__internal or nil
if type(INTERNAL_API) ~= "table" then
  error("LidCouncil missing internal API registry.")
end

INTERNAL_API.LIDCOUNCIL_CreateLootSessionSyncHistoryHelpers_Impl = function(deps)
  deps = type(deps) == "table" and deps or {}

  local ApplyFrameSkin = deps.ApplyFrameSkin
  local TrimText = deps.TrimText
  local FormatDateTime = deps.FormatDateTime
  local RequestLootSessionSectionRefresh = deps.RequestLootSessionSectionRefresh
  local ResolveOptionalApiFunction = deps.ResolveOptionalApiFunction

  local function RefreshSessionSyncPanels(editor)
    if type(RequestLootSessionSectionRefresh) == "function" then
      if RequestLootSessionSectionRefresh(editor, "SYNCMGMT") then
        return
      end
    end
    if editor and editor.RefreshLootSessionPage then
      editor:RefreshLootSessionPage({
        lootSessionSections = {
          SYNCMGMT = true,
        },
      })
    elseif editor and editor.Refresh then
      editor:Refresh()
    end
  end

  local function trim(value)
    if type(TrimText) == "function" then
      return TrimText(value)
    end
    local text = tostring(value or "")
    text = text:gsub("^%s+", "")
    text = text:gsub("%s+$", "")
    return text
  end

  local function formatWhen(value)
    if type(FormatDateTime) == "function" and tonumber(value) and tonumber(value) > 0 then
      return FormatDateTime(value)
    end
    return "-"
  end

  local function SetSyncHistoryStatus(frame, text, color)
    if type(frame) ~= "table" or not frame.status then
      return
    end
    local resolvedColor = type(color) == "table" and color or { 0.82, 0.84, 0.92, 1.00 }
    frame.status:SetText(tostring(text or ""))
    frame.status:SetTextColor(
      resolvedColor[1] or 0.82,
      resolvedColor[2] or 0.84,
      resolvedColor[3] or 0.92,
      resolvedColor[4] or 1
    )
  end

  local function ensureRows(frame, count)
    frame.rows = frame.rows or {}
    while #frame.rows < count do
      local row = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
      row:SetJustifyH("LEFT")
      row:SetText("")
      frame.rows[#frame.rows + 1] = row
    end
  end

  local function EnsureSyncHistoryPanel(editor)
    if not editor then
      return nil
    end
    if editor.lootSessionSyncHistoryFrame then
      return editor.lootSessionSyncHistoryFrame
    end

    local parent = editor.lootSessionRightContent or editor.lootSessionRightBg or UIParent
    local frame = CreateFrame("Frame", nil, parent, "BackdropTemplate")
    ApplyFrameSkin(frame)
    if frame.SetBackdropColor then
      frame:SetBackdropColor(0.05, 0.06, 0.08, 0.96)
    end

    local header = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    header:SetJustifyH("LEFT")
    header:SetText("Repair History and Undo")
    frame.header = header

    local undoBtn = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate")
    undoBtn:SetSize(152, 22)
    undoBtn:SetText("Undo Last Host Apply")
    frame.undoBtn = undoBtn

    local status = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    status:SetJustifyH("LEFT")
    status:SetText("")
    frame.status = status

    local empty = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    empty:SetJustifyH("LEFT")
    empty:SetText("No repair history has been recorded yet.")
    frame.empty = empty

    editor.lootSessionSyncHistoryFrame = frame
    return frame
  end

  local function RefreshSyncHistoryPanel(editor, context)
    local frame = EnsureSyncHistoryPanel(editor)
    if not frame then
      return nil
    end

    context = type(context) == "table" and context or {}
    local activeSession = context.activeSession
    local activeSessionIsHost = context.activeSessionIsHost and true or false
    local access = type(context.access) == "table" and context.access or {}
    local profileName = trim(type(activeSession) == "table" and activeSession.profileName or "")
    local sessionId = trim(type(activeSession) == "table" and activeSession.id or "")
    local inCombat = context.inCombat and true or false

    local getHistory = type(ResolveOptionalApiFunction) == "function"
      and ResolveOptionalApiFunction("LIDCOUNCIL_GetProfileRepairHistory")
      or nil
    local getUndoStatus = type(ResolveOptionalApiFunction) == "function"
      and ResolveOptionalApiFunction("LIDCOUNCIL_GetProfileUndoStatus")
      or nil
    local undoLastRepair = type(ResolveOptionalApiFunction) == "function"
      and ResolveOptionalApiFunction("LIDCOUNCIL_UndoLastProfileRepair")
      or nil
    local statusOverrideText = nil
    local statusOverrideColor = nil

    local function SetStatusOverride(text, color)
      statusOverrideText = tostring(text or "")
      statusOverrideColor = type(color) == "table" and color or { 1.00, 0.35, 0.25, 1.00 }
      SetSyncHistoryStatus(frame, statusOverrideText, statusOverrideColor)
    end

    local function ReadSyncHistoryValue(actionLabel, fn, fallback, ...)
      if type(fn) ~= "function" then
        return fallback
      end
      local ok, result = pcall(fn, ...)
      if not ok then
        SetStatusOverride(tostring(actionLabel or "Sync history") .. " failed: " .. tostring(result), { 1.00, 0.35, 0.25, 1.00 })
        return fallback
      end
      return result
    end

    local function RunSyncHistoryAction(actionLabel, fn, ...)
      if type(fn) ~= "function" then
        SetStatusOverride(tostring(actionLabel or "Sync history action") .. " is unavailable.", { 1.00, 0.55, 0.44, 1.00 })
        return false
      end
      local ok, result = pcall(fn, ...)
      if not ok then
        SetStatusOverride(tostring(actionLabel or "Sync history action") .. " failed: " .. tostring(result), { 1.00, 0.35, 0.25, 1.00 })
        return false
      end
      return true, result
    end

    local history = ReadSyncHistoryValue("Load repair history", getHistory, {}, profileName, sessionId)
    local undoStatus = ReadSyncHistoryValue("Load undo status", getUndoStatus, {
      available = false,
      count = 0,
      last = nil,
    }, profileName)
    history = type(history) == "table" and history or {}
    undoStatus = type(undoStatus) == "table" and undoStatus or {
      available = false,
      count = 0,
      last = nil,
    }

    if frame.undoBtn then
      frame.undoBtn:SetScript("OnClick", function()
        if profileName ~= "" and RunSyncHistoryAction("Undo last host repair", undoLastRepair, profileName) then
          RefreshSessionSyncPanels(editor)
        end
      end)
      if activeSession and activeSessionIsHost and access.canManageSession and not inCombat and undoStatus.available then
        frame.undoBtn:Enable()
      else
        frame.undoBtn:Disable()
      end
    end

    if frame.status then
      if statusOverrideText then
        SetSyncHistoryStatus(frame, statusOverrideText, statusOverrideColor)
      elseif not activeSession then
        SetSyncHistoryStatus(frame, "Undo becomes available after a host-side repair changes the active shared profile.")
      elseif undoStatus.available then
        SetSyncHistoryStatus(frame, "Manual safety net: " .. tostring(undoStatus.count or 0) .. " undo snapshot(s) ready for this active shared profile.", { 0.30, 0.90, 0.36, 1.00 })
      else
        SetSyncHistoryStatus(frame, "No host-side repair undo snapshot is currently available.", { 1.00, 0.82, 0.32, 1.00 })
      end
    end

    local visibleRows = {}
    for index = 1, math.min(6, #history) do
      local entry = type(history[index]) == "table" and history[index] or {}
      local memberKey = trim(entry.memberKey)
      local prefix = "[" .. formatWhen(entry.createdAt) .. "]"
      local suffix = trim(entry.summary)
      if memberKey ~= "" and memberKey ~= "UNKNOWN" then
        suffix = suffix ~= "" and (suffix .. " [" .. memberKey .. "]") or ("Member: " .. memberKey)
      end
      visibleRows[#visibleRows + 1] = prefix .. " " .. (suffix ~= "" and suffix or "Repair activity recorded.")
    end

    ensureRows(frame, math.max(1, #visibleRows))
    for index, row in ipairs(frame.rows or {}) do
      if visibleRows[index] then
        row:SetText(visibleRows[index])
        row:Show()
      else
        row:SetText("")
        row:Hide()
      end
    end

    if frame.empty then
      frame.empty:SetShown(#visibleRows == 0)
    end

    frame.__visibleRowCount = #visibleRows
    return frame
  end

  local function LayoutSyncHistoryPanel(editor, top, width)
    local frame = EnsureSyncHistoryPanel(editor)
    if not frame then
      return 0
    end

    width = math.max(320, tonumber(width) or 320)
    frame:ClearAllPoints()
    frame:SetPoint("TOPLEFT", 18, top)
    frame:SetWidth(width)

    frame.header:ClearAllPoints()
    frame.header:SetPoint("TOPLEFT", 12, -12)

    frame.undoBtn:ClearAllPoints()
    frame.undoBtn:SetPoint("TOPRIGHT", -12, -10)

    frame.status:ClearAllPoints()
    frame.status:SetPoint("TOPLEFT", 12, -38)
    frame.status:SetWidth(width - 24)

    local statusHeight = math.max(18, math.ceil(frame.status:GetStringHeight() or 0))
    local rowsTop = -42 - statusHeight - 10

    frame.empty:ClearAllPoints()
    frame.empty:SetPoint("TOPLEFT", 12, rowsTop)
    frame.empty:SetWidth(width - 24)

    local rowHeight = 18
    local visibleCount = math.max(1, tonumber(frame.__visibleRowCount) or 0)
    for index, row in ipairs(frame.rows or {}) do
      row:ClearAllPoints()
      row:SetPoint("TOPLEFT", 12, rowsTop - ((index - 1) * rowHeight))
      row:SetWidth(width - 24)
    end

    local rowsHeight = math.max(frame.empty:IsShown() and 18 or 0, visibleCount * rowHeight)
    local totalHeight = 56 + statusHeight + rowsHeight + 14
    frame:SetHeight(totalHeight)
    return totalHeight
  end

  return {
    RefreshSyncHistoryPanel = RefreshSyncHistoryPanel,
    LayoutSyncHistoryPanel = LayoutSyncHistoryPanel,
  }
end
