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

local shared = INTERNAL_API.LIDCOUNCIL_LootEditorShared_Impl
if type(shared) ~= "table" then
  error("LidCouncil missing loot editor shared helpers.")
end

local RequireApi = shared.RequireApi
local BindMouseWheelScroll = shared.BindMouseWheelScroll
local RootDB = shared.RootDB
local ApplyFrameSkin = shared.ApplyFrameSkin
local MakeYellowSubHeader = shared.MakeYellowSubHeader
local GetCharacterKey = shared.GetCharacterKey
local GetEnabledLootProfileName = shared.GetEnabledLootProfileName or RequireApi("LIDCOUNCIL_GetEnabledLootProfileName", _G.LIDCOUNCIL_GetEnabledLootProfileName)
local GetLootProfile = shared.GetLootProfile
local GetPrimaryLootProfileName = shared.GetPrimaryLootProfileName
local GetLootProfileNames = shared.GetLootProfileNames
local IsLootProfileVisibleInEditor = shared.IsLootProfileVisibleInEditor or function(_, profileName)
  return profileName ~= nil and profileName ~= ""
end
local GetLootProfileAccessInfo = shared.GetLootProfileAccessInfo
local GetLootProfilePermissionPolicyRoleState = shared.GetLootProfilePermissionPolicyRoleState
local SetCurrentLootProfile = shared.SetCurrentLootProfile
local CreateLootProfile = shared.CreateLootProfile
local DeleteLootProfile = shared.DeleteLootProfile
local CopyLootProfile = shared.CopyLootProfile
local SetLootProfileEnabled = shared.SetLootProfileEnabled
local SetLootProfileRaid = shared.SetLootProfileRaid
local AddLootRollOption = shared.AddLootRollOption
local UpdateLootRollOption = shared.UpdateLootRollOption
local RemoveLootRollOption = shared.RemoveLootRollOption
local UpdateLootPointMode = shared.UpdateLootPointMode
local UpdateLootLidTableRow = shared.UpdateLootLidTableRow
local AddLootPointRule = shared.AddLootPointRule
local RemoveLootPointRule = shared.RemoveLootPointRule
local StartLootSession = shared.StartLootSession
local StopLootSession = shared.StopLootSession
local GetActiveLootSession = shared.GetActiveLootSession
local AddLootLedgerEntry = shared.AddLootLedgerEntry
local GetLootLedgerCharacters = shared.GetLootLedgerCharacters
local ResolveOptionalApiFunction = shared.ResolveOptionalApiFunction
local CreateCustomDropdownControl = shared.CreateCustomDropdownControl
local TrimText = shared.TrimText
local FormatDateTime = shared.FormatDateTime
local FormatDuration = shared.FormatDuration
local CreateSimpleEditBox = shared.CreateSimpleEditBox
local SetListButtonSelected = shared.SetListButtonSelected
local SetTextListButtonTextColor = shared.SetTextListButtonTextColor
local EnsureTextListButtons = shared.EnsureTextListButtons
local CreateSectionShell = shared.CreateSectionShell
local ClampLayoutValue = shared.ClampLayoutValue
local GetResponsiveSectionLayout = shared.GetResponsiveSectionLayout
local SetControlWidth = shared.SetControlWidth
local GetFontStringWidth = shared.GetFontStringWidth
local CreateSectionDivider = shared.CreateSectionDivider
local FlowLayoutControls = shared.FlowLayoutControls
local LayoutRollOptionRow = shared.LayoutRollOptionRow
local LayoutLidTableEditorRow = shared.LayoutLidTableEditorRow
local BuildRollOptionsText = shared.BuildRollOptionsText
local DEFAULT_ROLL_OPTION_ICON_CHOICES = shared.DEFAULT_ROLL_OPTION_ICON_CHOICES
local ResolveTextureAsset = shared.ResolveTextureAsset
local ResolveDefaultRollOptionIcon = shared.ResolveDefaultRollOptionIcon
local ResolveRollOptionIcon = shared.ResolveRollOptionIcon
local GetRollOptionIconLabel = shared.GetRollOptionIconLabel
local EnsureRollOptionRows = shared.EnsureRollOptionRows
local EnsureLidTableEditorRows = shared.EnsureLidTableEditorRows
local ExtractItemID = shared.ExtractItemID
local ExtractItemLinkName = shared.ExtractItemLinkName
local FormatPointRuleItemLabel = shared.FormatPointRuleItemLabel
local FormatRaidLootItemLabel = shared.FormatRaidLootItemLabel
local LOOT_ITEM_MENU_PAGE_SIZE = shared.LOOT_ITEM_MENU_PAGE_SIZE
local NormalizeInstanceTuple = shared.NormalizeInstanceTuple
local NormalizeEncounterTuple = shared.NormalizeEncounterTuple
local NormalizeLootInfo = shared.NormalizeLootInfo
local EnsureEncounterJournalLoaded = shared.EnsureEncounterJournalLoaded
local CollectRaidEntries = shared.CollectRaidEntries
local CollectRaidLootEntries = shared.CollectRaidLootEntries
local FindRaidEntryByProfile = shared.FindRaidEntryByProfile
local FindRaidLootEntry = shared.FindRaidLootEntry
local EnsureLootLiveBoardMode = shared.EnsureLootLiveBoardMode
local ClampMenuPage = shared.ClampMenuPage
local GetSelectedValuePage = shared.GetSelectedValuePage

local ACTIVATE_PROFILE_REQUIRED_TEXT = "Please go to Profile and activate one Profile first"
local NO_ACTIVE_PROFILE_CURRENT_TEXT = "Current Profile: No profile activated :("
local NO_ACTIVE_PROFILE_TEXT_COLOR = { 1.00, 0.35, 0.25, 1.00 }

local function SetCurrentProfileFont(fontString, text, color)
  if not fontString then
    return
  end
  fontString:SetText(text)
  fontString.__lid_customTextColor = color
  if color and fontString.SetTextColor then
    fontString:SetTextColor(color[1], color[2], color[3], color[4] or 1)
  elseif fontString.SetTextColor then
    fontString:SetTextColor(0.92, 0.96, 1.00, 1.00)
  end
end

local function GetSessionContextProfileName()
  local root = RootDB()
  local enabledProfileName = TrimText(GetEnabledLootProfileName() or "")
  if enabledProfileName ~= "" and IsLootProfileVisibleInEditor(root, enabledProfileName) then
    return enabledProfileName
  end
  return nil
end

local EMPTY_SESSION_CONTEXT_PROFILE = {
  settings = {},
  sessions = {},
  lootLedger = {},
  lootLedgerMeta = {},
}

local EMPTY_SESSION_CONTEXT_ACCESS = {
  canStartSession = false,
  canManageSession = false,
  canOpenLiveBoard = false,
  canUseVoting = false,
  canAssignLoot = false,
}

local function ResolveSessionContextProfile()
  local root = RootDB()
  local profileName = TrimText(GetSessionContextProfileName())
  if profileName == "" or not root.profiles or type(root.profiles[profileName]) ~= "table" then
    return EMPTY_SESSION_CONTEXT_PROFILE, nil
  end
  return GetLootProfile(profileName)
end

local function ResolveSessionContextAccess(profileName)
  if TrimText(profileName) == "" then
    return EMPTY_SESSION_CONTEXT_ACCESS
  end
  return GetLootProfileAccessInfo(profileName)
end

local function ResolveRequiredSessionProfileName(actionLabel)
  local _, profileName = ResolveSessionContextProfile()
  if TrimText(profileName) ~= "" then
    return profileName
  end
  local message = ACTIVATE_PROFILE_REQUIRED_TEXT
  local printFn = ResolveOptionalApiFunction("LIDCOUNCIL_Print")
  if type(printFn) == "function" then
    printFn(message)
  end
  return nil
end

local function IsCombatLocked()
  return type(InCombatLockdown) == "function" and InCombatLockdown() and true or false
end
local EnsureLootProfileGroups = shared.EnsureLootProfileGroups
local FindLootProfileGroupIndex = shared.FindLootProfileGroupIndex
local RemoveLootProfileFromGroups = shared.RemoveLootProfileFromGroups
local ToggleLootProfileGroupCollapsed = shared.ToggleLootProfileGroupCollapsed
local GetLootProfileGroupName = shared.GetLootProfileGroupName
local BuildLootProfileNavRows = shared.BuildLootProfileNavRows
local BuildPointRulesText = shared.BuildPointRulesText
local ResolvePointMode = shared.ResolvePointMode
local GetLidTableRows = shared.GetLidTableRows
local BuildLidTableSummaryText = shared.BuildLidTableSummaryText
local POINT_MODE_CHOICES = shared.POINT_MODE_CHOICES
local GetSelectedProfileName = shared.GetSelectedProfileName
local RefreshCurrentSessionView
local LayoutCurrentSessionSection
local BuildSessionHistoryRowsData
local RefreshSessionHistoryRows
local LayoutSessionHistorySection
local RefreshSyncManagementView
local LayoutSyncManagementSection
local RefreshRoleSimulationView
local LayoutRoleSimulationSection
local RefreshAutoPassView
local LayoutAutoPassSection
local SIMULATION_ROLE_OPTIONS
local ROLE_SIM_RIGHTS_MATRIX

local function FormatLootProfileRoleLabel(role)
  local resolvedRole = string.upper(TrimText(role))
  if resolvedRole == "MASTER" then
    return "Master"
  end
  if resolvedRole == "COUNCIL" then
    return "Council Member"
  end
  if resolvedRole == "SESSION_HOST" then
    return "Session Host"
  end
  return "Raider"
end
local SESSION_CLASS_ICON_TEXTURE = "Interface\\GLUES\\CHARACTERCREATE\\UI-CHARACTERCREATE-CLASSES"

local function GetRoleSimMatrixCellText(allowed)
  if allowed then
    return "|cff4adf6b✔|r"
  end
  return "|cffff5a5a✖|r"
end

GetRoleSimMatrixCellText = function(allowed)
  if allowed then
    return "|cff4adf6bOK|r"
  end
  return "|cffff5a5aX|r"
end

local function ResolveRoleSimMatrixValue(rowDef, roleState, staticKey)
  rowDef = type(rowDef) == "table" and rowDef or {}
  roleState = type(roleState) == "table" and roleState or {}

  if type(rowDef.permissionKey) == "string" and rowDef.permissionKey ~= "" then
    return roleState[rowDef.permissionKey] and true or false
  end

  if type(rowDef.permissionKeys) == "table" and #rowDef.permissionKeys > 0 then
    for _, permissionKey in ipairs(rowDef.permissionKeys) do
      if not roleState[permissionKey] then
        return false
      end
    end
    return true
  end

  return rowDef[staticKey] and true or false
end

local function GetSessionClassColor(classFile)
  local resolvedClassFile = TrimText(classFile)
  local colorTable = (type(CUSTOM_CLASS_COLORS) == "table" and CUSTOM_CLASS_COLORS[resolvedClassFile])
    or (type(RAID_CLASS_COLORS) == "table" and RAID_CLASS_COLORS[resolvedClassFile])
    or nil
  if colorTable then
    return tonumber(colorTable.r or colorTable[1]) or 0.82,
      tonumber(colorTable.g or colorTable[2]) or 0.82,
      tonumber(colorTable.b or colorTable[3]) or 0.86,
      1
  end
  return 0.82, 0.82, 0.86, 1
end

local function ResolveSessionDisplayInfo(profile, memberKey, member)
  local meta = type(profile) == "table" and type(profile.lootLedgerMeta) == "table" and profile.lootLedgerMeta[memberKey] or nil
  return {
    className = TrimText(type(member) == "table" and member.className or (type(meta) == "table" and meta.className) or ""),
    classFile = TrimText(type(member) == "table" and member.classFile or (type(meta) == "table" and meta.classFile) or ""),
    specName = TrimText(type(member) == "table" and member.specName or (type(meta) == "table" and meta.specName) or ""),
    specIcon = TrimText(type(member) == "table" and member.specIcon or (type(meta) == "table" and meta.specIcon) or ""),
  }
