/**
 * Group section questions: main first, then its children (from `child_question_ids`).
 * Children are not repeated as top-level rows. Orphans (child without parent in section) render as single rows.
 *
 * IDs are normalized to numbers so Map/Set lookups work when API returns string ids (MySQL/json).
 *
 * @param {Array<{ question_id: number, main_question_id?: number|null, child_question_ids?: number[] }>} questions
 * @returns {Array<{ main: object, children: object[], orphan?: boolean }>}
 */
function normId(v) {
  const n = Number(v);
  return Number.isFinite(n) ? n : v;
}

/** Same rules as `getRpnRole` in SnapDetailCreatePage (SAT-style text match). */
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 isTopLevelMain(q) {
  const mq = q.main_question_id;
  return !(mq != null && mq !== '' && Number(mq) > 0);
}

/**
 * If a section includes an RPN question, that main row and its combined children are last.
 * Preserves relative order of all other questions.
 *
 * @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];
}

export function buildSectionQuestionGroups(questions) {
  if (!Array.isArray(questions) || questions.length === 0) return [];

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

  for (const q of questions) {
    const mq = q.main_question_id;
    /* Skip combined/RPN child rows; they render under the parent. */
    if (mq != null && mq !== '' && Number(mq) > 0) continue;

    const rawChildIds = q.child_question_ids || [];
    const children = rawChildIds.map((id) => byId.get(normId(id))).filter(Boolean);
    groups.push({ main: q, children });
    const mid = normId(q.question_id);
    inGroup.add(mid);
    for (const c of children) {
      inGroup.add(normId(c.question_id));
    }
  }

  for (const q of questions) {
    const id = normId(q.question_id);
    if (!inGroup.has(id)) {
      groups.push({ main: q, children: [], orphan: true });
      inGroup.add(id);
    }
  }

  return groups;
}
