export interface MarkdownSection {
  heading: string;
  level: number;
  content: string;
  startOffset: number;
  endOffset: number;
}

const HEADING_RE = /^(#{1,6})\s+(.*)$/gm;

function parseFallbackSections(body: string): MarkdownSection[] {
  if (!body.trim())
    return [];

  const isPseudoHeading = (text: string): boolean => {
    const t = text.trim();
    return (
      t.length > 0 && t.length <= 120 &&
      !t.includes('\n') &&
      !/^[-*+>]/.test(t) &&
      !/^\d+\./.test(t) &&
      !/^`{3,}/.test(t)
    );
  };

  // Build paragraph list with exact start/end offsets
  const separatorRe = /\n{2,}/g;
  const paragraphs: Array<{ text: string; start: number; end: number }> = [];
  let lastEnd = 0;
  let sep: RegExpExecArray | null;
  while ((sep = separatorRe.exec(body)) !== null) {
    if (sep.index > lastEnd)
      paragraphs.push({ text: body.slice(lastEnd, sep.index), start: lastEnd, end: sep.index });
    lastEnd = sep.index + sep[0].length;
  }
  if (lastEnd < body.length)
    paragraphs.push({ text: body.slice(lastEnd), start: lastEnd, end: body.length });

  if (paragraphs.length === 0)
    return [{ heading: '', level: 0, content: body, startOffset: 0, endOffset: body.length }];

  const headingIndices = new Set(
    paragraphs.map((p, i) => isPseudoHeading(p.text) ? i : -1).filter(i => i >= 0)
  );
  if (headingIndices.size === 0) {
    // No pseudo-headings — check if body is a bullet/numbered list.
    // If so, treat each top-level item (no leading spaces) as a section.
    const TOP_BULLET_RE = /^(?:[-*+]|\d+\.) /gm;
    const bulletStarts: number[] = [];
    let bm: RegExpExecArray | null;
    while ((bm = TOP_BULLET_RE.exec(body)) !== null) {
      bulletStarts.push(bm.index);
    }
    if (bulletStarts.length > 1) {
      return bulletStarts.map((startIdx, i) => {
        const endIdx = i + 1 < bulletStarts.length ? bulletStarts[i + 1] : body.length;
        const content = body.slice(startIdx, endIdx);
        const firstLine = content.split('\n')[0].replace(/^(?:[-*+]|\d+\.) /, '').trim();
        return {
          heading: firstLine.length > 50 ? firstLine.slice(0, 50) + '\u2026' : firstLine,
          level: 0,
          content,
          startOffset: startIdx,
          endOffset: endIdx,
        };
      });
    }
    return [{ heading: '', level: 0, content: body, startOffset: 0, endOffset: body.length }];
  }

  const sections: MarkdownSection[] = [];
  const headingIdxArray = [...headingIndices].sort((a, b) => a - b);
  const firstHi = headingIdxArray[0];

  // Preamble (content before first pseudo-heading)
  if (firstHi > 0) {
    sections.push({
      heading: '', level: 0,
      content: body.slice(paragraphs[0].start, paragraphs[firstHi].start),
      startOffset: paragraphs[0].start,
      endOffset: paragraphs[firstHi].start,
    });
  }

  // One section per pseudo-heading
  for (let h = 0; h < headingIdxArray.length; h++) {
    const hi = headingIdxArray[h];
    const nextHi = h + 1 < headingIdxArray.length ? headingIdxArray[h + 1] : null;
    const sectionEnd = nextHi !== null ? paragraphs[nextHi].start : body.length;
    sections.push({
      heading: paragraphs[hi].text.trim(),
      level: 0,
      content: body.slice(paragraphs[hi].start, sectionEnd),
      startOffset: paragraphs[hi].start,
      endOffset: sectionEnd,
    });
  }
  return sections;
}

export function parseMarkdownSections(body: string): MarkdownSection[] {
  const sections: MarkdownSection[] = [];
  const matches: { index: number; level: number; heading: string }[] = [];

  let match: RegExpExecArray | null;
  while ((match = HEADING_RE.exec(body)) !== null) {
    matches.push({
      index: match.index,
      level: match[1].length,
      heading: match[0],
    });
  }

  // Preamble: text before the first heading
  if (matches.length === 0) {
    return parseFallbackSections(body);
  }

  if (matches[0].index > 0) {
    sections.push({
      heading: "",
      level: 0,
      content: body.slice(0, matches[0].index),
      startOffset: 0,
      endOffset: matches[0].index,
    });
  }

  for (let i = 0; i < matches.length; i++) {
    const start = matches[i].index;
    const end = i + 1 < matches.length ? matches[i + 1].index : body.length;
    sections.push({
      heading: matches[i].heading,
      level: matches[i].level,
      content: body.slice(start, end),
      startOffset: start,
      endOffset: end,
    });
  }

  return sections;
}
