/* Long-form text in a caddie app — a stage's body, a brief, a summary of
 * what a client said. Block-level markdown-lite on top of Body's inline
 * rules: headings (##, ###), paragraphs, bullet lists (- or *), block quotes
 * (>), rules (---). Dependency-free and never innerHTML, like Body; the same
 * own-URLs-only image rule applies inside it. */

import { type ReactNode } from "react";
import { renderBody } from "./Body";

type Block =
  | { kind: "h"; level: number; text: string }
  | { kind: "p"; text: string }
  | { kind: "ul"; items: string[] }
  | { kind: "quote"; lines: string[] }
  | { kind: "hr" };

export function parseProse(text: string): Block[] {
  const out: Block[] = [];
  let para: string[] = [];
  const flush = () => {
    if (para.length) { out.push({ kind: "p", text: para.join(" ") }); para = []; }
  };
  for (const raw of text.replace(/\r\n?/g, "\n").split("\n")) {
    const line = raw.trimEnd();
    const h = line.match(/^(#{1,4})\s+(.*)$/);
    const li = line.match(/^\s*[-*]\s+(.*)$/);
    const q = line.match(/^>\s?(.*)$/);
    if (!line.trim()) { flush(); continue; }
    if (/^-{3,}$/.test(line.trim())) { flush(); out.push({ kind: "hr" }); continue; }
    if (h) { flush(); out.push({ kind: "h", level: h[1].length, text: h[2] }); continue; }
    if (li) {
      flush();
      const last = out[out.length - 1];
      if (last && last.kind === "ul") last.items.push(li[1]);
      else out.push({ kind: "ul", items: [li[1]] });
      continue;
    }
    if (q) {
      flush();
      const last = out[out.length - 1];
      if (last && last.kind === "quote") last.lines.push(q[1]);
      else out.push({ kind: "quote", lines: [q[1]] });
      continue;
    }
    para.push(line.trim());
  }
  flush();
  return out;
}

export function Prose({ text, imagePrefix, className }: {
  text: string; imagePrefix?: string; className?: string;
}) {
  const blocks = parseProse(text);
  const inline = (t: string): ReactNode => renderBody(t, imagePrefix);
  return (
    <div className={`cu-prose ${className ?? ""}`}>
      {blocks.map((b, i) => {
        switch (b.kind) {
          case "h": {
            const level = Math.min(4, b.level + 1);  // ## in text = h3 on the page
            return level === 2 ? <h2 key={i}>{inline(b.text)}</h2>
              : level === 3 ? <h3 key={i}>{inline(b.text)}</h3>
              : <h4 key={i}>{inline(b.text)}</h4>;
          }
          case "ul":
            return <ul key={i}>{b.items.map((t, j) => <li key={j}>{inline(t)}</li>)}</ul>;
          case "quote":
            return <blockquote key={i}>{b.lines.map((t, j) => <p key={j}>{inline(t)}</p>)}</blockquote>;
          case "hr":
            return <hr key={i} />;
          default:
            return <p key={i}>{inline(b.text)}</p>;
        }
      })}
    </div>
  );
}
