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 TransferPage = {}
local DEFAULT_SCOPE = "full_profile"
local RefreshImportReview
local RefreshRecoveryControls

local function Trim(value)
  local text = tostring(value or "")
  text = text:gsub("^%s+", "")
  text = text:gsub("%s+$", "")
  return text
end

local function SetButtonEnabled(button, enabled)
  if not button then
    return
  end
  if button.SetEnabled then
    button:SetEnabled(enabled == true)
  elseif enabled and button.Enable then
    button:Enable()
  elseif not enabled and button.Disable then
    button:Disable()
  end
end

local function FormatBytes(value)
  local bytes = math.max(0, tonumber(value) or 0)
  if bytes >= 1048576 then
    return string.format("%.2f MB", bytes / 1048576)
  end
  if bytes >= 1024 then
    return string.format("%.1f KB", bytes / 1024)
  end
  return tostring(math.floor(bytes)) .. " B"
end

local function FormatTimestamp(value)
  local timestamp = math.max(0, tonumber(value) or 0)
  if timestamp > 0 and type(date) == "function" then
    local ok, formatted = pcall(date, "%Y-%m-%d %H:%M:%S", timestamp)
    if ok and type(formatted) == "string" and formatted ~= "" then
      return formatted
    end
  end
  return "Time unavailable"
end

