// hwpx_util.mjs — OWPML section0 조작 공용 유틸 (깊이 인식)
// finalize_layout 및 프래그먼트 추출에서 공용 사용.

// 최상위 hp:p 문단만 분리 (표/머리말/드로잉 안의 중첩 hp:p 는 건너뜀).
// 반환: [{xml, start, end}] (start/end 는 sec 내 오프셋)
export function splitTopLevelParas(sec) {
  const tok = /<hp:p\b|<\/hp:p>/g;
  const out = [];
  let depth = 0, startIdx = -1, m;
  while ((m = tok.exec(sec))) {
    if (m[0] === '</hp:p>') {
      depth--;
      if (depth === 0) {
        out.push({ xml: sec.slice(startIdx, tok.lastIndex), start: startIdx, end: tok.lastIndex });
        startIdx = -1;
      }
    } else {
      if (depth === 0) startIdx = m.index;
      depth++;
    }
  }
  return out;
}

// 한 문단의 여는 태그 속성 추출
export function paraAttrs(pxml) {
  const open = pxml.slice(0, pxml.indexOf('>') + 1);
  return {
    styleIDRef: (open.match(/styleIDRef="(\d+)"/) || [])[1],
    paraPrIDRef: (open.match(/paraPrIDRef="(\d+)"/) || [])[1],
    pageBreak: (open.match(/pageBreak="(\d+)"/) || [])[1],
  };
}

// 문단 최상위(첫 서브리스트 진입 전) 텍스트만 — styleIDRef 판정용.
// 표/머리말 안의 텍스트가 섞이지 않도록 첫 <hp:tbl|hp:ctrl|hp:pic|hp:rect|hp:drawText 이전까지만.
export function paraLeadText(pxml) {
  let cut = pxml.length;
  for (const tag of ['<hp:tbl', '<hp:subList']) {
    const i = pxml.indexOf(tag);
    if (i >= 0 && i < cut) cut = i;
  }
  const head = pxml.slice(0, cut);
  return [...head.matchAll(/<hp:t>([\s\S]*?)<\/hp:t>/g)].map((x) => x[1]).join('').replace(/<[^>]+>/g, '').trim();
}

// section0 루트 여는태그/닫는태그 분리: <hs:sec ...> ... </hs:sec> 혹은 <hp:p ...> 바로 시작 형태 대응
export function splitSectionShell(sec) {
  // 첫 최상위 hp:p 시작 전까지를 head, 마지막 hp:p 끝 이후를 tail 로.
  const paras = splitTopLevelParas(sec);
  if (!paras.length) return { head: '', tail: '', body: sec };
  const head = sec.slice(0, paras[0].start);
  const tail = sec.slice(paras[paras.length - 1].end);
  return { head, tail, paras };
}

// XML 텍스트 이스케이프
export function esc(s) {
  return String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}
