/**
 * SAT-style RPN: same text rules as the ORAC snap UI (`getRpnRole`).
 * @param {string} [questionText]
 * @returns {'likelihood' | 'severity' | 'rpn' | null}
 */
export function getOracRpnRole(questionText) {
  const t = (questionText || "").toLowerCase();
  if (t.includes("likelihood of harm")) return "likelihood";
  if (t.includes("severity of harm")) return "severity";
  if (t.includes("rpn")) return "rpn";
  return null;
}

function normId(v) {
  const n = Number(v);
  return Number.isFinite(n) ? n : v;
}

/** True if this row is a top-level question in the section (not a combined child). */
function isTopLevelMain(q) {
  const mq = q.main_question_id;
  return !(mq != null && mq !== "" && Number(mq) > 0);
}

/**
 * If a section includes an RPN question (question text matches the RPN role),
 * that question and its combined children are moved to the end of the list.
 * Other questions keep their relative order.
 *
 * @param {Array<object>} questions
 * @returns {Array<object>}
 */
export function sortSectionQuestionsRpnLast(questions) {
  if (!Array.isArray(questions) || questions.length === 0) return questions;

  const byId = new Map(questions.map((q) => [normId(q.question_id), q]));

  /** @type {Array<number[]>} */
  const rpnClusters = [];
  const rpnClusterIds = new Set();

  for (const q of questions) {
    if (!isTopLevelMain(q)) continue;
    if (getOracRpnRole(q.question) !== "rpn") continue;
    const mid = normId(q.question_id);
    const childIds = (q.child_question_ids || []).map(normId);
    const ids = [mid, ...childIds];
    for (const id of ids) rpnClusterIds.add(id);
    rpnClusters.push(ids);
  }

  if (rpnClusters.length === 0) return questions;

  const rest = [];
  for (const q of questions) {
    const id = normId(q.question_id);
    if (!rpnClusterIds.has(id)) rest.push(q);
  }

  const tail = [];
  for (const cluster of rpnClusters) {
    for (const id of cluster) {
      const row = byId.get(id);
      if (row) tail.push(row);
    }
  }

  return [...rest, ...tail];
}