local function JoinReportLines(values, fallback, limit)
  local lines = {}
  for _, value in ipairs(type(values) == "table" and values or {}) do
    local text = Trim(value)
    if text ~= "" then
      lines[#lines + 1] = text
      if #lines >= (tonumber(limit) or 3) then
        break
      end
    end
  end
  return #lines > 0 and table.concat(lines, " | ") or tostring(fallback or "None")
end

local function GetScopeRegistry()
  local getter = type(API) == "table" and API.LIDCOUNCIL_GetProfileTransferScopeRegistry or nil
  local registry = type(getter) == "function" and getter() or {}
  return type(registry) == "table" and registry or {}
end

local function FindScope(scopeKey)
  local wanted = Trim(scopeKey)
  for _, definition in ipairs(GetScopeRegistry()) do
    if Trim(definition and definition.key) == wanted then
      return definition
    end
  end
  return nil
end

local function GetSelectedScopeKeys(editor)
  if not editor then return {} end
  if type(editor.__lootProfileTransferScopes) ~= "table" then
    local legacyKey = Trim(editor.__lootProfileTransferScopeKey)
    editor.__lootProfileTransferScopes = {
      [legacyKey ~= "" and legacyKey or DEFAULT_SCOPE] = true,
    }
  end
  local selected = editor.__lootProfileTransferScopes
  if selected.full_profile then
    editor.__lootProfileTransferScopes = { full_profile = true }
    selected = editor.__lootProfileTransferScopes
  end
  local scopes = {}
  for _, definition in ipairs(GetScopeRegistry()) do
    local key = Trim(definition and definition.key)
    if key ~= "" and selected[key] == true then
      scopes[#scopes + 1] = key
    end
  end
  return scopes
end

local function SetSelectedScopes(editor, scopes)
  if not editor then return end
  local selected = {}
  for _, scopeKey in ipairs(type(scopes) == "table" and scopes or {}) do
    local key = Trim(scopeKey)
    if FindScope(key) then selected[key] = true end
  end
  if selected.full_profile then selected = { full_profile = true } end
  editor.__lootProfileTransferScopes = selected
  local ordered = GetSelectedScopeKeys(editor)
  editor.__lootProfileTransferScopeKey = ordered[1] or ""
end

local function ScopeSignature(scopes)
  return table.concat(type(scopes) == "table" and scopes or {}, ",")
end

local function ResolveProfileName(editor)
  local profileName = Trim(editor and editor.selectedLootProfileName)
  if profileName == "" then
    profileName = Trim(editor and editor.selectedProfileName)
  end
  if profileName == "" and type(API.LIDCOUNCIL_GetEnabledLootProfileName) == "function" then
    profileName = Trim(API.LIDCOUNCIL_GetEnabledLootProfileName())
  end
  return profileName
end

local function SetStatus(editor, text, isError)
  local status = editor and editor.lootProfileTransferStatus
  if not status then
    return
  end
  status:SetText(tostring(text or ""))
  if isError then
    status:SetTextColor(1.00, 0.34, 0.28, 1.00)
  else
    status:SetTextColor(0.42, 0.90, 1.00, 1.00)
  end
end

local function RefreshPackageSummary(editor)
  local result = editor and editor.__lootProfileTransferExport or nil
  local summary = editor and editor.lootProfileTransferSummary or nil
  local partText = editor and editor.lootProfileTransferPartText or nil
  local hasResult = type(result) == "table" and type(result.parts) == "table" and #result.parts > 0
  if summary then
    if hasResult then
      local manifest = type(result.manifest) == "table" and result.manifest or {}
      local dependencies = type(manifest.dependencies) == "table" and table.concat(manifest.dependencies, ", ") or ""
      local dependencyText = dependencies ~= "" and (" | Companion scope: " .. dependencies) or ""
      summary:SetText(string.format(
        "%s\nProfile ID: %s\n%d part(s) | %s encoded | checksum %s%s",
        tostring(result.scopeLabel or "Shared Profile Package"),
        tostring(manifest.profileId or "Unavailable"),
        #result.parts,
        FormatBytes(manifest.encodedLength),
        tostring(manifest.payloadChecksum or "Unavailable"),
        dependencyText
      ))
    else
      summary:SetText("No package created yet. Select one or more content sections, then create a portable package.")
    end
  end
  if partText then
    if hasResult then
      result.currentPart = math.max(1, math.min(#result.parts, tonumber(result.currentPart) or 1))
      partText:SetText(string.format("Package part %d of %d", result.currentPart, #result.parts))
    else
      partText:SetText("No package parts available")
    end
  end
  SetButtonEnabled(editor and editor.lootProfileTransferPreviousBtn, hasResult and result.currentPart > 1)
  SetButtonEnabled(editor and editor.lootProfileTransferCopyPartBtn, hasResult)
  SetButtonEnabled(editor and editor.lootProfileTransferNextBtn, hasResult and result.currentPart < #result.parts)
end

local function RefreshScope(editor)
  if not editor then
    return
  end
  local scopes = GetSelectedScopeKeys(editor)
  local scopeSignature = ScopeSignature(scopes)
  local labels = {}
  local descriptions = {}
  local selectedSet = {}
  for _, scopeKey in ipairs(scopes) do
    local definition = FindScope(scopeKey)
    selectedSet[scopeKey] = true
    labels[#labels + 1] = tostring(definition and definition.label or scopeKey)
    descriptions[#descriptions + 1] = tostring(definition and definition.description or "")
  end
  local dropdownText
  if #scopes == 0 then
    dropdownText = "Select Package Content"
  elseif #scopes == 1 then
    dropdownText = labels[1]
  else
    dropdownText = string.format("Custom Bundle: %d sections", #scopes)
  end
  if editor.lootProfileTransferScopeDropdown then
    if editor.lootProfileTransferScopeDropdown.SetSelectedValue then
      editor.lootProfileTransferScopeDropdown:SetSelectedValue(scopeSignature)
    end
    if editor.lootProfileTransferScopeDropdown.SetText then
      editor.lootProfileTransferScopeDropdown:SetText(dropdownText)
    end
  end
  if editor.lootProfileTransferScopeDescription then
    local description
    if #scopes == 0 then
      description = "Select one or more profile sections to export. Complete Shared Profile is exclusive."
    elseif #scopes == 1 then
      description = descriptions[1]
    else
      description = string.format(
        "Custom bundle with %d sections. Selected sections are packaged and applied atomically.",
        #scopes
      )
    end
    if selectedSet.fun_awards and not selectedSet.loot_list then
      description = description .. " Loot List is recommended with Fun Award Events so derived results rebuild from matching character data."
    end
    editor.lootProfileTransferScopeDescription:SetText(description)
  end
  local profileName = ResolveProfileName(editor)
  if type(editor.__lootProfileTransferExport) == "table"
    and (Trim(editor.__lootProfileTransferExport.profileName) ~= profileName
      or Trim(editor.__lootProfileTransferExport.scopeSignature) ~= scopeSignature) then
    editor.__lootProfileTransferExport = nil
    SetStatus(editor, "", false)
  end
  if editor.lootProfileTransferProfileText then
    editor.lootProfileTransferProfileText:SetText(profileName ~= "" and ("Selected profile: " .. profileName) or "No profile selected")
  end
  SetButtonEnabled(editor.lootProfileTransferExportBtn, profileName ~= "" and #scopes > 0)
  RefreshPackageSummary(editor)
end

local function BuildScopeMenu(editor)
  local selected = {}
  for _, scopeKey in ipairs(GetSelectedScopeKeys(editor)) do selected[scopeKey] = true end
  local entries = {
    { text = "Package Preset", isTitle = true, notCheckable = true },
  }
  for _, definitionValue in ipairs(GetScopeRegistry()) do
    local definition = definitionValue
    local key = Trim(definition.key)
    if key == "full_profile" then
      entries[#entries + 1] = {
        text = tostring(definition.label or "Complete Shared Profile"),
        value = key,
        checked = selected.full_profile == true,
        keepShownOnClick = true,
        func = function()
          SetSelectedScopes(editor, { "full_profile" })
          editor.__lootProfileTransferExport = nil
          SetStatus(editor, "", false)
          RefreshScope(editor)
        end,
      }
      entries[#entries + 1] = { text = "Custom Bundle", isTitle = true, notCheckable = true }
      entries[#entries + 1] = {
        text = "Select All Separate Sections",
        notCheckable = true,
        keepShownOnClick = true,
        func = function()
          local allScopes = {}
          for _, available in ipairs(GetScopeRegistry()) do
            if Trim(available and available.key) ~= "full_profile" then
              allScopes[#allScopes + 1] = available.key
            end
          end
          SetSelectedScopes(editor, allScopes)
          editor.__lootProfileTransferExport = nil
          SetStatus(editor, "", false)
          RefreshScope(editor)
        end,
      }
    else
      entries[#entries + 1] = {
        text = tostring(definition.label or definition.key or "Profile Content"),
        value = key,
        checked = selected[key] == true,
        keepShownOnClick = true,
        func = function()
          local nextSelected = {}
          for _, selectedKey in ipairs(GetSelectedScopeKeys(editor)) do
            if selectedKey ~= "full_profile" then nextSelected[#nextSelected + 1] = selectedKey end
          end
          local foundIndex
          for index, selectedKey in ipairs(nextSelected) do
            if selectedKey == key then foundIndex = index break end
          end
          if foundIndex then
            table.remove(nextSelected, foundIndex)
          else
            nextSelected[#nextSelected + 1] = key
          end
          SetSelectedScopes(editor, nextSelected)
          editor.__lootProfileTransferExport = nil
          SetStatus(editor, "", false)
          RefreshScope(editor)
        end,
      }
    end
  end
  entries[#entries + 1] = {
    text = "Clear Selection",
    notCheckable = true,
    keepShownOnClick = true,
    func = function()
      SetSelectedScopes(editor, {})
      editor.__lootProfileTransferExport = nil
      SetStatus(editor, "", false)
      RefreshScope(editor)
    end,
  }
  return { width = 330, entries = entries }
end

local function ExportSelectedScope(editor)
  local exporter = type(API) == "table" and API.LIDCOUNCIL_ExportSharedProfilePackage or nil
  if type(exporter) ~= "function" then
    SetStatus(editor, "Profile package export API is unavailable.", true)
    return
  end
  local profileName = ResolveProfileName(editor)
  if profileName == "" then
    SetStatus(editor, "Select a profile before creating a package.", true)
    return
  end
  local scopes = GetSelectedScopeKeys(editor)
  if #scopes == 0 then
    SetStatus(editor, "Select at least one profile section for this package.", true)
    return
  end
  local ok, parts, manifest = exporter(profileName, scopes)
  if not ok then
    SetStatus(editor, tostring(parts or "Could not create the profile package."), true)
    return
  end
  local singleDefinition = #scopes == 1 and FindScope(scopes[1]) or nil
  editor.__lootProfileTransferExport = {
    profileName = profileName,
    scopes = scopes,
    scopeSignature = ScopeSignature(scopes),
    scopeLabel = #scopes == 1
      and tostring(singleDefinition and singleDefinition.label or scopes[1])
      or string.format("Profile Bundle (%d sections)", #scopes),
    parts = type(parts) == "table" and parts or {},
    manifest = type(manifest) == "table" and manifest or {},
    currentPart = 1,
  }
  SetStatus(editor, string.format("Package created successfully: %d section(s), %d part(s).", #scopes, #editor.__lootProfileTransferExport.parts), false)
  RefreshPackageSummary(editor)
end

local function CopyCurrentPart(editor)
  local result = editor and editor.__lootProfileTransferExport or nil
  if type(result) ~= "table" or type(result.parts) ~= "table" or #result.parts == 0 then
    SetStatus(editor, "Create a package before copying a part.", true)
    return
  end
  result.currentPart = math.max(1, math.min(#result.parts, tonumber(result.currentPart) or 1))
  local showCopyWindow = type(API) == "table" and API.LIDCOUNCIL_ShowCopyTextWindow or nil
  if type(showCopyWindow) ~= "function" then
    SetStatus(editor, "Copy window API is unavailable.", true)
    return
  end
  showCopyWindow(
    string.format("%s - Part %d of %d", tostring(result.scopeLabel or "Profile Package"), result.currentPart, #result.parts),
    result.parts[result.currentPart]
  )
end

local function SetImportStatus(editor, text, isError)
  local status = editor and editor.lootProfileTransferImportStatus
  if not status then
    return
  end
  status:SetText(tostring(text or ""))
  if isError then
    status:SetTextColor(1.00, 0.34, 0.28, 1.00)
  else
    status:SetTextColor(0.42, 0.90, 1.00, 1.00)
  end
end

local function FormatScopeLabels(scopes)
  local labels = {}
  for _, scopeKey in ipairs(type(scopes) == "table" and scopes or {}) do
    local definition = FindScope(scopeKey)
    labels[#labels + 1] = tostring(definition and definition.label or scopeKey)
  end
  return #labels > 0 and table.concat(labels, ", ") or "Unknown content"
end

local function GetCollectedParts(collection)
  if type(collection) ~= "table" or type(collection.parts) ~= "table"
    or collection.complete ~= true then
    return nil
  end
  local ordered = {}
  for index = 1, math.max(0, tonumber(collection.partCount) or 0) do
    if type(collection.parts[index]) ~= "string" then
      return nil
    end
    ordered[index] = collection.parts[index]
  end
  return ordered
end

local function ResolveExistingProfileName(profileId)
  local finder = type(API) == "table" and API.LIDCOUNCIL_FindLootProfileNameById or nil
  if type(finder) ~= "function" or Trim(profileId) == "" then
    return ""
  end
  local ok, profileName = pcall(finder, profileId)
  return ok and Trim(profileName) or ""
end

local function ResolveImportTarget(collection)
  if type(collection) ~= "table" then
    return "", false
  end
  local packageId = Trim(collection.packageId)
  if Trim(collection.__targetPackageId) ~= packageId then
    local existingName = ResolveExistingProfileName(collection.profileId)
    collection.targetName = existingName ~= "" and existingName or Trim(collection.profileName)
    collection.targetLocked = existingName ~= ""
    collection.__targetPackageId = packageId
    collection.inspection = nil
    collection.inspectedTargetName = nil
  end
  if Trim(collection.targetName) == "" then
    collection.targetName = Trim(collection.profileName)
  end
  return Trim(collection.targetName), collection.targetLocked == true
end

local function ResolveRecoveryTarget(editor)
  local collection = editor and editor.__lootProfileTransferImport or nil
  local targetName = type(collection) == "table" and ResolveImportTarget(collection) or ""
  if targetName == "" then
    targetName = ResolveProfileName(editor)
  end
  return targetName
end

local function RefreshImportSummary(editor)
  local collection = editor and editor.__lootProfileTransferImport or nil
  local summary = editor and editor.lootProfileTransferImportSummary or nil
  local hasCollection = type(collection) == "table" and type(collection.parts) == "table"
  if not hasCollection then
    if summary then
      summary:SetText("No package parts received. Paste one exported part at a time; out-of-order parts are accepted.")
    end
    SetButtonEnabled(editor and editor.lootProfileTransferClearPartsBtn, false)
    if type(RefreshImportReview) == "function" then RefreshImportReview(editor) end
    if type(RefreshRecoveryControls) == "function" then RefreshRecoveryControls(editor) end
    return
  end
  local missing = {}
  for index = 1, math.max(0, tonumber(collection.partCount) or 0) do
    if not collection.parts[index] then
      missing[#missing + 1] = tostring(index)
    end
  end
  local missingText = #missing > 0 and table.concat(missing, ", ") or "None"
  if #missingText > 90 then
    missingText = missingText:sub(1, 87) .. "..."
  end
  local inspection = type(collection.inspection) == "table" and collection.inspection or nil
  local inspectionText = "Waiting for remaining parts."
  if collection.complete and inspection then
    if inspection.valid then
      local blockers = type(inspection.blockers) == "table" and inspection.blockers or {}
      local warnings = type(inspection.warnings) == "table" and inspection.warnings or {}
      inspectionText = string.format(
        "Complete and checksummed | %d warning(s) | %d apply blocker(s)",
        #warnings,
        #blockers
      )
    else
      local errors = type(inspection.errors) == "table" and inspection.errors or {}
      inspectionText = "Inspection failed: " .. tostring(errors[1] or "Package is invalid.")
    end
  elseif collection.complete then
    inspectionText = "Complete; final inspection is pending."
  end
  if summary then
    summary:SetText(string.format(
      "Profile: %s | Package: %s\nContent: %s\nReceived: %d/%d part(s) | %s | Missing: %s\nStatus: %s",
      tostring(collection.profileName or "Unknown"),
      tostring(collection.packageId or "Unknown"),
      FormatScopeLabels(collection.scopes),
      math.max(0, tonumber(collection.receivedCount) or 0),
      math.max(0, tonumber(collection.partCount) or 0),
      FormatBytes(collection.encodedLength),
      missingText,
      inspectionText
    ))
  end
  SetButtonEnabled(editor and editor.lootProfileTransferClearPartsBtn, true)
  if type(RefreshImportReview) == "function" then RefreshImportReview(editor) end
  if type(RefreshRecoveryControls) == "function" then RefreshRecoveryControls(editor) end
end

local function InspectCollectedPackage(editor)
  local collection = editor and editor.__lootProfileTransferImport or nil
  local parts = GetCollectedParts(collection)
  if not parts then
    return
  end
  local inspector = type(API) == "table" and API.LIDCOUNCIL_InspectSharedProfilePackage or nil
  if type(inspector) ~= "function" then
    SetImportStatus(editor, "Complete package received, but the inspection API is unavailable.", true)
    return
  end
  local targetName = ResolveImportTarget(collection)
  local report = inspector(parts, targetName, { allowCreate = true })
  collection.inspection = type(report) == "table" and report or {
    valid = false,
    errors = { "Package inspection returned no report." },
  }
  collection.inspectedTargetName = targetName
  if collection.inspection.valid then
    SetImportStatus(editor, "Complete package received and checksum verified. No profile data was changed.", false)
  else
    local errors = type(collection.inspection.errors) == "table" and collection.inspection.errors or {}
    SetImportStatus(editor, tostring(errors[1] or "Package inspection failed."), true)
  end
  if type(RefreshImportReview) == "function" then RefreshImportReview(editor) end
  if type(RefreshRecoveryControls) == "function" then RefreshRecoveryControls(editor) end
  return collection.inspection
end

local function CollectPastedPart(editor, rawText)
  local collector = type(API) == "table" and API.LIDCOUNCIL_CollectSharedProfilePackagePart or nil
  if type(collector) ~= "function" then
    SetImportStatus(editor, "Profile package collector API is unavailable.", true)
    return
  end
  local accepted, collection, detail = collector(editor.__lootProfileTransferImport, rawText)
  if not accepted then
    SetImportStatus(editor, tostring(collection or "Package part was rejected."), true)
    return
  end
  editor.__lootProfileTransferImport = collection
  detail = type(detail) == "table" and detail or {}
  if detail.duplicate then
    SetImportStatus(editor, "This package part was already received; no duplicate was stored.", false)
  else
    SetImportStatus(editor, string.format("Received package part %d of %d.", detail.partIndex or 0, detail.partCount or 0), false)
  end
  if collection.complete then
    InspectCollectedPackage(editor)
  end
  RefreshImportSummary(editor)
end

local function OpenPackagePartPaste(editor)
  local showImportWindow = type(API) == "table" and API.LIDCOUNCIL_ShowImportWindow or nil
  if type(showImportWindow) ~= "function" then
    SetImportStatus(editor, "Paste window API is unavailable.", true)
    return
  end
  showImportWindow(function(_, rawText)
    CollectPastedPart(editor, rawText)
  end, {
    title = "Receive Profile Package Part",
    buttonText = "Add Part",
    placeholder = "Paste one LIDPKG1 package part here",
    requireName = false,
    previewLimit = 1200,
  })
end

RefreshImportReview = function(editor)
  local collection = editor and editor.__lootProfileTransferImport or nil
  local targetEdit = editor and editor.lootProfileTransferTargetEdit or nil
  local targetHint = editor and editor.lootProfileTransferTargetHint or nil
  local reviewText = editor and editor.lootProfileTransferReviewText or nil
  local applyButton = editor and editor.lootProfileTransferApplyBtn or nil
  local refreshButton = editor and editor.lootProfileTransferRefreshReviewBtn or nil
  if type(collection) ~= "table" then
    if targetEdit then
      editor.__lootProfileTransferTargetUpdating = true
      targetEdit:SetText("")
      editor.__lootProfileTransferTargetUpdating = false
      if targetEdit.Disable then targetEdit:Disable() end
    end
    if targetHint then targetHint:SetText("Receive a complete package before choosing its target.") end
    if reviewText then
      reviewText:SetText("No complete package is available for review.")
      reviewText:SetTextColor(0.72, 0.76, 0.84, 1.00)
    end
    SetButtonEnabled(refreshButton, false)
    SetButtonEnabled(applyButton, false)
    return
  end

  local targetName, targetLocked = ResolveImportTarget(collection)
  if targetEdit then
    if not targetEdit.HasFocus or not targetEdit:HasFocus() then
      editor.__lootProfileTransferTargetUpdating = true
      targetEdit:SetText(targetName)
      editor.__lootProfileTransferTargetUpdating = false
    end
    if targetLocked then
      if targetEdit.Disable then targetEdit:Disable() end
      targetEdit:SetTextColor(0.68, 0.76, 0.86, 1.00)
    else
      if targetEdit.Enable then targetEdit:Enable() end
      targetEdit:SetTextColor(0.92, 0.96, 1.00, 1.00)
    end
  end
  if targetHint then
    targetHint:SetText(targetLocked
      and "Locked to the existing local profile with this shared profile identity."
      or "No matching shared profile exists locally. Choose the name for the imported profile.")
  end

  local inspection = type(collection.inspection) == "table" and collection.inspection or nil
  local inspectedTarget = Trim(collection.inspectedTargetName)
  local currentReview = inspection and inspectedTarget == targetName
  if not collection.complete then
    if reviewText then
      reviewText:SetText("Receive every package part before running the dry-run review.")
      reviewText:SetTextColor(0.72, 0.76, 0.84, 1.00)
    end
    SetButtonEnabled(refreshButton, false)
    SetButtonEnabled(applyButton, false)
    return
  end
  SetButtonEnabled(refreshButton, true)
  if not currentReview then
    if reviewText then
      reviewText:SetText("Target changed. Refresh the dry-run review before applying this package.")
      reviewText:SetTextColor(1.00, 0.76, 0.30, 1.00)
    end
    SetButtonEnabled(applyButton, false)
    return
  end

  local targetState = inspection.targetExists and "Existing profile will be updated"
    or (inspection.willCreateTarget and "A new inactive profile will be created" or "Target unavailable")
  local effects = JoinReportLines(inspection.effects, "No replacement effects reported.", 7)
  local warnings = JoinReportLines(inspection.warnings, "None", 2)
  local blockers = JoinReportLines(inspection.blockers, "None", 2)
  local validity = inspection.valid and (inspection.canApply and "READY TO APPLY" or "BLOCKED") or "INVALID"
  if reviewText then
    reviewText:SetText(string.format(
      "%s | Target: %s | %s\nEffects: %s\nWarnings: %s\nBlockers: %s",
      validity,
      targetName ~= "" and targetName or "Not selected",
      targetState,
      effects,
      warnings,
      blockers
    ))
    if inspection.canApply then
      reviewText:SetTextColor(0.52, 0.92, 0.62, 1.00)
    elseif inspection.valid then
      reviewText:SetTextColor(1.00, 0.76, 0.30, 1.00)
    else
      reviewText:SetTextColor(1.00, 0.34, 0.28, 1.00)
    end
  end
  SetButtonEnabled(applyButton, inspection.valid == true and inspection.canApply == true and targetName ~= "")
end

RefreshRecoveryControls = function(editor)
  local dropdown = editor and editor.lootProfileTransferRecoveryDropdown or nil
  local summary = editor and editor.lootProfileTransferRecoverySummary or nil
  local restoreButton = editor and editor.lootProfileTransferRestoreBtn or nil
  if not editor then return end
  local targetName = ResolveRecoveryTarget(editor)
  if Trim(editor.__lootProfileTransferRecoveryTarget) ~= targetName then
    editor.__lootProfileTransferRecoveryTarget = targetName
    editor.__lootProfileTransferRecoveryId = nil
  end
  local getter = type(API) == "table" and API.LIDCOUNCIL_GetProfileTransferRecoveryBackups or nil
  local backups = targetName ~= "" and type(getter) == "function" and getter(targetName) or {}
  backups = type(backups) == "table" and backups or {}
  editor.__lootProfileTransferRecoveryBackups = backups

  local selectedId = Trim(editor.__lootProfileTransferRecoveryId)
  local selectedBackup
  for _, backup in ipairs(backups) do
    if Trim(backup and backup.id) == selectedId then
      selectedBackup = backup
      break
    end
  end
  if not selectedBackup then
    selectedId = ""
    editor.__lootProfileTransferRecoveryId = nil
  end

  if dropdown and dropdown.SetMenuBuilder then
    dropdown:SetMenuBuilder(function()
      local entries = {}
      for _, backupValue in ipairs(backups) do
        local backup = backupValue
        local backupId = Trim(backup and backup.id)
        local label = FormatTimestamp(backup and backup.createdAt) .. " | " .. FormatScopeLabels(backup and backup.scopes)
        entries[#entries + 1] = {
          text = label,
          value = backupId,
          checked = backupId ~= "" and backupId == Trim(editor.__lootProfileTransferRecoveryId),
          func = function()
            editor.__lootProfileTransferRecoveryId = backupId
            if dropdown.SetSelectedValue then dropdown:SetSelectedValue(backupId) end
            if dropdown.SetText then dropdown:SetText(label) end
            RefreshRecoveryControls(editor)
          end,
        }
      end
      if #entries == 0 then
        entries[1] = { text = "No transfer recovery snapshots", disabled = true, notCheckable = true }
      end
      return { width = 390, entries = entries }
    end)
    if selectedBackup then
      local label = FormatTimestamp(selectedBackup.createdAt) .. " | " .. FormatScopeLabels(selectedBackup.scopes)
      if dropdown.SetSelectedValue then dropdown:SetSelectedValue(selectedId) end
      if dropdown.SetText then dropdown:SetText(label) end
    else
      if dropdown.SetSelectedValue then dropdown:SetSelectedValue(nil) end
      if dropdown.SetText then dropdown:SetText(#backups > 0 and "Select Recovery Snapshot" or "No Recovery Snapshots") end
    end
  end
  if summary then
    if targetName == "" then
      summary:SetText("Select a profile or receive a package to view local transfer recovery snapshots.")
    elseif selectedBackup then
      summary:SetText(string.format(
        "Target: %s | Created: %s | Package: %s | Restores: %s",
        targetName,
        FormatTimestamp(selectedBackup.createdAt),
        tostring(selectedBackup.packageId or "Unknown"),
        FormatScopeLabels(selectedBackup.scopes)
      ))
    elseif #backups > 0 then
      summary:SetText(string.format("%d local recovery snapshot(s) available for %s.", #backups, targetName))
    else
      summary:SetText("No transfer recovery snapshot exists for " .. targetName .. ". One is created before an existing profile is replaced.")
    end
  end
  SetButtonEnabled(restoreButton, selectedBackup ~= nil and targetName ~= "")
end

local function ConfirmTransferAction(dialogKey, dialogText, buttonText, firstText, secondText, execute)
  if type(StaticPopupDialogs) ~= "table" or type(StaticPopup_Show) ~= "function" then
    return false
  end
  if not StaticPopupDialogs[dialogKey] then
    StaticPopupDialogs[dialogKey] = {
      text = dialogText,
      button1 = buttonText,
      button2 = CANCEL,
      timeout = 0,
      whileDead = 1,
      hideOnEscape = 1,
      preferredIndex = 3,
      OnAccept = function(dialog)
        local action = dialog and dialog.data
        if type(action) == "table" and type(action.execute) == "function" then
          action.execute()
        end
      end,
    }
  end
  StaticPopup_Show(dialogKey, tostring(firstText or ""), tostring(secondText or ""), { execute = execute })
  return true
end

local function ApplyCollectedPackage(editor)
  local collection = editor and editor.__lootProfileTransferImport or nil
  local parts = GetCollectedParts(collection)
  if not parts then
    SetImportStatus(editor, "Receive every package part before applying it.", true)
    return
  end
  local report = InspectCollectedPackage(editor)
  local targetName = type(collection) == "table" and ResolveImportTarget(collection) or ""
  if type(report) ~= "table" or report.canApply ~= true or targetName == "" then
    SetImportStatus(editor, "The fresh dry-run review is blocked. Resolve its blockers before applying.", true)
    return
  end
  local effects = JoinReportLines(report.effects, "selected profile data", 7)
  local function ExecuteApply()
    local applier = type(API) == "table" and API.LIDCOUNCIL_ApplySharedProfilePackage or nil
    if type(applier) ~= "function" then
      SetImportStatus(editor, "Profile package apply API is unavailable.", true)
      return
    end
    local ok, resultOrError, failedReport = applier(parts, targetName, { allowCreate = true })
    if not ok then
      collection.inspection = type(failedReport) == "table" and failedReport or collection.inspection
      SetImportStatus(editor, tostring(resultOrError or "Profile package could not be applied."), true)
      RefreshImportReview(editor)
      return
    end
    local appliedReport = type(resultOrError) == "table" and resultOrError or report
    collection.inspection = appliedReport
    collection.inspectedTargetName = targetName
    collection.applied = true
    editor.selectedLootProfileName = targetName
    editor.selectedProfileName = targetName
    editor.__lootProfileTransferRecoveryId = appliedReport.recoveryBackupId ~= "" and appliedReport.recoveryBackupId or nil
    SetImportStatus(editor, appliedReport.createdTarget
      and ("Created inactive profile " .. targetName .. " from the package.")
      or ("Applied the package to " .. targetName .. ". A local recovery snapshot was saved."), false)
    RefreshImportReview(editor)
    RefreshRecoveryControls(editor)
    if type(editor.RequestLootProfilePageRefresh) == "function" then
      editor:RequestLootProfilePageRefresh()
    end
  end
  if not ConfirmTransferAction(
    "LIDCOUNCIL_APPLY_SHARED_PROFILE_PACKAGE_CONFIRM",
    "Apply this profile package to %s?\n\nThe package will replace: %s\n\nExisting profile data is backed up locally first. A new profile remains inactive.",
    "Apply Package",
    targetName,
    effects,
    ExecuteApply
  ) then
    SetImportStatus(editor, "Package confirmation is unavailable. Reload the UI and try again.", true)
  end
end

local function RestoreSelectedRecovery(editor)
  local targetName = ResolveRecoveryTarget(editor)
  local backupId = Trim(editor and editor.__lootProfileTransferRecoveryId)
  if targetName == "" or backupId == "" then
    SetImportStatus(editor, "Select a transfer recovery snapshot first.", true)
    return
  end
  local function ExecuteRestore()
    local restore = type(API) == "table" and API.LIDCOUNCIL_RestoreProfileTransferRecoveryBackup or nil
    if type(restore) ~= "function" then
      SetImportStatus(editor, "Transfer recovery API is unavailable.", true)
      return
    end
    local ok, result = restore(targetName, backupId)
    if not ok then
      SetImportStatus(editor, tostring(result or "Recovery snapshot could not be restored."), true)
      return
    end
    SetImportStatus(editor, "Restored the local pre-import snapshot for " .. targetName .. ".", false)
    local collection = editor.__lootProfileTransferImport
    if type(collection) == "table" and collection.complete then
      InspectCollectedPackage(editor)
    end
    RefreshRecoveryControls(editor)
    if type(editor.RequestLootProfilePageRefresh) == "function" then
      editor:RequestLootProfilePageRefresh()
    end
  end
  if not ConfirmTransferAction(
    "LIDCOUNCIL_RESTORE_TRANSFER_RECOVERY_CONFIRM",
    "Restore the pre-import snapshot for %s?\n\nThis replaces the current profile state with recovery snapshot %s.",
    "Restore Snapshot",
    targetName,
    backupId,
    ExecuteRestore
  ) then
    SetImportStatus(editor, "Recovery confirmation is unavailable. Reload the UI and try again.", true)
  end
end

function TransferPage.Build(editor, parent, helpers)
  if not editor or not parent or editor.lootProfileTransferFrame then
    return
  end
  helpers = type(helpers) == "table" and helpers or {}
  editor.__lootProfileTransferScopeKey = Trim(editor.__lootProfileTransferScopeKey) ~= "" and editor.__lootProfileTransferScopeKey or DEFAULT_SCOPE

  local tabParent = editor.lootProfileTabStrip or parent
  editor.lootProfileTransferToggleBtn = helpers.CreateProfileTabButton(tabParent, "Transfer")
  editor.lootProfileTransferToggleBtn:SetScript("OnClick", function()
    editor.__lootProfileOpenSection = "transfer"
    if type(editor.RequestLootProfilePageRefresh) == "function" then
      editor:RequestLootProfilePageRefresh()
    elseif type(editor.LayoutLootProfilePage) == "function" then
      editor:LayoutLootProfilePage()
    end
    if editor.lootProfilesRightScroll and editor.lootProfilesRightScroll.SetVerticalScroll then
      editor.lootProfilesRightScroll:SetVerticalScroll(0)
    end
  end)

  local frame = CreateFrame("Frame", nil, parent, "BackdropTemplate")
  helpers.ApplyFrameSkin(frame)
  frame:EnableMouse(false)
  frame:SetFrameLevel(math.max((parent:GetFrameLevel() or 1) - 1, 0))
  editor.lootProfileTransferFrame = frame

  local header = helpers.MakeYellowSubHeader(parent, "Profile Transfer", 18, -494)
  editor.lootProfileTransferHeader = header

  local intro = parent:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  intro:SetJustifyH("LEFT")
  intro:SetText("Create portable, checksummed packages that preserve this shared profile's identity. Receivers can inspect each package before applying it.")
  editor.lootProfileTransferIntro = intro

  local profileText = parent:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  profileText:SetJustifyH("LEFT")
  editor.lootProfileTransferProfileText = profileText

  local scopeLabel = parent:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  scopeLabel:SetJustifyH("LEFT")
  scopeLabel:SetText("Package Content")
  editor.lootProfileTransferScopeLabel = scopeLabel

  local scopeDropdown = helpers.CreateDropdownControl(editor, parent, 330, "Complete Shared Profile")
  helpers.ApplyProfileUtilityDropdownStyle(scopeDropdown)
  scopeDropdown:SetMenuBuilder(function()
    return BuildScopeMenu(editor)
  end)
  editor.lootProfileTransferScopeDropdown = scopeDropdown

  local scopeDescription = parent:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  scopeDescription:SetJustifyH("LEFT")
  editor.lootProfileTransferScopeDescription = scopeDescription

  local exportButton = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate")
  exportButton:SetSize(178, 24)
  exportButton:SetText("Create Export Package")
  helpers.ApplyProfileUtilityActionStyle(exportButton, "add")
  helpers.AttachProfileActionTooltip(exportButton, "Create Export Package", "Build a checksummed package for the selected profile content. This does not modify the profile.")
  exportButton:SetScript("OnClick", function()
    ExportSelectedScope(editor)
  end)
  editor.lootProfileTransferExportBtn = exportButton

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

  local summaryFrame = CreateFrame("Frame", nil, parent, "BackdropTemplate")
  helpers.ApplyFrameSkin(summaryFrame)
  summaryFrame:EnableMouse(false)
  summaryFrame:SetFrameLevel(math.max((parent:GetFrameLevel() or 1) - 1, 0))
  editor.lootProfileTransferSummaryFrame = summaryFrame

  local summaryTitle = parent:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  summaryTitle:SetJustifyH("LEFT")
  summaryTitle:SetText("Export Package")
  editor.lootProfileTransferSummaryTitle = summaryTitle

  local summary = parent:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  summary:SetJustifyH("LEFT")
  summary:SetJustifyV("TOP")
  editor.lootProfileTransferSummary = summary

  local partText = parent:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  partText:SetJustifyH("LEFT")
  editor.lootProfileTransferPartText = partText

  local previousButton = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate")
  previousButton:SetSize(104, 22)
  previousButton:SetText("Previous Part")
  helpers.ApplyProfileUtilityActionStyle(previousButton, "utility")
  previousButton:SetScript("OnClick", function()
    local result = editor.__lootProfileTransferExport
    if type(result) == "table" then
      result.currentPart = math.max(1, (tonumber(result.currentPart) or 1) - 1)
      RefreshPackageSummary(editor)
    end
  end)
  editor.lootProfileTransferPreviousBtn = previousButton

  local copyButton = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate")
  copyButton:SetSize(136, 22)
  copyButton:SetText("Copy Current Part")
  helpers.ApplyProfileUtilityActionStyle(copyButton, "add")
  copyButton:SetScript("OnClick", function()
    CopyCurrentPart(editor)
  end)
  editor.lootProfileTransferCopyPartBtn = copyButton

  local nextButton = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate")
  nextButton:SetSize(88, 22)
  nextButton:SetText("Next Part")
  helpers.ApplyProfileUtilityActionStyle(nextButton, "utility")
  nextButton:SetScript("OnClick", function()
    local result = editor.__lootProfileTransferExport
    if type(result) == "table" and type(result.parts) == "table" then
      result.currentPart = math.min(#result.parts, (tonumber(result.currentPart) or 1) + 1)
      RefreshPackageSummary(editor)
    end
  end)
  editor.lootProfileTransferNextBtn = nextButton

  local safety = parent:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  safety:SetJustifyH("LEFT")
  safety:SetText("Each part includes package identity, profile identity, checksums, schema metadata, and its exact position. Keep every part for multipart packages.")
  editor.lootProfileTransferSafety = safety

  local importHeader = helpers.MakeYellowSubHeader(parent, "Receive Package", 18, -494)
  editor.lootProfileTransferImportHeader = importHeader

  local importIntro = parent:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  importIntro:SetJustifyH("LEFT")
  importIntro:SetText("Paste every package part on the receiving client. Parts are held only for inspection until you explicitly approve an import.")
  editor.lootProfileTransferImportIntro = importIntro

  local pastePartButton = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate")
  pastePartButton:SetSize(156, 24)
  pastePartButton:SetText("Paste Package Part")
  helpers.ApplyProfileUtilityActionStyle(pastePartButton, "add")
  helpers.AttachProfileActionTooltip(pastePartButton, "Paste Package Part", "Add one exported package part. Parts may be pasted in any order and duplicates are ignored safely.")
  pastePartButton:SetScript("OnClick", function()
    OpenPackagePartPaste(editor)
  end)
  editor.lootProfileTransferPastePartBtn = pastePartButton

  local clearPartsButton = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate")
  clearPartsButton:SetSize(142, 24)
  clearPartsButton:SetText("Clear Received Parts")
  helpers.ApplyProfileUtilityActionStyle(clearPartsButton, "utility")
  helpers.AttachProfileActionTooltip(clearPartsButton, "Clear Received Parts", "Discard only the temporary package-part collection. No profile data is changed.")
  clearPartsButton:SetScript("OnClick", function()
    editor.__lootProfileTransferImport = nil
    SetImportStatus(editor, "Received package parts cleared.", false)
    RefreshImportSummary(editor)
  end)
  editor.lootProfileTransferClearPartsBtn = clearPartsButton

  local importStatus = parent:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  importStatus:SetJustifyH("LEFT")
  importStatus:SetText("")
  editor.lootProfileTransferImportStatus = importStatus

  local importSummaryFrame = CreateFrame("Frame", nil, parent, "BackdropTemplate")
  helpers.ApplyFrameSkin(importSummaryFrame)
  importSummaryFrame:EnableMouse(false)
  importSummaryFrame:SetFrameLevel(math.max((parent:GetFrameLevel() or 1) - 1, 0))
  editor.lootProfileTransferImportSummaryFrame = importSummaryFrame

  local importSummaryTitle = parent:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  importSummaryTitle:SetJustifyH("LEFT")
  importSummaryTitle:SetText("Received Package")
  editor.lootProfileTransferImportSummaryTitle = importSummaryTitle

  local importSummary = parent:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  importSummary:SetJustifyH("LEFT")
  importSummary:SetJustifyV("TOP")
  editor.lootProfileTransferImportSummary = importSummary

  local importSafety = parent:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  importSafety:SetJustifyH("LEFT")
  importSafety:SetText("Collection and inspection are non-mutating. Applying requires a fresh blocker check and explicit confirmation.")
  editor.lootProfileTransferImportSafety = importSafety

  local reviewHeader = helpers.MakeYellowSubHeader(parent, "Review and Apply", 18, -494)
  editor.lootProfileTransferReviewHeader = reviewHeader

  local targetLabel = parent:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  targetLabel:SetJustifyH("LEFT")
  targetLabel:SetText("Target Profile")
  editor.lootProfileTransferTargetLabel = targetLabel

  local targetEdit = helpers.CreateSimpleEditBox(parent, 300, 24)
  targetEdit:SetScript("OnTextChanged", function(self, userInput)
    if not userInput or editor.__lootProfileTransferTargetUpdating then return end
    local collection = editor.__lootProfileTransferImport
    if type(collection) ~= "table" or collection.targetLocked then return end
    collection.targetName = Trim(self:GetText())
    collection.inspection = nil
    collection.inspectedTargetName = nil
    RefreshImportReview(editor)
    RefreshRecoveryControls(editor)
  end)
  targetEdit:SetScript("OnEnterPressed", function(self)
    self:ClearFocus()
    InspectCollectedPackage(editor)
    RefreshImportSummary(editor)
  end)
  targetEdit:SetScript("OnEscapePressed", function(self)
    self:ClearFocus()
    RefreshImportReview(editor)
  end)
  editor.lootProfileTransferTargetEdit = targetEdit

  local refreshReviewButton = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate")
  refreshReviewButton:SetSize(148, 24)
  refreshReviewButton:SetText("Refresh Dry-Run")
  helpers.ApplyProfileUtilityActionStyle(refreshReviewButton, "utility")
  helpers.AttachProfileActionTooltip(refreshReviewButton, "Refresh Dry-Run", "Reassemble and validate the package against the current target, session state, combat state, identity, and schema without changing data.")
  refreshReviewButton:SetScript("OnClick", function()
    InspectCollectedPackage(editor)
    RefreshImportSummary(editor)
  end)
  editor.lootProfileTransferRefreshReviewBtn = refreshReviewButton

  local targetHint = parent:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  targetHint:SetJustifyH("LEFT")
  editor.lootProfileTransferTargetHint = targetHint

  local reviewFrame = CreateFrame("Frame", nil, parent, "BackdropTemplate")
  helpers.ApplyFrameSkin(reviewFrame)
  reviewFrame:EnableMouse(false)
  reviewFrame:SetFrameLevel(math.max((parent:GetFrameLevel() or 1) - 1, 0))
  editor.lootProfileTransferReviewFrame = reviewFrame

  local reviewTitle = parent:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  reviewTitle:SetJustifyH("LEFT")
  reviewTitle:SetText("Dry-Run Result")
  editor.lootProfileTransferReviewTitle = reviewTitle

  local reviewText = parent:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  reviewText:SetJustifyH("LEFT")
  reviewText:SetJustifyV("TOP")
  editor.lootProfileTransferReviewText = reviewText

  local applyButton = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate")
  applyButton:SetSize(176, 24)
  applyButton:SetText("Apply Reviewed Package")
  helpers.ApplyProfileUtilityActionStyle(applyButton, "add")
  helpers.AttachProfileActionTooltip(applyButton, "Apply Reviewed Package", "Run one final safety inspection, ask for confirmation, then apply every selected scope transactionally. Existing data receives a local recovery snapshot first.")
  applyButton:SetScript("OnClick", function()
    ApplyCollectedPackage(editor)
  end)
  editor.lootProfileTransferApplyBtn = applyButton

  local recoveryHeader = helpers.MakeYellowSubHeader(parent, "Local Import Recovery", 18, -494)
  editor.lootProfileTransferRecoveryHeader = recoveryHeader

  local recoveryIntro = parent:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  recoveryIntro:SetJustifyH("LEFT")
  recoveryIntro:SetText("Before an existing profile is replaced, LidCouncil keeps up to three local snapshots. Restore one only when no session is prepared or active and you are out of combat.")
  editor.lootProfileTransferRecoveryIntro = recoveryIntro

  local recoveryDropdown = helpers.CreateDropdownControl(editor, parent, 390, "No Recovery Snapshots")
  helpers.ApplyProfileUtilityDropdownStyle(recoveryDropdown)
  editor.lootProfileTransferRecoveryDropdown = recoveryDropdown

  local restoreButton = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate")
  restoreButton:SetSize(156, 24)
  restoreButton:SetText("Restore Snapshot")
  helpers.ApplyProfileUtilityActionStyle(restoreButton, "restore")
  helpers.AttachProfileActionTooltip(restoreButton, "Restore Transfer Snapshot", "Replace the current profile with the selected local snapshot that was saved immediately before a package import.")
  restoreButton:SetScript("OnClick", function()
    RestoreSelectedRecovery(editor)
  end)
  editor.lootProfileTransferRestoreBtn = restoreButton

  local recoverySummary = parent:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  recoverySummary:SetJustifyH("LEFT")
  recoverySummary:SetJustifyV("TOP")
  editor.lootProfileTransferRecoverySummary = recoverySummary

  RefreshScope(editor)
  RefreshImportSummary(editor)
end

function TransferPage.Layout(editor, expanded, sectionTop, sectionWidth, textWidth, sectionGap)
  if not editor or not editor.lootProfileTransferFrame then
    return sectionTop
  end
  local controls = {
    editor.lootProfileTransferFrame,
    editor.lootProfileTransferHeader,
    editor.lootProfileTransferIntro,
    editor.lootProfileTransferProfileText,
    editor.lootProfileTransferScopeLabel,
    editor.lootProfileTransferScopeDropdown,
    editor.lootProfileTransferScopeDescription,
    editor.lootProfileTransferExportBtn,
    editor.lootProfileTransferStatus,
    editor.lootProfileTransferSummaryFrame,
    editor.lootProfileTransferSummaryTitle,
    editor.lootProfileTransferSummary,
    editor.lootProfileTransferPartText,
    editor.lootProfileTransferPreviousBtn,
    editor.lootProfileTransferCopyPartBtn,
    editor.lootProfileTransferNextBtn,
    editor.lootProfileTransferSafety,
    editor.lootProfileTransferImportHeader,
    editor.lootProfileTransferImportIntro,
    editor.lootProfileTransferPastePartBtn,
    editor.lootProfileTransferClearPartsBtn,
    editor.lootProfileTransferImportStatus,
    editor.lootProfileTransferImportSummaryFrame,
    editor.lootProfileTransferImportSummaryTitle,
    editor.lootProfileTransferImportSummary,
    editor.lootProfileTransferImportSafety,
    editor.lootProfileTransferReviewHeader,
    editor.lootProfileTransferTargetLabel,
    editor.lootProfileTransferTargetEdit,
    editor.lootProfileTransferRefreshReviewBtn,
    editor.lootProfileTransferTargetHint,
    editor.lootProfileTransferReviewFrame,
    editor.lootProfileTransferReviewTitle,
    editor.lootProfileTransferReviewText,
    editor.lootProfileTransferApplyBtn,
    editor.lootProfileTransferRecoveryHeader,
    editor.lootProfileTransferRecoveryIntro,
    editor.lootProfileTransferRecoveryDropdown,
    editor.lootProfileTransferRestoreBtn,
    editor.lootProfileTransferRecoverySummary,
  }
  if not expanded then
    for _, control in ipairs(controls) do
      if control and control.Hide then control:Hide() end
    end
    return sectionTop
  end

  RefreshScope(editor)
  local left = 34
  local width = math.max(220, tonumber(textWidth) or (tonumber(sectionWidth) or 560) - 36)
  local top = tonumber(sectionTop) or -200
  local frameHeight = 1128
  editor.lootProfileTransferFrame:ClearAllPoints()
  editor.lootProfileTransferFrame:SetPoint("TOPLEFT", 18, top)
  editor.lootProfileTransferFrame:SetSize(sectionWidth, frameHeight)
  editor.lootProfileTransferFrame:Show()

  editor.lootProfileTransferHeader:ClearAllPoints()
  editor.lootProfileTransferHeader:SetPoint("TOPLEFT", left, top - 20)
  editor.lootProfileTransferIntro:ClearAllPoints()
  editor.lootProfileTransferIntro:SetPoint("TOPLEFT", left, top - 44)
  editor.lootProfileTransferIntro:SetWidth(width)
  editor.lootProfileTransferProfileText:ClearAllPoints()
  editor.lootProfileTransferProfileText:SetPoint("TOPLEFT", left, top - 82)
  editor.lootProfileTransferScopeLabel:ClearAllPoints()
  editor.lootProfileTransferScopeLabel:SetPoint("TOPLEFT", left, top - 108)
  editor.lootProfileTransferScopeDropdown:ClearAllPoints()
  editor.lootProfileTransferScopeDropdown:SetPoint("TOPLEFT", left, top - 128)
  editor.lootProfileTransferScopeDescription:ClearAllPoints()
  editor.lootProfileTransferScopeDescription:SetPoint("TOPLEFT", left + 348, top - 130)
  editor.lootProfileTransferScopeDescription:SetWidth(math.max(180, width - 348))
  editor.lootProfileTransferExportBtn:ClearAllPoints()
  editor.lootProfileTransferExportBtn:SetPoint("TOPLEFT", left, top - 166)
  editor.lootProfileTransferStatus:ClearAllPoints()
  editor.lootProfileTransferStatus:SetPoint("LEFT", editor.lootProfileTransferExportBtn, "RIGHT", 12, 0)
  editor.lootProfileTransferStatus:SetWidth(math.max(180, width - 200))

  editor.lootProfileTransferSummaryFrame:ClearAllPoints()
  editor.lootProfileTransferSummaryFrame:SetPoint("TOPLEFT", left, top - 204)
  editor.lootProfileTransferSummaryFrame:SetSize(width, 108)
  editor.lootProfileTransferSummaryTitle:ClearAllPoints()
  editor.lootProfileTransferSummaryTitle:SetPoint("TOPLEFT", left + 12, top - 216)
  editor.lootProfileTransferSummary:ClearAllPoints()
  editor.lootProfileTransferSummary:SetPoint("TOPLEFT", left + 12, top - 238)
  editor.lootProfileTransferSummary:SetWidth(width - 24)
  editor.lootProfileTransferPartText:ClearAllPoints()
  editor.lootProfileTransferPartText:SetPoint("TOPLEFT", left, top - 322)
  editor.lootProfileTransferPreviousBtn:ClearAllPoints()
  editor.lootProfileTransferPreviousBtn:SetPoint("LEFT", editor.lootProfileTransferPartText, "RIGHT", 18, 0)
  editor.lootProfileTransferCopyPartBtn:ClearAllPoints()
  editor.lootProfileTransferCopyPartBtn:SetPoint("LEFT", editor.lootProfileTransferPreviousBtn, "RIGHT", 8, 0)
  editor.lootProfileTransferNextBtn:ClearAllPoints()
  editor.lootProfileTransferNextBtn:SetPoint("LEFT", editor.lootProfileTransferCopyPartBtn, "RIGHT", 8, 0)
  editor.lootProfileTransferSafety:ClearAllPoints()
  editor.lootProfileTransferSafety:SetPoint("TOPLEFT", left, top - 360)
  editor.lootProfileTransferSafety:SetWidth(width)

  editor.lootProfileTransferImportHeader:ClearAllPoints()
  editor.lootProfileTransferImportHeader:SetPoint("TOPLEFT", left, top - 414)
  editor.lootProfileTransferImportIntro:ClearAllPoints()
  editor.lootProfileTransferImportIntro:SetPoint("TOPLEFT", left, top - 438)
  editor.lootProfileTransferImportIntro:SetWidth(width)
  editor.lootProfileTransferPastePartBtn:ClearAllPoints()
  editor.lootProfileTransferPastePartBtn:SetPoint("TOPLEFT", left, top - 472)
  editor.lootProfileTransferClearPartsBtn:ClearAllPoints()
  editor.lootProfileTransferClearPartsBtn:SetPoint("LEFT", editor.lootProfileTransferPastePartBtn, "RIGHT", 8, 0)
  editor.lootProfileTransferImportStatus:ClearAllPoints()
  editor.lootProfileTransferImportStatus:SetPoint("LEFT", editor.lootProfileTransferClearPartsBtn, "RIGHT", 12, 0)
  editor.lootProfileTransferImportStatus:SetWidth(math.max(180, width - 330))
  editor.lootProfileTransferImportSummaryFrame:ClearAllPoints()
  editor.lootProfileTransferImportSummaryFrame:SetPoint("TOPLEFT", left, top - 510)
  editor.lootProfileTransferImportSummaryFrame:SetSize(width, 124)
  editor.lootProfileTransferImportSummaryTitle:ClearAllPoints()
  editor.lootProfileTransferImportSummaryTitle:SetPoint("TOPLEFT", left + 12, top - 522)
  editor.lootProfileTransferImportSummary:ClearAllPoints()
  editor.lootProfileTransferImportSummary:SetPoint("TOPLEFT", left + 12, top - 544)
  editor.lootProfileTransferImportSummary:SetWidth(width - 24)
  editor.lootProfileTransferImportSafety:ClearAllPoints()
  editor.lootProfileTransferImportSafety:SetPoint("TOPLEFT", left, top - 650)
  editor.lootProfileTransferImportSafety:SetWidth(width)

  editor.lootProfileTransferReviewHeader:ClearAllPoints()
  editor.lootProfileTransferReviewHeader:SetPoint("TOPLEFT", left, top - 700)
  editor.lootProfileTransferTargetLabel:ClearAllPoints()
  editor.lootProfileTransferTargetLabel:SetPoint("TOPLEFT", left, top - 730)
  editor.lootProfileTransferTargetEdit:ClearAllPoints()
  editor.lootProfileTransferTargetEdit:SetPoint("TOPLEFT", left, top - 750)
  editor.lootProfileTransferRefreshReviewBtn:ClearAllPoints()
  editor.lootProfileTransferRefreshReviewBtn:SetPoint("LEFT", editor.lootProfileTransferTargetEdit, "RIGHT", 10, 0)
  editor.lootProfileTransferTargetHint:ClearAllPoints()
  editor.lootProfileTransferTargetHint:SetPoint("TOPLEFT", left, top - 780)
  editor.lootProfileTransferTargetHint:SetWidth(width)
  editor.lootProfileTransferReviewFrame:ClearAllPoints()
  editor.lootProfileTransferReviewFrame:SetPoint("TOPLEFT", left, top - 810)
  editor.lootProfileTransferReviewFrame:SetSize(width, 128)
  editor.lootProfileTransferReviewTitle:ClearAllPoints()
  editor.lootProfileTransferReviewTitle:SetPoint("TOPLEFT", left + 12, top - 822)
  editor.lootProfileTransferReviewText:ClearAllPoints()
  editor.lootProfileTransferReviewText:SetPoint("TOPLEFT", left + 12, top - 844)
  editor.lootProfileTransferReviewText:SetWidth(width - 24)
  editor.lootProfileTransferApplyBtn:ClearAllPoints()
  editor.lootProfileTransferApplyBtn:SetPoint("TOPLEFT", left, top - 948)

  editor.lootProfileTransferRecoveryHeader:ClearAllPoints()
  editor.lootProfileTransferRecoveryHeader:SetPoint("TOPLEFT", left, top - 994)
  editor.lootProfileTransferRecoveryIntro:ClearAllPoints()
  editor.lootProfileTransferRecoveryIntro:SetPoint("TOPLEFT", left, top - 1018)
  editor.lootProfileTransferRecoveryIntro:SetWidth(width)
  editor.lootProfileTransferRecoveryDropdown:ClearAllPoints()
  editor.lootProfileTransferRecoveryDropdown:SetPoint("TOPLEFT", left, top - 1058)
  editor.lootProfileTransferRestoreBtn:ClearAllPoints()
  editor.lootProfileTransferRestoreBtn:SetPoint("LEFT", editor.lootProfileTransferRecoveryDropdown, "RIGHT", 10, 0)
  editor.lootProfileTransferRecoverySummary:ClearAllPoints()
  editor.lootProfileTransferRecoverySummary:SetPoint("TOPLEFT", left, top - 1092)
  editor.lootProfileTransferRecoverySummary:SetWidth(width)

  for _, control in ipairs(controls) do
    if control and control.Show then control:Show() end
  end
  RefreshPackageSummary(editor)
  RefreshImportSummary(editor)
  return top - frameHeight - (tonumber(sectionGap) or 18)
end

INTERNAL_API.LIDCOUNCIL_ProfileTransferPage_Impl = TransferPage