end

local function ResolveSessionIconData(displayInfo)
  if type(displayInfo) ~= "table" then
    return nil
  end
  local specIcon = TrimText(displayInfo.specIcon)
  if specIcon ~= "" then
    return { texture = specIcon }
  end
  local classFile = TrimText(displayInfo.classFile)
  local coords = classFile ~= "" and type(CLASS_ICON_TCOORDS) == "table" and CLASS_ICON_TCOORDS[classFile] or nil
  if type(coords) == "table" then
    return {
      texture = SESSION_CLASS_ICON_TEXTURE,
      left = coords[1],
      right = coords[2],
      top = coords[3],
      bottom = coords[4],
    }
  end
  return nil
end

local function ApplySessionIcon(texture, iconData)
  if not texture then
    return
  end
  if type(iconData) ~= "table" or TrimText(iconData.texture) == "" then
    texture:SetTexture("Interface\\Icons\\INV_Misc_QuestionMark")
    texture:SetTexCoord(0, 1, 0, 1)
    return
  end
  texture:SetTexture(iconData.texture)
  if type(iconData.left) == "number" and type(iconData.right) == "number" and type(iconData.top) == "number" and type(iconData.bottom) == "number" then
    texture:SetTexCoord(iconData.left, iconData.right, iconData.top, iconData.bottom)
  else
    texture:SetTexCoord(0, 1, 0, 1)
  end
end

local function ResolveSessionSyncState(member, memberKey, session, selfCharacter)
  if type(member) ~= "table" then
    return "PENDING"
  end
  local status = string.upper(TrimText(member.status or "JOINED"))
  if status == "DECLINED" then
    return "DECLINED"
  end
  local resolvedKey = TrimText(memberKey ~= "" and memberKey or member.name or "")
  local selfKey = TrimText(selfCharacter)
  local sessionHost = TrimText(type(session) == "table" and session.host or "")
  local isLocalAuthority = resolvedKey ~= "" and (resolvedKey == selfKey or resolvedKey == sessionHost)
  if tonumber(member.lastSyncAt) and isLocalAuthority then
    return "SYNCED"
  end

  local localProfileName = TrimText(type(session) == "table" and session.profileName or "")
  local getProfileId = ResolveOptionalApiFunction("LIDCOUNCIL_GetLootProfileId")
  local getRevisionSummary = ResolveOptionalApiFunction("LIDCOUNCIL_GetLootProfileRevisionSummary")
  if tonumber(member.lastSyncAt) and TrimText(member.addonVersion) ~= "" and localProfileName ~= ""
      and type(getProfileId) == "function" and type(getRevisionSummary) == "function" then
    local localProfileId = TrimText(select(1, getProfileId(localProfileName)) or "")
    local memberProfileId = TrimText(member.sharedProfileId)
    if localProfileId == "" or memberProfileId == "" or string.lower(localProfileId) ~= string.lower(memberProfileId) then
      return "PARTIAL"
    end

    local localSummary = getRevisionSummary(localProfileName)
    local settingsRevision = math.max(0, tonumber(type(localSummary) == "table" and localSummary.settings) or 0)
    local permissionsRevision = math.max(0, tonumber(type(localSummary) == "table" and localSummary.permissions) or 0)
    local operationalRevision = math.max(0, tonumber(type(localSummary) == "table" and localSummary.operational) or 0)
    local lootRevision = math.max(0, tonumber(type(localSummary) == "table" and localSummary.loot) or operationalRevision)
    local settingsChecksum = TrimText(type(localSummary) == "table" and localSummary.settingsChecksum or "")
    local permissionsChecksum = TrimText(type(localSummary) == "table" and localSummary.permissionsChecksum or "")
    local operationalChecksum = TrimText(type(localSummary) == "table" and localSummary.operationalChecksum or "")
    local lootChecksum = TrimText(type(localSummary) == "table" and localSummary.lootChecksum or "")
    if lootChecksum == "" then
      lootChecksum = operationalChecksum
    end
    local memberSettingsChecksum = TrimText(member.settingsChecksum)
    local memberPermissionsChecksum = TrimText(member.permissionsChecksum)
    local memberOperationalChecksum = TrimText(member.operationalChecksum)
    local memberLootChecksum = TrimText(member.lootChecksum)
    if memberLootChecksum == "" then
      memberLootChecksum = memberOperationalChecksum
    end
    local hasSettingsChecksum = settingsChecksum ~= "" and memberSettingsChecksum ~= ""
    local hasPermissionsChecksum = permissionsChecksum ~= "" and memberPermissionsChecksum ~= ""
    local hasLootChecksum = lootChecksum ~= "" and memberLootChecksum ~= ""

    if hasSettingsChecksum and settingsChecksum ~= memberSettingsChecksum then
      return "PARTIAL"
    end
    if hasPermissionsChecksum and permissionsChecksum ~= memberPermissionsChecksum then
      return "PARTIAL"
    end
    if hasLootChecksum and lootChecksum ~= memberLootChecksum then
      return "PARTIAL"
    end
    if hasSettingsChecksum and hasPermissionsChecksum and hasLootChecksum then
      return "SYNCED"
    end

    if settingsRevision == math.max(0, tonumber(member.settingsRevision) or 0)
        and permissionsRevision == math.max(0, tonumber(member.permissionsRevision) or 0)
        and lootRevision == math.max(0, tonumber(member.lootRevision) or tonumber(member.operationalRevision) or 0) then
      return "SYNCED"
    end
    return "PARTIAL"
  end
  if tonumber(member.lastSyncAt) then
    return "PARTIAL"
  end
  return "PENDING"
end

local function ResolveBootstrapDomainMatch(localRevision, localChecksum, memberRevision, memberChecksum)
  local resolvedLocalChecksum = TrimText(localChecksum)
  local resolvedMemberChecksum = TrimText(memberChecksum)
  if resolvedLocalChecksum ~= "" and resolvedMemberChecksum ~= "" then
    return resolvedLocalChecksum == resolvedMemberChecksum
  end
  return math.max(0, tonumber(localRevision) or 0) == math.max(0, tonumber(memberRevision) or 0)
end

local function ResolveSessionBootstrapState(member, memberKey, session, selfCharacter)
  if type(member) ~= "table" then
    return "PENDING"
  end
  local status = string.upper(TrimText(member.status or "JOINED"))
  if status == "DECLINED" then
    return "DECLINED"
  end

  local resolvedKey = TrimText(memberKey ~= "" and memberKey or member.name or "")
  local selfKey = TrimText(selfCharacter)
  local sessionHost = TrimText(type(session) == "table" and session.host or "")
  if resolvedKey ~= "" and resolvedKey == sessionHost then
    return "READY"
  end
  if resolvedKey ~= "" and resolvedKey == selfKey then
    if type(session) == "table" and session.sharedProfileReady == false then
      return "PENDING"
    end
    return "READY"
  end
  if not tonumber(member.lastSyncAt) then
    return "PENDING"
  end

  local localProfileName = TrimText(type(session) == "table" and session.profileName or "")
  local getProfileId = ResolveOptionalApiFunction("LIDCOUNCIL_GetLootProfileId")
  local getRevisionSummary = ResolveOptionalApiFunction("LIDCOUNCIL_GetLootProfileRevisionSummary")
  if TrimText(member.addonVersion) == "" or localProfileName == ""
      or type(getProfileId) ~= "function" or type(getRevisionSummary) ~= "function" then
    return "PENDING"
  end

  local localProfileId = TrimText(select(1, getProfileId(localProfileName)) or "")
  local memberProfileId = TrimText(member.sharedProfileId)
  if localProfileId == "" or memberProfileId == "" then
    return "PENDING"
  end
  if string.lower(localProfileId) ~= string.lower(memberProfileId) then
    return "REVIEW"
  end

  local localSummary = getRevisionSummary(localProfileName)
  local settingsRevision = math.max(0, tonumber(type(localSummary) == "table" and localSummary.settings) or 0)
  local permissionsRevision = math.max(0, tonumber(type(localSummary) == "table" and localSummary.permissions) or 0)
  local settingsChecksum = TrimText(type(localSummary) == "table" and localSummary.settingsChecksum or "")
  local permissionsChecksum = TrimText(type(localSummary) == "table" and localSummary.permissionsChecksum or "")
  local memberSettingsRevision = math.max(0, tonumber(member.settingsRevision) or 0)
  local memberPermissionsRevision = math.max(0, tonumber(member.permissionsRevision) or 0)
  local memberSettingsChecksum = TrimText(member.settingsChecksum)
  local memberPermissionsChecksum = TrimText(member.permissionsChecksum)

  local settingsMatch = ResolveBootstrapDomainMatch(settingsRevision, settingsChecksum, memberSettingsRevision, memberSettingsChecksum)
  local permissionsMatch = ResolveBootstrapDomainMatch(permissionsRevision, permissionsChecksum, memberPermissionsRevision, memberPermissionsChecksum)
  if settingsMatch and permissionsMatch then
    return "READY"
  end

  if memberSettingsRevision > settingsRevision or memberPermissionsRevision > permissionsRevision then
    return "REVIEW"
  end
  return "PENDING"
end

local function GetSessionBootstrapLabel(state)
  local resolved = string.upper(TrimText(state))
  if resolved == "READY" then
    return "Roll Ready"
  elseif resolved == "REVIEW" then
    return "Needs Review"
  elseif resolved == "DECLINED" then
    return "Declined"
  end
  return "Bootstrap Pending"
end

local function GetSessionBootstrapDescription(state)
  local resolved = string.upper(TrimText(state))
  if resolved == "READY" then
    return "Roll-Ready means the joined member matches the current shared profile lineage plus Settings and Permissions, so loot choices can open even if Loot or Session history is still syncing."
  elseif resolved == "REVIEW" then
    return "Needs Review means the joined member differs in shared profile lineage or in bootstrap-critical Settings or Permissions and should be reviewed before trusting loot choices."
  elseif resolved == "DECLINED" then
    return "The invited member declined the current session."
  end
  return "Bootstrap Pending means the joined member has not finished the initial host bootstrap yet. Roll choices may still be blocked while the host pushes Settings and Permissions."
end

local function GetSessionBootstrapColor(state)
  local resolved = string.upper(TrimText(state))
  if resolved == "READY" then
    return 0.20, 0.88, 0.32, 1
  elseif resolved == "REVIEW" then
    return 0.95, 0.32, 0.26, 1
  elseif resolved == "DECLINED" then
    return 0.90, 0.32, 0.24, 1
  end
  return 1.00, 0.82, 0.28, 1
end

local function GetSessionSyncLabel(syncState)
  if syncState == "SYNCED" then
    return "Fully Synced"
  elseif syncState == "PARTIAL" then
    return "Partial Sync"
  elseif syncState == "DECLINED" then
    return "Declined"
  end
  return "Waiting"
end

local function GetSessionSyncDescription(syncState)
  if syncState == "SYNCED" then
    return "All joined members match the local shared profile identity plus Settings, Permissions, and Loot Data checksums. Session bookkeeping is tracked separately."
  elseif syncState == "PARTIAL" then
    return "Partial Sync means at least one joined member has different or incomplete profile identity, Settings, Permissions, or Loot Data checksum data."
  elseif syncState == "DECLINED" then
    return "One or more invited members declined the current session."
  end
  return "Waiting for joined members to answer the session invite and report sync data."
end

local function ApplyTrafficLight(texture, syncState)
  if not texture then
    return
  end
  texture:SetTexture("Interface\\Buttons\\WHITE8x8")
  local r, g, b, a = 0.70, 0.70, 0.76, 1
  if syncState == "SYNCED" then
    r, g, b = 0.20, 0.88, 0.32
  elseif syncState == "PARTIAL" then
    r, g, b = 1.00, 0.82, 0.28
  elseif syncState == "DECLINED" then
    r, g, b = 0.90, 0.32, 0.24
  end
  texture:SetVertexColor(r, g, b, a)
