// portable-text.jsx — minimal Portable Text → React renderer.
//
// Sanity stores rich text as "Portable Text": a flat array of blocks.
// Text blocks carry a `style` (normal, h2, h3, h4, blockquote) and an
// array of `children` spans, each with `marks`. List items are plain
// blocks with `listItem` ("bullet" | "number") + `level`; consecutive
// list blocks must be grouped into <ul>/<ol> ourselves. Standalone
// images arrive as `{ _type: "image", asset, alt, caption }`.
//
// No @portabletext/react (it needs a bundler) — this hand-rolled version
// covers everything the editor schema (blockContent) can produce.

const PT_MARK_TAG = {
  strong: "strong",
  em: "em",
  code: "code",
  "underline": "u",
  "strike-through": "s",
};

// Render a single span's text wrapped in its decorator marks + link annots.
function renderSpan(span, markDefs, key) {
  const text = span.text || "";
  const marks = span.marks || [];
  let node = text;

  marks.forEach((mark, i) => {
    const tag = PT_MARK_TAG[mark];
    if (tag) {
      node = React.createElement(tag, { key: `${key}-d${i}` }, node);
      return;
    }
    // not a decorator → look it up as an annotation (e.g. link)
    const def = (markDefs || []).find((d) => d._key === mark);
    if (def && def._type === "link" && def.href) {
      const external = /^https?:\/\//.test(def.href);
      node = React.createElement(
        "a",
        {
          key: `${key}-a${i}`,
          href: def.href,
          className: "pt-link",
          ...(external ? { target: "_blank", rel: "noopener noreferrer" } : {}),
        },
        node
      );
    }
  });

  return React.createElement(React.Fragment, { key }, node);
}

function renderTextBlock(block, key) {
  const children = (block.children || []).map((span, i) =>
    renderSpan(span, block.markDefs, `${key}-s${i}`)
  );
  const style = block.style || "normal";

  switch (style) {
    case "h2":
      return <h2 key={key} className="pt-h2">{children}</h2>;
    case "h3":
      return <h3 key={key} className="pt-h3">{children}</h3>;
    case "h4":
      return <h4 key={key} className="pt-h4">{children}</h4>;
    case "blockquote":
      return <blockquote key={key} className="pt-quote">{children}</blockquote>;
    default:
      return <p key={key} className="pt-p">{children}</p>;
  }
}

function renderImage(block, key) {
  const ref = block.asset && block.asset._ref;
  const refUrl = ref && window.__sanity ? window.__sanity.refToUrl(ref) : null;
  // Prefer a Sanity ref; fall back to an expanded asset.url or a direct url.
  const raw = refUrl || (block.asset && block.asset.url) || block.url || null;
  const src = raw && refUrl && window.__sanity
    ? window.__sanity.sized(raw, { w: 1200, q: 80 })
    : raw;
  if (!src) return null;
  return (
    <figure key={key} className="pt-figure">
      <img src={src} alt={block.alt || ""} loading="lazy" />
      {block.caption ? <figcaption className="pt-caption">{block.caption}</figcaption> : null}
    </figure>
  );
}

function PortableText({ value }) {
  if (!Array.isArray(value) || value.length === 0) return null;

  const out = [];
  let i = 0;

  while (i < value.length) {
    const block = value[i];

    // ---- image / unknown non-text blocks ----
    if (block._type === "image") {
      out.push(renderImage(block, block._key || `img-${i}`));
      i++;
      continue;
    }

    // ---- list runs: gather consecutive list items of the same type ----
    if (block._type === "block" && block.listItem) {
      const listType = block.listItem; // "bullet" | "number"
      const items = [];
      while (
        i < value.length &&
        value[i]._type === "block" &&
        value[i].listItem === listType
      ) {
        const li = value[i];
        const liChildren = (li.children || []).map((span, j) =>
          renderSpan(span, li.markDefs, `${li._key || i}-li-s${j}`)
        );
        items.push(
          <li key={li._key || `li-${i}`} className="pt-li">{liChildren}</li>
        );
        i++;
      }
      const Tag = listType === "number" ? "ol" : "ul";
      out.push(
        React.createElement(
          Tag,
          { key: `list-${i}`, className: listType === "number" ? "pt-ol" : "pt-ul" },
          items
        )
      );
      continue;
    }

    // ---- plain text block ----
    if (block._type === "block") {
      out.push(renderTextBlock(block, block._key || `b-${i}`));
      i++;
      continue;
    }

    // unknown block type → skip
    i++;
  }

  return <div className="pt-body">{out}</div>;
}

window.PortableText = PortableText;
