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

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

  local TrimText = deps.TrimText
  local ResolveOptionalApiFunction = deps.ResolveOptionalApiFunction
  local GetLootProfilePermissionPolicyRoleState = deps.GetLootProfilePermissionPolicyRoleState
  local ApplyTrafficLight = deps.ApplyTrafficLight
  local SetListButtonSelected = deps.SetListButtonSelected
  local SetTextListButtonTextColor = deps.SetTextListButtonTextColor
  local FlowLayoutControls = deps.FlowLayoutControls
  local ClampLayoutValue = deps.ClampLayoutValue
  local FormatLootProfileRoleLabel = deps.FormatLootProfileRoleLabel

  local SIMULATION_ROLE_OPTIONS = {
    { key = "MASTER", label = "Master" },
    { key = "SESSION_HOST", label = "Session Host" },
    { key = "COUNCIL", label = "Council Member" },
    { key = "RAIDER", label = "Raider" },
  }

  local ROLE_SIM_RIGHTS_MATRIX = {
    { section = "Profile" },
    { right = "Delete Local Profile Copy", permissionKey = "canDeleteProfile" },
    { right = "Manage Rights", permissionKey = "canManageRights" },
    { right = "Edit Profile Settings", permissionKeys = { "canEditRaidSettings", "canEditRollSettings", "canEditPointSettings" } },
    { section = "Session" },
    { right = "Start Session", permissionKey = "canStartSession" },
    { right = "Manage / Stop Session", permissionKey = "canManageSession" },
    { right = "Open Live Board", permissionKey = "canOpenLiveBoard" },
    { right = "Use Voting", permissionKey = "canVote" },
    { right = "Assign / Unassign Loot", permissionKey = "canAssignLoot" },
    { right = "View Current Session", master = true, sessionHost = true, council = true, raider = true },
    { right = "View Session History", master = true, sessionHost = true, council = true, raider = true },
    { right = "Enable / Disable Personal Auto Pass", master = true, sessionHost = true, council = true, raider = true },
    { right = "Receive Roll Popup / Choose Roll", master = true, sessionHost = true, council = true, raider = true },
    { right = "View Live Board History", master = true, sessionHost = true, council = true, raider = true },
    { section = "Loot List" },
    { right = "Edit Loot List", permissionKey = "canEditLootList" },
    { right = "View Loot List", master = true, sessionHost = true, council = true, raider = true },
    { right = "View Loot List Details", master = true, sessionHost = true, council = true, raider = true },
  }

  local function GetRoleSimMatrixCellText(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 RefreshRoleSimulationView(editor, context)
    if not editor then
      return
    end

    context = type(context) == "table" and context or {}
    local profileName = TrimText(context.profileName)
    local access = type(context.access) == "table" and context.access or {}

    local effectiveRoleLabel = type(FormatLootProfileRoleLabel) == "function"
      and FormatLootProfileRoleLabel(access.role)
      or TrimText(access.role)
    local getSimulationRoleMode = ResolveOptionalApiFunction("LIDCOUNCIL_GetSimulationRoleMode")
    local simulationRoleMode = type(getSimulationRoleMode) == "function"
      and string.upper(TrimText(getSimulationRoleMode(profileName) or ""))
      or string.upper(TrimText(access.role))
    if simulationRoleMode == "" then
      simulationRoleMode = string.upper(TrimText(access.role))
    end
    local effectiveModeLabel = simulationRoleMode == "SESSION_HOST" and "Session Host" or effectiveRoleLabel
    local masterPolicy = type(GetLootProfilePermissionPolicyRoleState) == "function" and GetLootProfilePermissionPolicyRoleState(profileName, "MASTER") or {}
    local sessionHostPolicy = type(GetLootProfilePermissionPolicyRoleState) == "function" and GetLootProfilePermissionPolicyRoleState(profileName, "SESSION_HOST") or {}
    local councilPolicy = type(GetLootProfilePermissionPolicyRoleState) == "function" and GetLootProfilePermissionPolicyRoleState(profileName, "COUNCIL") or {}
    local raiderPolicy = type(GetLootProfilePermissionPolicyRoleState) == "function" and GetLootProfilePermissionPolicyRoleState(profileName, "RAIDER") or {}

    if editor.lootSessionTitle then
      editor.lootSessionTitle:SetText("Role Simulation")
    end
    if editor.lootSessionStatus then
      editor.lootSessionStatus:SetText("Simulation role override active")
      editor.lootSessionStatus:SetTextColor(1.00, 0.82, 0.32, 1.00)
    end
    ApplyTrafficLight(editor.lootSessionStatusIndicator, "PARTIAL")

    if editor.lootSessionRoleSimDesc then
      editor.lootSessionRoleSimDesc:SetText(
        "This testing-only tool changes your local effective role while the activated profile is Simulation. " ..
        "It does not change real council/master assignments in normal profiles."
      )
    end
    if editor.lootSessionRoleSimCurrent then
      editor.lootSessionRoleSimCurrent:SetText("Effective Simulation Mode: " .. effectiveModeLabel)
    end
    if editor.lootSessionRoleSimState then
      editor.lootSessionRoleSimState:SetText(
        "The rights overview below reads the current Council Settings policy of the Simulation profile. " ..
        "If you change those rights in Profile > Council Settings, this table updates automatically."
      )
    end

    for _, row in ipairs(editor.lootSessionRoleSimMatrixRows or {}) do
      local def = row.definition or {}
      row.__isRoleSimSection = def.section and true or false
      if row.__isRoleSimSection then
        if row.SetBackdropColor then
          row:SetBackdropColor(0, 0, 0, 0)
        end
        if row.SetBackdropBorderColor then
          row:SetBackdropBorderColor(0, 0, 0, 0)
        end
        row.rightText:SetText(tostring(def.section or ""))
        row.rightText:SetTextColor(1.00, 0.82, 0.32, 1.00)
        row.masterText:SetText("")
        row.sessionHostText:SetText("")
        row.councilText:SetText("")
        row.raiderText:SetText("")
      else
        if row.SetBackdropColor then
          row:SetBackdropColor(0.05, 0.05, 0.07, 0.94)
        end
        row.rightText:SetText(tostring(def.right or ""))
        row.rightText:SetTextColor(0.92, 0.92, 0.96, 1.00)
        row.masterText:SetText(GetRoleSimMatrixCellText(ResolveRoleSimMatrixValue(def, masterPolicy, "master")))
        row.sessionHostText:SetText(GetRoleSimMatrixCellText(ResolveRoleSimMatrixValue(def, sessionHostPolicy, "sessionHost")))
        row.councilText:SetText(GetRoleSimMatrixCellText(ResolveRoleSimMatrixValue(def, councilPolicy, "council")))
        row.raiderText:SetText(GetRoleSimMatrixCellText(ResolveRoleSimMatrixValue(def, raiderPolicy, "raider")))
      end
    end

    for _, def in ipairs(SIMULATION_ROLE_OPTIONS) do
      local button = def.key == "MASTER" and editor.sessionRoleSimMasterBtn
        or (def.key == "SESSION_HOST" and editor.sessionRoleSimSessionHostBtn
        or (def.key == "COUNCIL" and editor.sessionRoleSimCouncilBtn or editor.sessionRoleSimRaiderBtn))
      local isSelected = simulationRoleMode == def.key
      if button then
        SetListButtonSelected(button, isSelected)
        SetTextListButtonTextColor(button, isSelected and { 1.00, 0.88, 0.32, 1.00 } or { 0.92, 0.92, 0.96, 1.00 })
        if button.Enable then
          button:Enable()
        end
      end
    end

    if editor.lootSessionBody then
      editor.lootSessionBody:SetText("")
      editor.lootSessionBody:Hide()
    end
  end

  local function LayoutRoleSimulationSection(editor, page, rightContentWidth)
    if not editor then
      return 220
    end

    if editor.sessionSyncBoardBtn then
      editor.sessionSyncBoardBtn:Hide()
    end
    if editor.lootSessionRoleSimDesc then
      editor.lootSessionRoleSimDesc:ClearAllPoints()
      editor.lootSessionRoleSimDesc:SetPoint("TOPLEFT", 18, -106)
      editor.lootSessionRoleSimDesc:SetWidth(rightContentWidth)
    end
    if editor.lootSessionRoleSimCurrent then
      editor.lootSessionRoleSimCurrent:ClearAllPoints()
      editor.lootSessionRoleSimCurrent:SetPoint("TOPLEFT", 18, -152)
      editor.lootSessionRoleSimCurrent:SetWidth(rightContentWidth)
    end

    local buttonHeight = FlowLayoutControls({
      editor.sessionRoleSimMasterBtn,
      editor.sessionRoleSimSessionHostBtn,
      editor.sessionRoleSimCouncilBtn,
      editor.sessionRoleSimRaiderBtn,
    }, 18, -184, rightContentWidth, 10, 8)

    local matrixTop = -184 - buttonHeight - 16
    local matrixWidth = rightContentWidth
    local rightsWidth = ClampLayoutValue(math.floor(matrixWidth * 0.34), 140, 240)
    local roleColumnWidth = math.max(56, math.floor((matrixWidth - rightsWidth) / 4))
    local matrixRowHeight = 24
    local matrixGap = 4
    local matrixSectionGap = 12
    local headerHeight = 24
    local matrixRowsHeight = 0
    for index, row in ipairs(editor.lootSessionRoleSimMatrixRows or {}) do
      if index > 1 and row.__isRoleSimSection then
        matrixRowsHeight = matrixRowsHeight + matrixSectionGap
      end
      matrixRowsHeight = matrixRowsHeight + matrixRowHeight + matrixGap
    end
    local matrixHeight = headerHeight + matrixRowsHeight

    if editor.lootSessionRoleSimMatrixFrame then
      editor.lootSessionRoleSimMatrixFrame:ClearAllPoints()
      editor.lootSessionRoleSimMatrixFrame:SetPoint("TOPLEFT", 18, matrixTop)
      editor.lootSessionRoleSimMatrixFrame:SetSize(matrixWidth, matrixHeight)
    end
    if editor.lootSessionRoleSimMatrixHeader then
      editor.lootSessionRoleSimMatrixHeader:ClearAllPoints()
      editor.lootSessionRoleSimMatrixHeader:SetPoint("TOPLEFT", editor.lootSessionRoleSimMatrixFrame, "TOPLEFT", 0, 0)
      editor.lootSessionRoleSimMatrixHeader:SetSize(matrixWidth, headerHeight)
    end

    local masterX = rightsWidth
    local sessionHostX = masterX + roleColumnWidth
    local councilX = sessionHostX + roleColumnWidth
    local raiderX = councilX + roleColumnWidth
    if editor.lootSessionRoleSimHeaderRight then
      editor.lootSessionRoleSimHeaderRight:ClearAllPoints()
      editor.lootSessionRoleSimHeaderRight:SetPoint("TOPLEFT", editor.lootSessionRoleSimMatrixHeader, "TOPLEFT", 10, -5)
      editor.lootSessionRoleSimHeaderRight:SetWidth(rightsWidth - 16)
    end
    if editor.lootSessionRoleSimHeaderMaster then
      editor.lootSessionRoleSimHeaderMaster:ClearAllPoints()
      editor.lootSessionRoleSimHeaderMaster:SetPoint("TOPLEFT", editor.lootSessionRoleSimMatrixHeader, "TOPLEFT", masterX, -5)
      editor.lootSessionRoleSimHeaderMaster:SetWidth(roleColumnWidth)
    end
    if editor.lootSessionRoleSimHeaderSessionHost then
      editor.lootSessionRoleSimHeaderSessionHost:ClearAllPoints()
      editor.lootSessionRoleSimHeaderSessionHost:SetPoint("TOPLEFT", editor.lootSessionRoleSimMatrixHeader, "TOPLEFT", sessionHostX, -5)
      editor.lootSessionRoleSimHeaderSessionHost:SetWidth(roleColumnWidth)
    end
    if editor.lootSessionRoleSimHeaderCouncil then
      editor.lootSessionRoleSimHeaderCouncil:ClearAllPoints()
      editor.lootSessionRoleSimHeaderCouncil:SetPoint("TOPLEFT", editor.lootSessionRoleSimMatrixHeader, "TOPLEFT", councilX, -5)
      editor.lootSessionRoleSimHeaderCouncil:SetWidth(roleColumnWidth)
    end
    if editor.lootSessionRoleSimHeaderRaider then
      editor.lootSessionRoleSimHeaderRaider:ClearAllPoints()
      editor.lootSessionRoleSimHeaderRaider:SetPoint("TOPLEFT", editor.lootSessionRoleSimMatrixHeader, "TOPLEFT", raiderX, -5)
      editor.lootSessionRoleSimHeaderRaider:SetWidth(roleColumnWidth)
    end

    local matrixRowOffset = headerHeight + matrixGap
    for index, row in ipairs(editor.lootSessionRoleSimMatrixRows or {}) do
      if index > 1 and row.__isRoleSimSection then
        matrixRowOffset = matrixRowOffset + matrixSectionGap
      end
      local rowY = -matrixRowOffset
      row:ClearAllPoints()
      row:SetPoint("TOPLEFT", editor.lootSessionRoleSimMatrixFrame, "TOPLEFT", 0, rowY)
      row:SetSize(matrixWidth, matrixRowHeight)
      row.rightText:ClearAllPoints()
      row.rightText:SetPoint("TOPLEFT", row, "TOPLEFT", 10, -5)
      row.rightText:SetWidth(row.__isRoleSimSection and (matrixWidth - 20) or (rightsWidth - 16))
      row.masterText:ClearAllPoints()
      row.masterText:SetPoint("TOPLEFT", row, "TOPLEFT", masterX, -5)
      row.masterText:SetWidth(roleColumnWidth)
      row.masterText:SetShown(not row.__isRoleSimSection)
      row.sessionHostText:ClearAllPoints()
      row.sessionHostText:SetPoint("TOPLEFT", row, "TOPLEFT", sessionHostX, -5)
      row.sessionHostText:SetWidth(roleColumnWidth)
      row.sessionHostText:SetShown(not row.__isRoleSimSection)
      row.councilText:ClearAllPoints()
      row.councilText:SetPoint("TOPLEFT", row, "TOPLEFT", councilX, -5)
      row.councilText:SetWidth(roleColumnWidth)
      row.councilText:SetShown(not row.__isRoleSimSection)
      row.raiderText:ClearAllPoints()
      row.raiderText:SetPoint("TOPLEFT", row, "TOPLEFT", raiderX, -5)
      row.raiderText:SetWidth(roleColumnWidth)
      row.raiderText:SetShown(not row.__isRoleSimSection)
      matrixRowOffset = matrixRowOffset + matrixRowHeight + matrixGap
    end

    local stateTop = matrixTop - matrixHeight - 10
    if editor.lootSessionRoleSimState then
      editor.lootSessionRoleSimState:ClearAllPoints()
      editor.lootSessionRoleSimState:SetPoint("TOPLEFT", 18, stateTop)
      editor.lootSessionRoleSimState:SetWidth(rightContentWidth)
    end
    local stateHeight = math.max(40, math.ceil((editor.lootSessionRoleSimState and editor.lootSessionRoleSimState:IsShown() and editor.lootSessionRoleSimState:GetStringHeight() or 0)))
    local contentBottom = math.abs(stateTop) + stateHeight + 24
    if page then
      page.__contentHeight = math.max(420, contentBottom)
    end
    return contentBottom
  end

  return {
    RefreshRoleSimulationView = RefreshRoleSimulationView,
    LayoutRoleSimulationSection = LayoutRoleSimulationSection,
    SIMULATION_ROLE_OPTIONS = SIMULATION_ROLE_OPTIONS,
    ROLE_SIM_RIGHTS_MATRIX = ROLE_SIM_RIGHTS_MATRIX,
  }
end