end

local function GetTrafficLightColor(syncState)
  if syncState == "SYNCED" then
    return 0.20, 0.88, 0.32, 1
  elseif syncState == "PARTIAL" then
    return 1.00, 0.82, 0.28, 1
  elseif syncState == "DECLINED" then
    return 0.90, 0.32, 0.24, 1
  end
  return 0.70, 0.70, 0.76, 1
end

local function GetSessionStatusColor(status)
  local upperStatus = string.upper(TrimText(status))
  if upperStatus == "JOINED" or upperStatus == "ACTIVE" or upperStatus == "FINISHED" then
    return 0.20, 0.88, 0.32, 1
  elseif upperStatus == "LEFT" then
    return 1.00, 0.82, 0.28, 1
  elseif upperStatus == "DECLINED" or upperStatus == "FAILED" or upperStatus == "STOPPED" then
    return 0.90, 0.32, 0.24, 1
  elseif upperStatus == "INVITED" or upperStatus == "PENDING" or upperStatus == "PREPARING" then
    return 1.00, 0.82, 0.28, 1
  end
  return 0.82, 0.82, 0.86, 1
end

local function RefreshLootSessionPage_Impl(self)
  if not self then
    return
  end

  local root = RootDB()
  local profile, profileName = ResolveSessionContextProfile()
  local hasActiveProfile = TrimText(profileName) ~= ""
  local access = ResolveSessionContextAccess(profileName)
  local section = self.lootSessionSection or "CURRENT"
  local selfCharacter = GetCharacterKey() or "Unknown"
  local isSimulationProfile = TrimText(profileName) == "Simulation"
  if section == "ROLESIM" and not isSimulationProfile then
    section = "CURRENT"
  end
  self.lootSessionSection = section

  local currentBtn = self.sessionNavCurrentBtn
  local historyBtn = self.sessionNavHistoryBtn
  local syncMgmtBtn = self.sessionNavSyncManagementBtn
  local roleSimBtn = self.sessionNavRoleSimBtn
  local autoPassSettingsBtn = self.sessionNavAutoPassSettingsBtn
  local startBtn = self.sessionStartBtn
  local activateBtn = self.sessionActivateBtn
  local stopBtn = self.sessionStopBtn
  local inviteBtn = self.sessionInviteBtn
  local removeMemberBtn = self.sessionRemoveMemberBtn
  local pushProfileBtn = self.sessionPushProfileBtn
  local checkSyncBtn = self.sessionCheckSyncBtn
  local profileSyncDropdown = self.sessionProfileSyncMemberDropdown
  local recommendedRepairBtn = self.sessionRecommendedRepairBtn
  local requestProfileBtn = self.sessionRequestProfileBtn
  local previewProfileBtn = self.sessionPreviewProfileBtn
  local syncBoardBtn = self.sessionSyncBoardBtn
  local liveSummary = self.lootSessionLiveSummary
  local overviewFrame = self.lootSessionOverviewFrame
  local currentMembersHeader = self.lootSessionMembersHeader
  local memberColumns = self.lootSessionMemberColumns
  local memberRowsFrame = self.lootSessionMemberRowsFrame
  local historyHeader = self.lootSessionHistoryHeader
  local historyColumns = self.lootSessionHistoryColumns
  local historyRowsFrame = self.lootSessionHistoryRowsFrame
  local roleSimHeader = self.lootSessionRoleSimHeader
  local roleSimDesc = self.lootSessionRoleSimDesc
  local roleSimCurrent = self.lootSessionRoleSimCurrent
  local roleSimMasterBtn = self.sessionRoleSimMasterBtn
  local roleSimSessionHostBtn = self.sessionRoleSimSessionHostBtn
  local roleSimCouncilBtn = self.sessionRoleSimCouncilBtn
  local roleSimRaiderBtn = self.sessionRoleSimRaiderBtn
  local roleSimMatrixFrame = self.lootSessionRoleSimMatrixFrame
  local roleSimMatrixHeader = self.lootSessionRoleSimMatrixHeader
  local roleSimState = self.lootSessionRoleSimState
  local autoPassHeader = self.lootSessionAutoPassHeader
  local autoPassDesc = self.lootSessionAutoPassDesc
  local autoPassCurrent = self.lootSessionAutoPassCurrent
  local autoPassLocalBtn = self.sessionAutoPassLocalBtn
  local autoPassState = self.lootSessionAutoPassState
  local syncCheckHeader = self.lootSessionSyncCheckHeader
  local syncIntro = self.lootSessionSyncIntro
  local syncDashboardFrame = self.lootSessionSyncDashboardFrame
  local syncScopeFrame = self.lootSessionSyncScopeFrame
  local syncPushHeader = self.lootSessionSyncPushHeader
  local syncPullHeader = self.lootSessionSyncPullHeader
  local syncAutoHeader = self.lootSessionSyncAutoHeader
  local syncAutoText = self.lootSessionSyncAutoText
  local syncManualHeader = self.lootSessionSyncManualHeader
  local syncManualText = self.lootSessionSyncManualText
  local syncReviewHeader = self.lootSessionSyncReviewHeader
  local syncReviewColumns = self.lootSessionSyncReviewColumns
  local syncReviewRowsFrame = self.lootSessionSyncReviewRowsFrame
  local syncReviewEmpty = self.lootSessionSyncReviewEmpty
  local body = self.lootSessionBody

  if self.lootSessionInactiveOverlay then
    self.lootSessionInactiveOverlay:SetShown(not hasActiveProfile)
  end
  if self.lootSessionNavBg then
    self.lootSessionNavBg:SetShown(hasActiveProfile)
  end
  if self.lootSessionRightBg then
    self.lootSessionRightBg:SetShown(hasActiveProfile)
  end

  if not hasActiveProfile then
    self.lootSessionSection = "CURRENT"
    if self.panelsTitle then self.panelsTitle:SetText("Profile") end
    SetCurrentProfileFont(self.panelsCurrentLabel, NO_ACTIVE_PROFILE_CURRENT_TEXT, NO_ACTIVE_PROFILE_TEXT_COLOR)
    if self.UpdateScrollLayout then
      self:UpdateScrollLayout()
    end
    return
  end
  if self.panelsTitle then self.panelsTitle:SetText("Session") end

  local activeSession, activeProfileName = GetActiveLootSession()
  local activeSessionProfile = activeSession and root.profiles and root.profiles[activeProfileName] or nil
  activeSessionProfile = type(activeSessionProfile) == "table" and activeSessionProfile or profile
  local activeSessionIsHost = activeSession and tostring(activeSession.host or "") == tostring(selfCharacter)
  local activeSessionMember = activeSession and activeSession.members and activeSession.members[selfCharacter] or nil
  local activeSessionIsJoined = activeSessionIsHost or (type(activeSessionMember) == "table" and tostring(activeSessionMember.status or "JOINED") == "JOINED")
  local roleLabel = string.format(
    "%s | %s",
    FormatLootProfileRoleLabel(access.role),
    activeSessionIsHost and "Session Host" or (activeSessionIsJoined and "Joined Member" or "Observer")
  )
  local liveSummaryProvider = ResolveOptionalApiFunction("LIDCOUNCIL_GetLiveLootBoardSummary")
  local liveSummaryState = liveSummaryProvider and liveSummaryProvider() or nil
  local inCombat = IsCombatLocked()

  for _, button in ipairs(self.lootSessionNavButtons or {}) do
    SetListButtonSelected(button, false)
    SetTextListButtonTextColor(button, { 0.92, 0.92, 0.96, 1.00 })
  end
  if roleSimBtn then
    roleSimBtn:SetShown(isSimulationProfile)
  end
  if section == "CURRENT" then
    if currentBtn then
      SetListButtonSelected(currentBtn, true)
      SetTextListButtonTextColor(currentBtn, { 1.00, 0.88, 0.32, 1.00 })
    end
  elseif section == "SYNCMGMT" then
    if syncMgmtBtn then
      SetListButtonSelected(syncMgmtBtn, true)
      SetTextListButtonTextColor(syncMgmtBtn, { 1.00, 0.88, 0.32, 1.00 })
    end
  elseif section == "ROLESIM" then
    if roleSimBtn then
      SetListButtonSelected(roleSimBtn, true)
      SetTextListButtonTextColor(roleSimBtn, { 1.00, 0.88, 0.32, 1.00 })
    end
  elseif section == "AUTOPASS" then
    if autoPassSettingsBtn then
      SetListButtonSelected(autoPassSettingsBtn, true)
      SetTextListButtonTextColor(autoPassSettingsBtn, { 1.00, 0.88, 0.32, 1.00 })
    end
  else
    if historyBtn then
      SetListButtonSelected(historyBtn, true)
      SetTextListButtonTextColor(historyBtn, { 1.00, 0.88, 0.32, 1.00 })
    end
  end

  if startBtn and startBtn.Enable then
    if activeSession or not access.canStartSession or inCombat then
      startBtn:Disable()
    else
      startBtn:Enable()
    end
  end
  local activeSessionStatus = string.upper(TrimText(activeSession and activeSession.status or ""))
  local activeSessionIsPreparing = activeSessionStatus == "PREPARING"
  if activateBtn and activateBtn.Enable then
    if activeSession and activeSessionIsPreparing and activeSessionIsHost and access.canStartSession and not inCombat then
      activateBtn:Enable()
    else
      activateBtn:Disable()
    end
  end
  if stopBtn and stopBtn.Enable then
    if activeSession and activeSessionIsHost and access.canManageSession then
      stopBtn:Enable()
    else
      stopBtn:Disable()
    end
  end
  if inviteBtn and inviteBtn.Enable then
    if activeSession and activeSessionIsHost and access.canManageSession and not inCombat then
      inviteBtn:Enable()
    else
      inviteBtn:Disable()
    end
  end
  if removeMemberBtn and removeMemberBtn.Enable then
    local selectedMemberKey = TrimText(self.lootSessionSelectedMemberKey)
    local selectedMember = activeSession and activeSession.members and activeSession.members[selectedMemberKey] or nil
    local selectedIsHost = activeSession and string.lower(TrimText(activeSession.host)) == string.lower(selectedMemberKey)
    local selectedIsSelf = string.lower(selectedMemberKey) == string.lower(selfCharacter)
    if activeSession and activeSessionIsHost and access.canManageSession and selectedMember and not selectedIsHost and not selectedIsSelf and not inCombat then
      removeMemberBtn:Enable()
    else
      removeMemberBtn:Disable()
    end
  end
  if pushProfileBtn and pushProfileBtn.Enable then
    if activeSession and activeSessionIsHost and access.canManageSession then
      pushProfileBtn:Enable()
    else
      pushProfileBtn:Disable()
    end
  end

  local showingCurrent = (section == "CURRENT")
  local showingSyncManagement = (section == "SYNCMGMT")
  local showingRoleSimulation = (section == "ROLESIM")
  local showingAutoPassSetting = (section == "AUTOPASS")
  local showingHistory = not showingCurrent and not showingSyncManagement and not showingRoleSimulation and not showingAutoPassSetting

  if showingSyncManagement then
    RefreshSyncManagementView(self, {
      activeSession = activeSession,
      activeSessionIsHost = activeSessionIsHost,
      access = access,
    })
    syncDashboardFrame = self.lootSessionSyncDashboardFrame
    syncScopeFrame = self.lootSessionSyncScopeFrame
  else
    self.lootSessionAllSyncCandidates = {}
    self.lootSessionSyncCandidates = {}
  end

  local historyRowsData = section == "HISTORY" and BuildSessionHistoryRowsData(profile, selfCharacter) or {}
  local historyExpanded = self.lootSessionHistoryExpanded or {}
  self.lootSessionHistoryExpanded = historyExpanded
  RefreshSessionHistoryRows(self, historyRowsData, historyExpanded)

  if startBtn then startBtn:SetShown(showingCurrent) end
  if activateBtn then activateBtn:SetShown(showingCurrent) end
  if stopBtn then stopBtn:SetShown(showingCurrent) end
  if inviteBtn then inviteBtn:SetShown(showingCurrent) end
  if removeMemberBtn then removeMemberBtn:SetShown(showingCurrent) end
  if checkSyncBtn then checkSyncBtn:SetShown(showingSyncManagement) end
  if pushProfileBtn then pushProfileBtn:SetShown(showingSyncManagement) end
  if profileSyncDropdown then profileSyncDropdown:SetShown(showingSyncManagement) end
  if recommendedRepairBtn then recommendedRepairBtn:SetShown(showingSyncManagement) end
  if requestProfileBtn then requestProfileBtn:SetShown(showingSyncManagement) end
  if previewProfileBtn then previewProfileBtn:SetShown(showingSyncManagement) end
  if syncBoardBtn then syncBoardBtn:SetShown(showingSyncManagement) end
  if self.lootSessionSyncHistoryFrame then
    self.lootSessionSyncHistoryFrame:SetShown(showingSyncManagement)
  end
  if self.lootSessionSyncSelectedHint then
    self.lootSessionSyncSelectedHint:SetShown(showingSyncManagement and TrimText(self.lootSessionSyncSelectedHint:GetText()) ~= "")
  end
  if self.lootSessionProfileSyncStatus then
    self.lootSessionProfileSyncStatus:SetShown(showingSyncManagement and TrimText(self.lootSessionProfileSyncStatus:GetText()) ~= "")
  end
  if self.lootSessionSyncProgress then
    self.lootSessionSyncProgress:SetShown(false)
  end
  if self.lootSessionSyncProgressFrame then
    self.lootSessionSyncProgressFrame:SetShown(showingSyncManagement)
  end
  if liveSummary then liveSummary:SetShown(showingCurrent) end
  if overviewFrame then overviewFrame:SetShown(showingCurrent) end
  if currentMembersHeader then currentMembersHeader:SetShown(showingCurrent and activeSession ~= nil) end
  if memberColumns then memberColumns:SetShown(showingCurrent and activeSession ~= nil) end
  if memberRowsFrame then memberRowsFrame:SetShown(showingCurrent and activeSession ~= nil) end
  if historyHeader then historyHeader:SetShown(showingHistory) end
  if historyColumns then historyColumns:SetShown(showingHistory) end
  if historyRowsFrame then historyRowsFrame:SetShown(showingHistory) end
  if roleSimHeader then roleSimHeader:SetShown(showingRoleSimulation) end
  if roleSimDesc then roleSimDesc:SetShown(showingRoleSimulation) end
  if roleSimCurrent then roleSimCurrent:SetShown(showingRoleSimulation) end
  if roleSimMasterBtn then roleSimMasterBtn:SetShown(showingRoleSimulation) end
  if roleSimSessionHostBtn then roleSimSessionHostBtn:SetShown(showingRoleSimulation) end
  if roleSimCouncilBtn then roleSimCouncilBtn:SetShown(showingRoleSimulation) end
  if roleSimRaiderBtn then roleSimRaiderBtn:SetShown(showingRoleSimulation) end
  if roleSimMatrixFrame then roleSimMatrixFrame:SetShown(showingRoleSimulation) end
  if roleSimMatrixHeader then roleSimMatrixHeader:SetShown(showingRoleSimulation) end
  for _, row in ipairs(self.lootSessionRoleSimMatrixRows or {}) do
    row:SetShown(showingRoleSimulation)
  end
  if roleSimState then roleSimState:SetShown(showingRoleSimulation) end
  if autoPassHeader then autoPassHeader:SetShown(showingAutoPassSetting) end
  if autoPassDesc then autoPassDesc:SetShown(showingAutoPassSetting) end
  if autoPassCurrent then autoPassCurrent:SetShown(false) end
  if autoPassLocalBtn then autoPassLocalBtn:SetShown(showingAutoPassSetting) end
  if autoPassState then autoPassState:SetShown(showingAutoPassSetting) end
  if syncCheckHeader then syncCheckHeader:SetShown(showingSyncManagement) end
  if syncIntro then syncIntro:SetShown(false) end
  if syncDashboardFrame then syncDashboardFrame:SetShown(showingSyncManagement) end
  if syncScopeFrame then syncScopeFrame:SetShown(showingSyncManagement) end
  if syncPushHeader then syncPushHeader:SetShown(showingSyncManagement) end
  if syncPullHeader then syncPullHeader:SetShown(showingSyncManagement) end
  if syncAutoHeader then syncAutoHeader:SetShown(showingSyncManagement) end
  if syncAutoText then syncAutoText:SetShown(showingSyncManagement) end
  if syncManualHeader then syncManualHeader:SetShown(showingSyncManagement) end
  if syncManualText then syncManualText:SetShown(showingSyncManagement) end
  if syncReviewHeader then syncReviewHeader:SetShown(false) end
  if syncReviewColumns then syncReviewColumns:SetShown(false) end
  if syncReviewRowsFrame then syncReviewRowsFrame:SetShown(false) end
  if syncReviewEmpty then syncReviewEmpty:SetShown(false) end
  if body then
    body:SetShown(showingHistory)
  end
  if not showingSyncManagement then
    for _, row in ipairs(self.lootSessionSyncReviewRows or {}) do
      row:Hide()
    end
  end

  if section == "CURRENT" then
    RefreshCurrentSessionView(self, {
      activeSession = activeSession,
      activeSessionProfile = activeSessionProfile,
      selfCharacter = selfCharacter,
      activeSessionIsHost = activeSessionIsHost,
      activeSessionIsJoined = activeSessionIsJoined,
      activeProfileName = activeProfileName,
      profileName = profileName,
      roleLabel = roleLabel,
      liveSummaryState = liveSummaryState,
    })
  elseif showingSyncManagement then
    -- RefreshSyncManagementView already populated the sync-management content.
  elseif showingRoleSimulation then
    RefreshRoleSimulationView(self, {
      profileName = profileName,
      access = access,
    })
  elseif showingAutoPassSetting then
    RefreshAutoPassView(self, {
      activeSession = activeSession,
      selfCharacter = selfCharacter,
    })
  else
    self.lootSessionTitle:SetText("Session History")
    self.lootSessionStatus:SetText("Profile: " .. tostring(profileName))
    self.lootSessionStatus:SetTextColor(0.82, 0.82, 0.86, 1.00)
    ApplyTrafficLight(self.lootSessionStatusIndicator, #historyRowsData > 0 and "SYNCED" or "PENDING")
    if body then
      body:SetText("")
      body:SetShown(false)
    end
  end

  if self.LayoutLootSessionPage then
    self:LayoutLootSessionPage()
  end
  SetCurrentProfileFont(self.panelsCurrentLabel, "Current Profile: " .. tostring(profileName), nil)
  if self.UpdateScrollLayout then
    self:UpdateScrollLayout()
  end
end

local CreateLootSessionCurrentHelpers = INTERNAL_API.LIDCOUNCIL_CreateLootSessionCurrentHelpers_Impl
if type(CreateLootSessionCurrentHelpers) ~= "function" then
  error("LidCouncil missing loot session current helpers.")
end

local lootSessionCurrentHelpers = CreateLootSessionCurrentHelpers({
  ApplyFrameSkin = ApplyFrameSkin,
  RootDB = RootDB,
  TrimText = TrimText,
  ResolveSessionDisplayInfo = ResolveSessionDisplayInfo,
  ResolveSessionSyncState = ResolveSessionSyncState,
  ResolveSessionBootstrapState = ResolveSessionBootstrapState,
  ResolveSessionIconData = ResolveSessionIconData,
  ApplySessionIcon = ApplySessionIcon,
  GetSessionClassColor = GetSessionClassColor,
  GetSessionSyncLabel = GetSessionSyncLabel,
  GetSessionSyncDescription = GetSessionSyncDescription,
  GetSessionBootstrapLabel = GetSessionBootstrapLabel,
  GetSessionBootstrapDescription = GetSessionBootstrapDescription,
  GetSessionBootstrapColor = GetSessionBootstrapColor,
  ApplyTrafficLight = ApplyTrafficLight,
  GetTrafficLightColor = GetTrafficLightColor,
  GetSessionStatusColor = GetSessionStatusColor,
  GetLocalAutoPassEnabled = rawget(_G, "LIDCOUNCIL_GetLocalAutoPassEnabled"),
  FormatDateTime = FormatDateTime,
  FlowLayoutControls = FlowLayoutControls,
  ClampLayoutValue = ClampLayoutValue,
})

RefreshCurrentSessionView = lootSessionCurrentHelpers.RefreshCurrentSessionView
LayoutCurrentSessionSection = lootSessionCurrentHelpers.LayoutCurrentSessionSection

local CreateLootSessionHistoryHelpers = INTERNAL_API.LIDCOUNCIL_CreateLootSessionHistoryHelpers_Impl
if type(CreateLootSessionHistoryHelpers) ~= "function" then
  error("LidCouncil missing loot session history helpers.")
end

local lootSessionHistoryHelpers = CreateLootSessionHistoryHelpers({
  ApplyFrameSkin = ApplyFrameSkin,
  TrimText = TrimText,
  ResolveSessionDisplayInfo = ResolveSessionDisplayInfo,
  ResolveSessionSyncState = ResolveSessionSyncState,
  ResolveSessionIconData = ResolveSessionIconData,
  ApplySessionIcon = ApplySessionIcon,
  GetSessionClassColor = GetSessionClassColor,
  GetSessionStatusColor = GetSessionStatusColor,
  GetTrafficLightColor = GetTrafficLightColor,
  GetSessionSyncLabel = GetSessionSyncLabel,
  ApplyTrafficLight = ApplyTrafficLight,
  FormatDateTime = FormatDateTime,
  FormatDuration = FormatDuration,
})

BuildSessionHistoryRowsData = lootSessionHistoryHelpers.BuildSessionHistoryRowsData
RefreshSessionHistoryRows = lootSessionHistoryHelpers.RefreshSessionHistoryRows
LayoutSessionHistorySection = lootSessionHistoryHelpers.LayoutSessionHistorySection

local CreateLootSessionSyncHelpers = INTERNAL_API.LIDCOUNCIL_CreateLootSessionSyncHelpers_Impl
if type(CreateLootSessionSyncHelpers) ~= "function" then
  error("LidCouncil missing loot session sync helpers.")
end

local lootSessionSyncHelpers = CreateLootSessionSyncHelpers({
  ApplyFrameSkin = ApplyFrameSkin,
  RootDB = RootDB,
  TrimText = TrimText,
  GetSessionClassColor = GetSessionClassColor,
  ResolveOptionalApiFunction = ResolveOptionalApiFunction,
  FlowLayoutControls = FlowLayoutControls,
  ClampLayoutValue = ClampLayoutValue,
  FormatDateTime = FormatDateTime,
  ApplyTrafficLight = ApplyTrafficLight,
})

RefreshSyncManagementView = lootSessionSyncHelpers.RefreshSyncManagementView
LayoutSyncManagementSection = lootSessionSyncHelpers.LayoutSyncManagementSection

local CreateLootSessionRoleSimHelpers = INTERNAL_API.LIDCOUNCIL_CreateLootSessionRoleSimHelpers_Impl
if type(CreateLootSessionRoleSimHelpers) ~= "function" then
  error("LidCouncil missing loot session role simulation helpers.")
end

local lootSessionRoleSimHelpers = CreateLootSessionRoleSimHelpers({
  TrimText = TrimText,
  ResolveOptionalApiFunction = ResolveOptionalApiFunction,
  GetLootProfilePermissionPolicyRoleState = GetLootProfilePermissionPolicyRoleState,
  ApplyTrafficLight = ApplyTrafficLight,
  SetListButtonSelected = SetListButtonSelected,
  SetTextListButtonTextColor = SetTextListButtonTextColor,
  FlowLayoutControls = FlowLayoutControls,
  ClampLayoutValue = ClampLayoutValue,
  FormatLootProfileRoleLabel = FormatLootProfileRoleLabel,
})

RefreshRoleSimulationView = lootSessionRoleSimHelpers.RefreshRoleSimulationView
LayoutRoleSimulationSection = lootSessionRoleSimHelpers.LayoutRoleSimulationSection
SIMULATION_ROLE_OPTIONS = lootSessionRoleSimHelpers.SIMULATION_ROLE_OPTIONS or {}
ROLE_SIM_RIGHTS_MATRIX = lootSessionRoleSimHelpers.ROLE_SIM_RIGHTS_MATRIX or {}

local CreateLootSessionAutoPassHelpers = INTERNAL_API.LIDCOUNCIL_CreateLootSessionAutoPassHelpers_Impl
if type(CreateLootSessionAutoPassHelpers) ~= "function" then
  error("LidCouncil missing loot session auto pass helpers.")
end

local lootSessionAutoPassHelpers = CreateLootSessionAutoPassHelpers({
  TrimText = TrimText,
  ResolveOptionalApiFunction = ResolveOptionalApiFunction,
  ApplyTrafficLight = ApplyTrafficLight,
})

RefreshAutoPassView = lootSessionAutoPassHelpers.RefreshAutoPassView
LayoutAutoPassSection = lootSessionAutoPassHelpers.LayoutAutoPassSection

local function BuildLootSessionPage(editor, page)
  if not editor or not page then
    return
  end

  local navBg, rightBg = CreateSectionShell(page, 220)
  editor.lootSessionNavBg = navBg
  editor.lootSessionRightBg = rightBg

  local rightScroll = CreateFrame("ScrollFrame", nil, rightBg, "UIPanelScrollFrameTemplate")
  rightScroll:SetPoint("TOPLEFT", 6, -6)
  rightScroll:SetPoint("BOTTOMRIGHT", -28, 6)
  rightScroll:EnableMouseWheel(true)
  local rightContent = CreateFrame("Frame", nil, rightScroll)
  rightContent:SetSize(1, 1)
  rightScroll:SetScrollChild(rightContent)
  editor.lootSessionRightScroll = rightScroll
  editor.lootSessionRightContent = rightContent

  local rightBg = rightContent

  local navTitle = navBg:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
  navTitle:SetPoint("TOPLEFT", 8, -8)
  navTitle:SetText("Session")

  local currentBtn = CreateFrame("Button", nil, navBg, "UIPanelButtonTemplate")
  currentBtn:SetSize(200, 22)
  currentBtn:SetPoint("TOPLEFT", 8, -34)
  currentBtn:SetText("Current Session")
  editor.sessionNavCurrentBtn = currentBtn

  local historyBtn = CreateFrame("Button", nil, navBg, "UIPanelButtonTemplate")
  historyBtn:SetSize(200, 22)
  historyBtn:SetPoint("TOPLEFT", 8, -62)
  historyBtn:SetText("Session History")
  editor.sessionNavHistoryBtn = historyBtn

  local syncMgmtBtn = CreateFrame("Button", nil, navBg, "UIPanelButtonTemplate")
  syncMgmtBtn:SetSize(200, 22)
  syncMgmtBtn:SetPoint("TOPLEFT", 8, -90)
  syncMgmtBtn:SetText("Sync Management")
  editor.sessionNavSyncManagementBtn = syncMgmtBtn

  local roleSimBtn = CreateFrame("Button", nil, navBg, "UIPanelButtonTemplate")
  roleSimBtn:SetSize(200, 22)
  roleSimBtn:SetPoint("TOPLEFT", 8, -118)
  roleSimBtn:SetText("Role Simulation")
  editor.sessionNavRoleSimBtn = roleSimBtn

  local autoPassSettingsBtn = CreateFrame("Button", nil, navBg, "UIPanelButtonTemplate")
  autoPassSettingsBtn:SetSize(200, 22)
  autoPassSettingsBtn:SetPoint("TOPLEFT", 8, -146)
  autoPassSettingsBtn:SetText("Auto Pass Setting")
  editor.sessionNavAutoPassSettingsBtn = autoPassSettingsBtn

  editor.lootSessionNavButtons = { currentBtn, historyBtn, syncMgmtBtn, roleSimBtn, autoPassSettingsBtn }

  local title = rightBg:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
  title:SetPoint("TOPLEFT", 18, -16)
  title:SetText("Current Session")
  editor.lootSessionTitle = title

  local statusIndicator = rightBg:CreateTexture(nil, "ARTWORK")
  statusIndicator:SetSize(10, 10)
  statusIndicator:SetPoint("TOPLEFT", 18, -48)
  editor.lootSessionStatusIndicator = statusIndicator

  local status = rightBg:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
  status:SetPoint("LEFT", statusIndicator, "RIGHT", 8, 0)
  status:SetJustifyH("LEFT")
  status:SetText("No active session")
  editor.lootSessionStatus = status

  local startBtn = CreateFrame("Button", nil, rightBg, "UIPanelButtonTemplate")
  startBtn:SetSize(120, 22)
  startBtn:SetPoint("TOPLEFT", 18, -78)
  startBtn:SetText("Prepare Session")
  editor.sessionStartBtn = startBtn

  local activateBtn = CreateFrame("Button", nil, rightBg, "UIPanelButtonTemplate")
  activateBtn:SetSize(120, 22)
  activateBtn:SetPoint("LEFT", startBtn, "RIGHT", 10, 0)
  activateBtn:SetText("Start Session")
  editor.sessionActivateBtn = activateBtn

  local stopBtn = CreateFrame("Button", nil, rightBg, "UIPanelButtonTemplate")
  stopBtn:SetSize(120, 22)
  stopBtn:SetPoint("LEFT", activateBtn, "RIGHT", 10, 0)
  stopBtn:SetText("Stop Session")
  editor.sessionStopBtn = stopBtn

  local inviteBtn = CreateFrame("Button", nil, rightBg, "UIPanelButtonTemplate")
  inviteBtn:SetSize(140, 22)
  inviteBtn:SetPoint("LEFT", stopBtn, "RIGHT", 10, 0)
  inviteBtn:SetText("Send Session Invite")
  editor.sessionInviteBtn = inviteBtn

  local removeMemberBtn = CreateFrame("Button", nil, rightBg, "UIPanelButtonTemplate")
  removeMemberBtn:SetSize(150, 22)
  removeMemberBtn:SetPoint("LEFT", inviteBtn, "RIGHT", 10, 0)
  removeMemberBtn:SetText("Remove Member")
  editor.sessionRemoveMemberBtn = removeMemberBtn

  local pushProfileBtn = CreateFrame("Button", nil, rightBg, "UIPanelButtonTemplate")
  pushProfileBtn:SetSize(146, 22)
  pushProfileBtn:SetPoint("LEFT", removeMemberBtn, "RIGHT", 10, 0)
  pushProfileBtn:SetText("Push Host Repair")
  editor.sessionPushProfileBtn = pushProfileBtn

  local checkSyncBtn = CreateFrame("Button", nil, rightBg, "UIPanelButtonTemplate")
  checkSyncBtn:SetSize(154, 22)
  checkSyncBtn:SetText("Check Differences")
  editor.sessionCheckSyncBtn = checkSyncBtn

  local profileSyncDropdown = CreateCustomDropdownControl(editor, rightBg, {
    width = 320,
    buttonHeight = 22,
    text = "No member update review needed",
    maxVisibleEntries = 12,
  })
  editor.sessionProfileSyncMemberDropdown = profileSyncDropdown

  local requestProfileBtn = CreateFrame("Button", nil, rightBg, "UIPanelButtonTemplate")
  requestProfileBtn:SetSize(172, 22)
  requestProfileBtn:SetText("Pull Member Repair")
  editor.sessionRequestProfileBtn = requestProfileBtn

  local recommendedRepairBtn = CreateFrame("Button", nil, rightBg, "UIPanelButtonTemplate")
  recommendedRepairBtn:SetSize(178, 22)
  recommendedRepairBtn:SetText("Run Recommended Repair")
  editor.sessionRecommendedRepairBtn = recommendedRepairBtn

  local previewProfileBtn = CreateFrame("Button", nil, rightBg, "UIPanelButtonTemplate")
  previewProfileBtn:SetSize(172, 22)
  previewProfileBtn:SetText("Preview Member Repair")
  editor.sessionPreviewProfileBtn = previewProfileBtn

  local profileSyncSelectedHint = rightBg:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  profileSyncSelectedHint:SetJustifyH("LEFT")
  profileSyncSelectedHint:SetText("")
  editor.lootSessionSyncSelectedHint = profileSyncSelectedHint

  local profileSyncStatus = rightBg:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  profileSyncStatus:SetJustifyH("LEFT")
  profileSyncStatus:SetText("")
  editor.lootSessionProfileSyncStatus = profileSyncStatus

  local syncProgress = rightBg:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  syncProgress:SetJustifyH("LEFT")
  syncProgress:SetText("")
  editor.lootSessionSyncProgress = syncProgress

  local syncBoardBtn = CreateFrame("Button", nil, rightBg, "UIPanelButtonTemplate")
  syncBoardBtn:SetSize(126, 22)
  syncBoardBtn:SetPoint("TOPRIGHT", -18, -142)
  syncBoardBtn:SetText("Send Board Sync")
  syncBoardBtn:Hide()
  editor.sessionSyncBoardBtn = syncBoardBtn

  local liveSummary = rightBg:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  liveSummary:SetPoint("TOPLEFT", 18, -106)
  liveSummary:SetWidth(560)
  liveSummary:SetJustifyH("LEFT")
  liveSummary:SetText("")
  editor.lootSessionLiveSummary = liveSummary

  local overviewFrame = CreateFrame("Frame", nil, rightBg, "BackdropTemplate")
  ApplyFrameSkin(overviewFrame)
  editor.lootSessionOverviewFrame = overviewFrame

  local overviewTitle = overviewFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
  overviewTitle:SetPoint("TOPLEFT", 14, -12)
  overviewTitle:SetJustifyH("LEFT")
  editor.lootSessionOverviewTitle = overviewTitle

  local overviewMeta = overviewFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  overviewMeta:SetPoint("TOPLEFT", 14, -34)
  overviewMeta:SetJustifyH("LEFT")
  editor.lootSessionOverviewMeta = overviewMeta

  editor.lootSessionOverviewCards = {}
  for _, label in ipairs({ "Profile", "Role", "Session Start", "Members", "Host", "Roll Ready", "Session Sync" }) do
    local card = CreateFrame("Frame", nil, overviewFrame, "BackdropTemplate")
    ApplyFrameSkin(card)
    local valueText = card:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    valueText:SetPoint("TOPLEFT", 10, -12)
    valueText:SetJustifyH("LEFT")
    local labelText = card:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    labelText:SetPoint("TOPLEFT", 10, -34)
    labelText:SetJustifyH("LEFT")
    labelText:SetText(label)
    local dot = card:CreateTexture(nil, "ARTWORK")
    dot:SetSize(8, 8)
    dot:SetPoint("TOPRIGHT", -10, -14)
    dot:Hide()
    editor.lootSessionOverviewCards[#editor.lootSessionOverviewCards + 1] = {
      frame = card,
      valueText = valueText,
      labelText = labelText,
      dot = dot,
      label = label,
    }
  end

  local currentMembersHeader = MakeYellowSubHeader(rightBg, "Joined Members", 18, -240)
  editor.lootSessionMembersHeader = currentMembersHeader

  local memberColumns = CreateFrame("Frame", nil, rightBg, "BackdropTemplate")
  ApplyFrameSkin(memberColumns)
  if memberColumns.SetBackdropColor then
    memberColumns:SetBackdropColor(0.06, 0.06, 0.08, 0.98)
  end
  editor.lootSessionMemberColumns = memberColumns
  local memberHeaderName = memberColumns:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  memberHeaderName:SetJustifyH("LEFT")
  memberHeaderName:SetText("Raider")
  editor.lootSessionMemberHeaderName = memberHeaderName
  local memberHeaderSync = memberColumns:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  memberHeaderSync:SetJustifyH("LEFT")
  memberHeaderSync:SetText("Sync")
  editor.lootSessionMemberHeaderSync = memberHeaderSync
  local memberHeaderAutoPass = memberColumns:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  memberHeaderAutoPass:SetJustifyH("LEFT")
  memberHeaderAutoPass:SetText("Auto-Pass")
  editor.lootSessionMemberHeaderAutoPass = memberHeaderAutoPass
  local memberHeaderVersion = memberColumns:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  memberHeaderVersion:SetJustifyH("LEFT")
  memberHeaderVersion:SetText("Version")
  editor.lootSessionMemberHeaderVersion = memberHeaderVersion
  local memberHeaderStatus = memberColumns:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  memberHeaderStatus:SetJustifyH("LEFT")
  memberHeaderStatus:SetText("Join Status")
  editor.lootSessionMemberHeaderStatus = memberHeaderStatus
  local memberHeaderJoined = memberColumns:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  memberHeaderJoined:SetJustifyH("LEFT")
  memberHeaderJoined:SetText("Joined")
  editor.lootSessionMemberHeaderJoined = memberHeaderJoined

  local memberRowsFrame = CreateFrame("Frame", nil, rightBg)
  editor.lootSessionMemberRowsFrame = memberRowsFrame
  editor.lootSessionMemberRows = {}

  local historyHeader = MakeYellowSubHeader(rightBg, "Session History", 18, -78)
  editor.lootSessionHistoryHeader = historyHeader

  local historyColumns = CreateFrame("Frame", nil, rightBg, "BackdropTemplate")
  ApplyFrameSkin(historyColumns)
  if historyColumns.SetBackdropColor then
    historyColumns:SetBackdropColor(0.06, 0.06, 0.08, 0.98)
  end
  editor.lootSessionHistoryColumns = historyColumns

  local historyHeaderStarted = historyColumns:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  historyHeaderStarted:SetJustifyH("LEFT")
  historyHeaderStarted:SetText("Started")
  editor.lootSessionHistoryHeaderStarted = historyHeaderStarted

  local historyHeaderHost = historyColumns:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  historyHeaderHost:SetJustifyH("LEFT")
  historyHeaderHost:SetText("Host")
  editor.lootSessionHistoryHeaderHost = historyHeaderHost

  local historyHeaderMembers = historyColumns:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  historyHeaderMembers:SetJustifyH("LEFT")
  historyHeaderMembers:SetText("Members")
  editor.lootSessionHistoryHeaderMembers = historyHeaderMembers

  local historyHeaderSource = historyColumns:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  historyHeaderSource:SetJustifyH("LEFT")
  historyHeaderSource:SetText("Source")
  editor.lootSessionHistoryHeaderSource = historyHeaderSource

  local historyHeaderResult = historyColumns:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  historyHeaderResult:SetJustifyH("LEFT")
  historyHeaderResult:SetText("Result")
  editor.lootSessionHistoryHeaderResult = historyHeaderResult

  local historyRowsFrame = CreateFrame("Frame", nil, rightBg)
  editor.lootSessionHistoryRowsFrame = historyRowsFrame
  editor.lootSessionHistoryRows = {}
  editor.lootSessionHistoryExpanded = editor.lootSessionHistoryExpanded or {}

  local roleSimHeader = MakeYellowSubHeader(rightBg, "Role Simulation", 18, -78)
  editor.lootSessionRoleSimHeader = roleSimHeader

  local roleSimDesc = rightBg:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  roleSimDesc:SetJustifyH("LEFT")
  roleSimDesc:SetText("")
  editor.lootSessionRoleSimDesc = roleSimDesc

  local roleSimCurrent = rightBg:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
  roleSimCurrent:SetJustifyH("LEFT")
  roleSimCurrent:SetText("")
  editor.lootSessionRoleSimCurrent = roleSimCurrent

  local roleSimMasterBtn = CreateFrame("Button", nil, rightBg, "UIPanelButtonTemplate")
  roleSimMasterBtn:SetSize(120, 22)
  roleSimMasterBtn:SetText("Master")
  editor.sessionRoleSimMasterBtn = roleSimMasterBtn

  local roleSimCouncilBtn = CreateFrame("Button", nil, rightBg, "UIPanelButtonTemplate")
  roleSimCouncilBtn:SetSize(140, 22)
  roleSimCouncilBtn:SetText("Council Member")
  editor.sessionRoleSimCouncilBtn = roleSimCouncilBtn

  local roleSimSessionHostBtn = CreateFrame("Button", nil, rightBg, "UIPanelButtonTemplate")
  roleSimSessionHostBtn:SetSize(130, 22)
  roleSimSessionHostBtn:SetText("Session Host")
  editor.sessionRoleSimSessionHostBtn = roleSimSessionHostBtn

  local roleSimRaiderBtn = CreateFrame("Button", nil, rightBg, "UIPanelButtonTemplate")
  roleSimRaiderBtn:SetSize(120, 22)
  roleSimRaiderBtn:SetText("Raider")
  editor.sessionRoleSimRaiderBtn = roleSimRaiderBtn

  local roleSimState = rightBg:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  roleSimState:SetJustifyH("LEFT")
  roleSimState:SetText("")
  editor.lootSessionRoleSimState = roleSimState

  local roleSimMatrixFrame = CreateFrame("Frame", nil, rightBg)
  editor.lootSessionRoleSimMatrixFrame = roleSimMatrixFrame

  local roleSimMatrixHeader = CreateFrame("Frame", nil, roleSimMatrixFrame)
  editor.lootSessionRoleSimMatrixHeader = roleSimMatrixHeader

  local matrixHeaderRight = roleSimMatrixHeader:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  matrixHeaderRight:SetJustifyH("LEFT")
  matrixHeaderRight:SetText("Rights")
  editor.lootSessionRoleSimHeaderRight = matrixHeaderRight

  local matrixHeaderMaster = roleSimMatrixHeader:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  matrixHeaderMaster:SetJustifyH("CENTER")
  matrixHeaderMaster:SetText("Master")
  editor.lootSessionRoleSimHeaderMaster = matrixHeaderMaster

  local matrixHeaderSessionHost = roleSimMatrixHeader:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  matrixHeaderSessionHost:SetJustifyH("CENTER")
  matrixHeaderSessionHost:SetText("Session Host")
  editor.lootSessionRoleSimHeaderSessionHost = matrixHeaderSessionHost

  local matrixHeaderCouncil = roleSimMatrixHeader:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  matrixHeaderCouncil:SetJustifyH("CENTER")
  matrixHeaderCouncil:SetText("Council")
  editor.lootSessionRoleSimHeaderCouncil = matrixHeaderCouncil

  local matrixHeaderRaider = roleSimMatrixHeader:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  matrixHeaderRaider:SetJustifyH("CENTER")
  matrixHeaderRaider:SetText("Raider")
  editor.lootSessionRoleSimHeaderRaider = matrixHeaderRaider

  editor.lootSessionRoleSimMatrixRows = {}
  for _, rowDef in ipairs(ROLE_SIM_RIGHTS_MATRIX) do
    local row = CreateFrame("Frame", nil, roleSimMatrixFrame, "BackdropTemplate")
    ApplyFrameSkin(row)
    row.__isRoleSimSection = rowDef.section and true or false
    if row.SetBackdropColor then
      if row.__isRoleSimSection then
        row:SetBackdropColor(0, 0, 0, 0)
      else
        row:SetBackdropColor(0.05, 0.05, 0.07, 0.94)
      end
    end
    if row.__isRoleSimSection and row.SetBackdropBorderColor then
      row:SetBackdropBorderColor(0, 0, 0, 0)
    end
    local rightText = row:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    rightText:SetJustifyH("LEFT")
    rightText:SetText(rowDef.section or rowDef.right)
    local masterText = row:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    masterText:SetJustifyH("CENTER")
    local sessionHostText = row:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    sessionHostText:SetJustifyH("CENTER")
    local councilText = row:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    councilText:SetJustifyH("CENTER")
    local raiderText = row:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
    raiderText:SetJustifyH("CENTER")
    row.masterText = masterText
    row.sessionHostText = sessionHostText
    row.councilText = councilText
    row.raiderText = raiderText
    row.rightText = rightText
    row.definition = rowDef
    editor.lootSessionRoleSimMatrixRows[#editor.lootSessionRoleSimMatrixRows + 1] = row
  end

  local autoPassHeader = MakeYellowSubHeader(rightBg, "Auto Pass Setting", 18, -78)
  editor.lootSessionAutoPassHeader = autoPassHeader

  local autoPassDesc = rightBg:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  autoPassDesc:SetJustifyH("LEFT")
  autoPassDesc:SetText("")
  editor.lootSessionAutoPassDesc = autoPassDesc

  local autoPassCurrent = rightBg:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
  autoPassCurrent:SetJustifyH("LEFT")
  autoPassCurrent:SetText("")
  editor.lootSessionAutoPassCurrent = autoPassCurrent

  local autoPassLocalBtn = CreateFrame("Button", nil, rightBg, "UIPanelButtonTemplate")
  autoPassLocalBtn:SetSize(190, 22)
  autoPassLocalBtn:SetText("Deactivate Auto-Pass")
  editor.sessionAutoPassLocalBtn = autoPassLocalBtn

  local autoPassState = rightBg:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  autoPassState:SetJustifyH("LEFT")
  autoPassState:SetText("")
  editor.lootSessionAutoPassState = autoPassState

  local syncCheckHeader = MakeYellowSubHeader(rightBg, "1. Check Differences", 18, -78)
  editor.lootSessionSyncCheckHeader = syncCheckHeader

  local syncIntro = rightBg:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  syncIntro:SetJustifyH("LEFT")
  syncIntro:SetText("")
  editor.lootSessionSyncIntro = syncIntro

  local syncPushHeader = MakeYellowSubHeader(rightBg, "2. Repair From Host", 18, -78)
  editor.lootSessionSyncPushHeader = syncPushHeader

  local syncPullHeader = MakeYellowSubHeader(rightBg, "3. Pull Repair From Member", 18, -78)
  editor.lootSessionSyncPullHeader = syncPullHeader

  local syncAutoHeader = MakeYellowSubHeader(rightBg, "Automatic Syncs", 18, -78)
  editor.lootSessionSyncAutoHeader = syncAutoHeader

  local syncAutoText = rightBg:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  syncAutoText:SetJustifyH("LEFT")
  syncAutoText:SetText("")
  editor.lootSessionSyncAutoText = syncAutoText

  local syncManualHeader = MakeYellowSubHeader(rightBg, "Manual Syncs", 18, -78)
  editor.lootSessionSyncManualHeader = syncManualHeader

  local syncManualText = rightBg:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  syncManualText:SetJustifyH("LEFT")
  syncManualText:SetText("")
  editor.lootSessionSyncManualText = syncManualText

  local syncReviewHeader = MakeYellowSubHeader(rightBg, "Joined Copy Status", 18, -78)
  editor.lootSessionSyncReviewHeader = syncReviewHeader

  local syncReviewColumns = CreateFrame("Frame", nil, rightBg, "BackdropTemplate")
  ApplyFrameSkin(syncReviewColumns)
  if syncReviewColumns.SetBackdropColor then
    syncReviewColumns:SetBackdropColor(0.06, 0.06, 0.08, 0.98)
  end
  editor.lootSessionSyncReviewColumns = syncReviewColumns

  local syncReviewHeaderMember = syncReviewColumns:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  syncReviewHeaderMember:SetJustifyH("LEFT")
  syncReviewHeaderMember:SetText("Member")
  editor.lootSessionSyncReviewHeaderMember = syncReviewHeaderMember

  local syncReviewHeaderState = syncReviewColumns:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  syncReviewHeaderState:SetJustifyH("LEFT")
  syncReviewHeaderState:SetText("State")
  editor.lootSessionSyncReviewHeaderState = syncReviewHeaderState

  local syncReviewHeaderRemote = syncReviewColumns:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  syncReviewHeaderRemote:SetJustifyH("LEFT")
  syncReviewHeaderRemote:SetText("Member Newer")
  editor.lootSessionSyncReviewHeaderRemote = syncReviewHeaderRemote

  local syncReviewHeaderLocal = syncReviewColumns:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  syncReviewHeaderLocal:SetJustifyH("LEFT")
  syncReviewHeaderLocal:SetText("Host Newer")
  editor.lootSessionSyncReviewHeaderLocal = syncReviewHeaderLocal

  local syncReviewHeaderUpdated = syncReviewColumns:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  syncReviewHeaderUpdated:SetJustifyH("LEFT")
  syncReviewHeaderUpdated:SetText("Last Change")
  editor.lootSessionSyncReviewHeaderUpdated = syncReviewHeaderUpdated

  local syncReviewHeaderSession = syncReviewColumns:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  syncReviewHeaderSession:SetJustifyH("LEFT")
  syncReviewHeaderSession:SetText("Session")
  editor.lootSessionSyncReviewHeaderSession = syncReviewHeaderSession

  local syncReviewRowsFrame = CreateFrame("Frame", nil, rightBg)
  editor.lootSessionSyncReviewRowsFrame = syncReviewRowsFrame
  editor.lootSessionSyncReviewRows = {}

  local syncReviewEmpty = rightBg:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  syncReviewEmpty:SetJustifyH("LEFT")
  syncReviewEmpty:SetText("")
  editor.lootSessionSyncReviewEmpty = syncReviewEmpty

  local body = rightBg:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  body:SetPoint("TOPLEFT", 18, -132)
  body:SetWidth(560)
  body:SetJustifyH("LEFT")
  body:SetText("")
  editor.lootSessionBody = body

  local inactiveOverlay = CreateFrame("Frame", nil, page, "BackdropTemplate")
  ApplyFrameSkin(inactiveOverlay)
  inactiveOverlay:SetPoint("TOPLEFT", page, "TOPLEFT", 0, -44)
  inactiveOverlay:SetPoint("BOTTOMRIGHT", page, "BOTTOMRIGHT", 0, 0)
  inactiveOverlay:EnableMouse(true)
  inactiveOverlay:SetFrameStrata("HIGH")
  inactiveOverlay:SetFrameLevel((page.GetFrameLevel and page:GetFrameLevel() or 0) + 20)
  inactiveOverlay:Hide()
  editor.lootSessionInactiveOverlay = inactiveOverlay

  local inactiveText = inactiveOverlay:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
  inactiveText:SetPoint("CENTER", 0, 0)
  inactiveText:SetWidth(520)
  inactiveText:SetJustifyH("CENTER")
  inactiveText:SetJustifyV("MIDDLE")
  inactiveText:SetText(ACTIVATE_PROFILE_REQUIRED_TEXT)
  editor.lootSessionInactiveText = inactiveText

  page.__contentHeight = 720

  local function LayoutLootSessionPage(self)
    if not self or not self.lootSessionRightBg then
      return
    end

    local _, navWidth = GetResponsiveSectionLayout(page, 220, 180, 260, 0.26)
    local rightViewportWidth = math.floor((self.lootSessionRightScroll and self.lootSessionRightScroll.GetWidth and self.lootSessionRightScroll:GetWidth()) or ((self.lootSessionRightBg:GetWidth() or 620) - 34))
    if rightViewportWidth < 320 then
      rightViewportWidth = math.floor((self.lootSessionRightBg:GetWidth() or 620) - 34)
    end
    local rightContentWidth = math.max(300, rightViewportWidth - 36)
    local rightViewportHeight = math.floor((self.lootSessionRightScroll and self.lootSessionRightScroll.GetHeight and self.lootSessionRightScroll:GetHeight()) or ((self.lootSessionRightBg:GetHeight() or 520) - 12))
    if rightViewportHeight < 220 then
      rightViewportHeight = math.floor((self.lootSessionRightBg:GetHeight() or 520) - 12)
    end
    local section = self.lootSessionSection or "CURRENT"
    local showingCurrent = (section == "CURRENT")
    local showingSyncManagement = (section == "SYNCMGMT")
    local showingRoleSimulation = (section == "ROLESIM")
    local isSimulationProfile = TrimText(GetSessionContextProfileName()) == "Simulation"
    local contentBottom = 180

    if self.lootSessionNavBg then
      self.lootSessionNavBg:SetWidth(navWidth)
    end
    if self.sessionNavCurrentBtn then self.sessionNavCurrentBtn:Show() end
    if self.sessionNavHistoryBtn then self.sessionNavHistoryBtn:Show() end
    if self.sessionNavSyncManagementBtn then self.sessionNavSyncManagementBtn:Show() end
    if self.sessionNavRoleSimBtn then self.sessionNavRoleSimBtn:SetShown(isSimulationProfile) end
    if self.sessionNavAutoPassSettingsBtn then self.sessionNavAutoPassSettingsBtn:Show() end
    local navTop = -34
    for _, button in ipairs({
      self.sessionNavCurrentBtn,
      self.sessionNavHistoryBtn,
      self.sessionNavSyncManagementBtn,
      isSimulationProfile and self.sessionNavRoleSimBtn or nil,
      self.sessionNavAutoPassSettingsBtn,
    }) do
      if button then
        button:SetSize(navWidth - 16, 22)
        button:ClearAllPoints()
        button:SetPoint("TOPLEFT", 8, navTop)
        navTop = navTop - 28
      end
    end
    if self.lootSessionLiveSummary then
      self.lootSessionLiveSummary:SetWidth(rightContentWidth)
    end
    if self.lootSessionBody then
      self.lootSessionBody:SetWidth(rightContentWidth)
    end
    if self.lootSessionStatus then
      self.lootSessionStatus:SetWidth(rightContentWidth - 38)
    end
    if self.lootSessionOverviewFrame then
      self.lootSessionOverviewFrame:SetWidth(rightContentWidth)
    end
    if self.lootSessionOverviewMeta then
      self.lootSessionOverviewMeta:SetWidth(rightContentWidth - 28)
    end

    if showingCurrent then
      contentBottom = LayoutCurrentSessionSection(self, page, rightContentWidth)
    elseif showingSyncManagement then
      if self.sessionRoleSimMasterBtn then self.sessionRoleSimMasterBtn:Hide() end
      if self.sessionRoleSimSessionHostBtn then self.sessionRoleSimSessionHostBtn:Hide() end
      if self.sessionRoleSimCouncilBtn then self.sessionRoleSimCouncilBtn:Hide() end
      if self.sessionRoleSimRaiderBtn then self.sessionRoleSimRaiderBtn:Hide() end
      contentBottom = LayoutSyncManagementSection(self, page, rightContentWidth)
    elseif showingRoleSimulation then
      contentBottom = LayoutRoleSimulationSection(self, page, rightContentWidth)
    elseif section == "AUTOPASS" then
      contentBottom = LayoutAutoPassSection(self, page, rightContentWidth)
    else
      if self.sessionSyncBoardBtn then
        self.sessionSyncBoardBtn:Hide()
      end
      local bodyTop = LayoutSessionHistorySection(self, rightContentWidth)
      if self.lootSessionBody then
        self.lootSessionBody:ClearAllPoints()
        self.lootSessionBody:SetPoint("TOPLEFT", 18, bodyTop)
      end
      local bodyHeight = math.max(40, math.ceil((self.lootSessionBody and self.lootSessionBody:IsShown() and self.lootSessionBody:GetStringHeight() or 0)))
      contentBottom = math.abs(bodyTop) + bodyHeight + 24
    end

    local contentHeight = math.max(420, contentBottom)
    if self.lootSessionRightContent then
      self.lootSessionRightContent:SetSize(math.max(1, rightViewportWidth), math.max(rightViewportHeight, contentHeight))
    end
    if self.lootSessionRightScroll and self.lootSessionRightScroll.UpdateScrollChildRect then
      self.lootSessionRightScroll:UpdateScrollChildRect()
    end
    page.__contentHeight = math.max(420, rightViewportHeight)
  end

  local function SetSessionSection(section)
    editor.lootSessionSection = section
    if editor.Refresh then
      editor:Refresh()
    end
  end

  currentBtn:SetScript("OnClick", function()
    SetSessionSection("CURRENT")
  end)
  historyBtn:SetScript("OnClick", function()
    SetSessionSection("HISTORY")
  end)
  syncMgmtBtn:SetScript("OnClick", function()
    SetSessionSection("SYNCMGMT")
  end)
  roleSimBtn:SetScript("OnClick", function()
    SetSessionSection("ROLESIM")
  end)
  autoPassSettingsBtn:SetScript("OnClick", function()
    SetSessionSection("AUTOPASS")
  end)

  startBtn:SetScript("OnClick", function()
    if IsCombatLocked() then
      if editor.Refresh then
        editor:Refresh()
      end
      return
    end
    local profileName = ResolveRequiredSessionProfileName("Prepare Session")
    if not profileName then
      if editor.Refresh then
        editor:Refresh()
      end
      return
    end
    if not GetLootProfileAccessInfo(profileName).canStartSession then
      return
    end
    local startFlow = ResolveOptionalApiFunction("LIDCOUNCIL_StartLootSessionFlow")
    if startFlow then
      startFlow(profileName)
    else
      StartLootSession(profileName)
    end
    if editor.Refresh then
      editor:Refresh()
    end
  end)

  activateBtn:SetScript("OnClick", function()
    if IsCombatLocked() then
      if editor.Refresh then
        editor:Refresh()
      end
      return
    end
    local activeSession, profileName = GetActiveLootSession()
    if not activeSession or TrimText(profileName) == "" then
      if editor.Refresh then
        editor:Refresh()
      end
      return
    end
    if not GetLootProfileAccessInfo(profileName).canStartSession then
      return
    end
    local activateFlow = ResolveOptionalApiFunction("LIDCOUNCIL_ActivatePreparedLootSessionFlow")
    if type(activateFlow) == "function" then
      activateFlow()
    end
    if editor.Refresh then
      editor:Refresh()
    end
  end)

  stopBtn:SetScript("OnClick", function()
    local profileName = ResolveRequiredSessionProfileName("Stop Session")
    if not profileName then
      if editor.Refresh then
        editor:Refresh()
      end
      return
    end
    if not GetLootProfileAccessInfo(profileName).canManageSession then
      return
    end
    local stopFlow = ResolveOptionalApiFunction("LIDCOUNCIL_StopLootSessionFlow")
    if stopFlow then
      stopFlow()
    else
      StopLootSession()
    end
    if editor.Refresh then
      editor:Refresh()
    end
  end)

  inviteBtn:SetScript("OnClick", function()
    if IsCombatLocked() then
      if editor.Refresh then
        editor:Refresh()
      end
      return
    end
    local profileName = ResolveRequiredSessionProfileName("Send Session Invite")
    if not profileName then
      if editor.Refresh then
        editor:Refresh()
      end
      return
    end
    if not GetLootProfileAccessInfo(profileName).canManageSession then
      return
    end
    local sendInvites = ResolveOptionalApiFunction("LIDCOUNCIL_SendActiveSessionInviteFlow")
    if type(sendInvites) == "function" then
      sendInvites()
    end
    if editor.Refresh then
      editor:Refresh()
    end
  end)

  removeMemberBtn:SetScript("OnClick", function()
    if IsCombatLocked() then
      if editor.Refresh then
        editor:Refresh()
      end
      return
    end
    local profileName = ResolveRequiredSessionProfileName("Remove Member")
    if not profileName then
      if editor.Refresh then
        editor:Refresh()
      end
      return
    end
    if not GetLootProfileAccessInfo(profileName).canManageSession then
      return
    end
    local selectedMember = TrimText(editor.lootSessionSelectedMemberKey)
    if selectedMember == "" then
      return
    end
    local removeMember = ResolveOptionalApiFunction("LIDCOUNCIL_RemoveActiveSessionMemberFlow")
    if type(removeMember) == "function" then
      removeMember(selectedMember)
    end
    editor.lootSessionSelectedMemberKey = nil
    if editor.Refresh then
      editor:Refresh()
    end
  end)

  pushProfileBtn:SetScript("OnClick", function()
    if IsCombatLocked() then
      if editor.Refresh then
        editor:Refresh()
      end
      return
    end
    local profileName = ResolveRequiredSessionProfileName("Push Host Repair")
    if not profileName then
      if editor.Refresh then
        editor:Refresh()
      end
      return
    end
    if not GetLootProfileAccessInfo(profileName).canManageSession then
      return
    end
    local pushProfileUpdate = ResolveOptionalApiFunction("LIDCOUNCIL_PushActiveProfileSnapshotFlow")
    if type(pushProfileUpdate) == "function" then
      local selectedScopeActions = type(editor.lootSessionSelectedScopeActions) == "table" and editor.lootSessionSelectedScopeActions.push or nil
      local targetMember = nil
      local options = nil
      if type(selectedScopeActions) == "table"
        and selectedScopeActions.selectionActive
        and selectedScopeActions.compatibleCount > 0 then
        targetMember = TrimText(selectedScopeActions.targetMemberKey)
        options = {
          domains = selectedScopeActions.domains,
          subdomains = selectedScopeActions.subdomains,
        }
      end
      pushProfileUpdate(targetMember, options)
    end
    if editor.Refresh then
      editor:Refresh()
    end
  end)

  checkSyncBtn:SetScript("OnClick", function()
    if IsCombatLocked() then
      if editor.Refresh then
        editor:Refresh()
      end
      return
    end
    local profileName = ResolveRequiredSessionProfileName("Check Differences")
    if not profileName then
      if editor.Refresh then
        editor:Refresh()
      end
      return
    end
    if not GetLootProfileAccessInfo(profileName).canManageSession then
      return
    end
    local requestSubchecks = ResolveOptionalApiFunction("LIDCOUNCIL_RequestActiveProfileSubchecksumFlow")
    if type(requestSubchecks) == "function" then
      requestSubchecks()
    end
    if editor.Refresh then
      editor:Refresh()
    end
  end)

  recommendedRepairBtn:SetScript("OnClick", function()
    if IsCombatLocked() then
      if editor.Refresh then
        editor:Refresh()
      end
      return
    end
    local profileName = ResolveRequiredSessionProfileName("Run Recommended Repair")
    if not profileName then
      if editor.Refresh then
        editor:Refresh()
      end
      return
    end
    if not GetLootProfileAccessInfo(profileName).canManageSession then
      return
    end

    local selectedMember = TrimText(editor.lootSessionSelectedSyncMember or (profileSyncDropdown and profileSyncDropdown:GetSelectedValue()) or "")
    local selectedCandidate = nil
    for _, candidate in ipairs(editor.lootSessionAllSyncCandidates or {}) do
      if string.lower(TrimText(type(candidate) == "table" and candidate.memberKey or "")) == string.lower(selectedMember) then
        selectedCandidate = candidate
        break
      end
    end
    local recommendation = type(selectedCandidate) == "table" and type(selectedCandidate.safeRecommendation) == "table" and selectedCandidate.safeRecommendation or nil
    if type(recommendation) ~= "table" then
      return
    end

    editor.lootSessionSelectedSyncMember = selectedMember
    editor.lootSessionSyncScopeSelections = type(editor.lootSessionSyncScopeSelections) == "table" and editor.lootSessionSyncScopeSelections or {}
    editor.lootSessionSyncScopeSelections[selectedMember] = editor.lootSessionSyncScopeSelections[selectedMember] or { selected = {} }
    local selectionEntry = editor.lootSessionSyncScopeSelections[selectedMember]
    selectionEntry.selected = {}
    for _, subdomain in ipairs(type(recommendation.subdomains) == "table" and recommendation.subdomains or {}) do
      if TrimText(subdomain) ~= "" then
        selectionEntry.selected[TrimText(subdomain)] = true
      end
    end

    local action = string.lower(TrimText(recommendation.action))
    if action == "push" then
      local pushProfileUpdate = ResolveOptionalApiFunction("LIDCOUNCIL_PushActiveProfileSnapshotFlow")
      if type(pushProfileUpdate) == "function" then
        pushProfileUpdate(selectedMember ~= "" and selectedMember or nil, {
          domains = recommendation.domains,
          subdomains = recommendation.subdomains,
        })
      end
    elseif action == "pull" then
      local requestProfileUpdate = ResolveOptionalApiFunction("LIDCOUNCIL_RequestActiveProfileSnapshotFlow")
      if type(requestProfileUpdate) == "function" then
        requestProfileUpdate(selectedMember, {
          domains = recommendation.domains,
          subdomains = recommendation.subdomains,
        })
      end
    elseif action == "preview" then
      local requestProfileUpdate = ResolveOptionalApiFunction("LIDCOUNCIL_RequestActiveProfileSnapshotFlow")
      if type(requestProfileUpdate) == "function" then
        requestProfileUpdate(selectedMember, {
          mode = "PREVIEW",
          domains = recommendation.domains,
          subdomains = recommendation.subdomains,
        })
      end
    else
      local requestSubchecks = ResolveOptionalApiFunction("LIDCOUNCIL_RequestActiveProfileSubchecksumFlow")
      if type(requestSubchecks) == "function" then
        requestSubchecks(selectedMember ~= "" and selectedMember or nil)
      end
    end
    if editor.Refresh then
      editor:Refresh()
    end
  end)

  requestProfileBtn:SetScript("OnClick", function()
    if IsCombatLocked() then
      if editor.Refresh then
        editor:Refresh()
      end
      return
    end
    local profileName = ResolveRequiredSessionProfileName("Pull Member Repair")
    if not profileName then
      if editor.Refresh then
        editor:Refresh()
      end
      return
    end
    if not GetLootProfileAccessInfo(profileName).canManageSession then
      return
    end
    local requestProfileUpdate = ResolveOptionalApiFunction("LIDCOUNCIL_RequestActiveProfileSnapshotFlow")
    if type(requestProfileUpdate) == "function" then
      local selectedMember = TrimText(editor.lootSessionSelectedSyncMember or (profileSyncDropdown and profileSyncDropdown:GetSelectedValue()) or "")
      local selectedScopeActions = type(editor.lootSessionSelectedScopeActions) == "table" and editor.lootSessionSelectedScopeActions.pull or nil
      local options = nil
      if type(selectedScopeActions) == "table"
        and selectedScopeActions.selectionActive
        and selectedScopeActions.compatibleCount > 0
        and string.lower(TrimText(selectedScopeActions.targetMemberKey)) == string.lower(selectedMember) then
        options = {
          domains = selectedScopeActions.domains,
          subdomains = selectedScopeActions.subdomains,
        }
      end
      requestProfileUpdate(selectedMember, options)
    end
    if editor.Refresh then
      editor:Refresh()
    end
  end)

  previewProfileBtn:SetScript("OnClick", function()
    if IsCombatLocked() then
      if editor.Refresh then
        editor:Refresh()
      end
      return
    end
    local profileName = ResolveRequiredSessionProfileName("Preview Member Repair")
    if not profileName then
      if editor.Refresh then
        editor:Refresh()
      end
      return
    end
    if not GetLootProfileAccessInfo(profileName).canManageSession then
      return
    end
    local requestProfileUpdate = ResolveOptionalApiFunction("LIDCOUNCIL_RequestActiveProfileSnapshotFlow")
    if type(requestProfileUpdate) == "function" then
      local selectedMember = TrimText(editor.lootSessionSelectedSyncMember or (profileSyncDropdown and profileSyncDropdown:GetSelectedValue()) or "")
      local options = { mode = "PREVIEW" }
      local selectedScopeActions = type(editor.lootSessionSelectedScopeActions) == "table" and editor.lootSessionSelectedScopeActions.preview or nil
      if type(selectedScopeActions) == "table"
        and selectedScopeActions.selectionActive
        and selectedScopeActions.compatibleCount > 0
        and string.lower(TrimText(selectedScopeActions.targetMemberKey)) == string.lower(selectedMember) then
        options.domains = selectedScopeActions.domains
        options.subdomains = selectedScopeActions.subdomains
      end
      requestProfileUpdate(selectedMember, options)
    end
    if editor.Refresh then
      editor:Refresh()
    end
  end)

  syncBoardBtn:SetScript("OnClick", function()
    if IsCombatLocked() then
      if editor.Refresh then
        editor:Refresh()
      end
      return
    end
    local profileName = ResolveRequiredSessionProfileName("Send Board Sync")
    if not profileName then
      if editor.Refresh then
        editor:Refresh()
      end
      return
    end
    if not GetLootProfileAccessInfo(profileName).canManageSession then
      return
    end
    local sendBoardSync = ResolveOptionalApiFunction("LIDCOUNCIL_SendActiveLiveBoardSyncFlow")
    if type(sendBoardSync) == "function" then
      sendBoardSync()
    end
    if editor.Refresh then
      editor:Refresh()
    end
  end)

  local function ApplySimulationRoleOverride(roleKey)
    local _, profileName = ResolveSessionContextProfile()
    if TrimText(profileName) ~= "Simulation" then
      return
    end
    local setSimulationRole = ResolveOptionalApiFunction("LIDCOUNCIL_SetSimulationRoleOverride")
    if type(setSimulationRole) == "function" then
      setSimulationRole(profileName, roleKey)
    end
    local refreshBoard = ResolveOptionalApiFunction("LIDCOUNCIL_RefreshLiveLootBoard")
    if type(refreshBoard) == "function" then
      refreshBoard()
    end
    if editor.Refresh then
      editor:Refresh()
    end
  end

  roleSimMasterBtn:SetScript("OnClick", function()
    ApplySimulationRoleOverride("MASTER")
  end)
  roleSimSessionHostBtn:SetScript("OnClick", function()
    ApplySimulationRoleOverride("SESSION_HOST")
  end)
  roleSimCouncilBtn:SetScript("OnClick", function()
    ApplySimulationRoleOverride("COUNCIL")
  end)
  roleSimRaiderBtn:SetScript("OnClick", function()
    ApplySimulationRoleOverride("RAIDER")
  end)

  autoPassLocalBtn:SetScript("OnClick", function()
    local getLocalAutoPassEnabled = ResolveOptionalApiFunction("LIDCOUNCIL_GetLocalAutoPassEnabled")
    local setLocalAutoPassEnabled = ResolveOptionalApiFunction("LIDCOUNCIL_SetLocalAutoPassEnabled")
    local notifyLocalAutoPassChanged = ResolveOptionalApiFunction("LIDCOUNCIL_NotifyLocalAutoPassChanged")
    if type(setLocalAutoPassEnabled) ~= "function" then
      return
    end
    local currentEnabled = true
    if type(getLocalAutoPassEnabled) == "function" then
      currentEnabled = getLocalAutoPassEnabled() and true or false
    end
    local nextEnabled = not currentEnabled
    setLocalAutoPassEnabled(nextEnabled)
    if type(notifyLocalAutoPassChanged) == "function" then
      notifyLocalAutoPassChanged(nextEnabled)
    elseif editor.Refresh then
      editor:Refresh()
    end
  end)

  editor.RefreshLootSessionPage = RefreshLootSessionPage_Impl

  if not editor.lootSessionCombatEventFrame then
    local combatEventFrame = CreateFrame("Frame")
    combatEventFrame:RegisterEvent("PLAYER_REGEN_DISABLED")
    combatEventFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
    combatEventFrame:SetScript("OnEvent", function()
      if editor.Refresh then
        editor:Refresh()
      end
    end)
    editor.lootSessionCombatEventFrame = combatEventFrame
  end

  if page and page.HookScript then
    page:HookScript("OnSizeChanged", function()
      LayoutLootSessionPage(editor)
    end)
  end
  editor.LayoutLootSessionPage = LayoutLootSessionPage
end

INTERNAL_API.LIDCOUNCIL_BuildLootSessionPage_Impl = BuildLootSessionPage

