// Minimal Lexical → React renderer for the node kinds our CMS emits today
// (heading h1-h4, paragraph, list/listitem, link, text, linebreak, plus the
// text-format bitflags). Add cases as new node kinds appear.
//
// Payload's payload-types declare lexical nodes loosely — `children` is
// `unknown` because the type can't enumerate all possible nodes. We cast
// internally and only read fields we know exist for the supported kinds.

import type { JSX } from "react";
import type { LexRoot } from "@/lib/cms";

type AnyNode = {
	type: string;
	tag?: string;
	text?: string;
	format?: number | string;
	children?: AnyNode[];
	fields?: { url?: string; newTab?: boolean; linkType?: string };
};

function renderNodes(nodes: AnyNode[] | undefined): JSX.Element[] {
	return (nodes ?? []).map((n, i) => renderNode(n, i));
}

function renderNode(n: AnyNode, key: number): JSX.Element {
	switch (n.type) {
		case "text": {
			const format = typeof n.format === "number" ? n.format : 0;
			let el: JSX.Element = <>{n.text}</>;
			if (format & 1) el = <strong>{el}</strong>;
			if (format & 2) el = <em>{el}</em>;
			if (format & 8) el = <u>{el}</u>;
			if (format & 16) el = <code>{el}</code>;
			return <span key={key}>{el}</span>;
		}

		case "linebreak":
			return <br key={key} />;

		case "paragraph":
			return <p key={key}>{renderNodes(n.children)}</p>;

		case "heading": {
			const Tag = (n.tag ?? "h2") as keyof JSX.IntrinsicElements;
			return <Tag key={key}>{renderNodes(n.children)}</Tag>;
		}

		case "list": {
			const Tag = n.tag === "ol" ? "ol" : "ul";
			return <Tag key={key}>{renderNodes(n.children)}</Tag>;
		}

		case "listitem":
			return <li key={key}>{renderNodes(n.children)}</li>;

		case "link": {
			const url = n.fields?.url ?? "#";
			const newTab = Boolean(n.fields?.newTab);
			return (
				<a
					key={key}
					href={url}
					{...(newTab
						? { target: "_blank", rel: "noopener noreferrer" }
						: {})}
				>
					{renderNodes(n.children)}
				</a>
			);
		}

		default:
			return <span key={key} />;
	}
}

export default function RichText({
	data,
}: {
	data: LexRoot | null | undefined;
}) {
	if (!data?.root) return null;
	return <>{renderNodes(data.root.children as AnyNode[] | undefined)}</>;
}
