import type { ReactNode } from "react";
import { parseInline, parseMarkup, type Align, type Inline } from "@/lib/blocks/markup";

const ALIGN: Record<Align, string> = { left: "text-left", center: "text-center", right: "text-right", justify: "text-justify" };

function renderInline(nodes: Inline[]): ReactNode {
  return nodes.map((n, i) => {
    if (n.t === "text") return n.v;
    if (n.t === "strong") return <strong key={i}>{renderInline(n.c)}</strong>;
    if (n.t === "em") return <em key={i}>{renderInline(n.c)}</em>;
    if (n.t === "u") return <u key={i}>{renderInline(n.c)}</u>;
    if (n.t === "s") return <s key={i}>{renderInline(n.c)}</s>;
    const ext = /^https?:/i.test(n.href) ? { rel: "noopener noreferrer" } : {};
    if (n.t === "btn") return <a key={i} href={n.href} {...ext} className="site-btn mr-2 inline-block rounded-md bg-primary px-4 py-2 text-sm font-semibold text-primary-foreground no-underline hover:opacity-90">{renderInline(n.c)}</a>;
    return (
      <a key={i} href={n.href} className="underline" {...ext}>
        {renderInline(n.c)}
      </a>
    );
  });
}

/** One line of safe markup (bold, italic, underline, strike, links) without paragraph wrappers: used for section and article titles. */
export function InlineMarkup({ text }: { text: string }) {
  return <>{renderInline(parseInline(text))}</>;
}

/** Renders the safe text markup as elements. Used by the public site and the editor preview. */
export function Markup({ text, headingLevel = 3 }: { text: string; headingLevel?: 2 | 3 }) {
  return (
    <>
      {parseMarkup(text).map((b, i) => {
        if (b.t === "p") return <p key={i} className={`mb-4 whitespace-pre-line leading-relaxed ${b.align ? ALIGN[b.align] : ""}`}>{renderInline(b.c)}</p>;
        if (b.t === "h2" || b.t === "h3") {
          const level = Math.max(headingLevel, b.t === "h2" ? 2 : 3);
          const Tag = level === 2 ? "h2" : "h3";
          return <Tag key={i} className={`${level === 2 ? "mb-3 text-2xl font-bold tracking-tight" : "mb-2 text-xl font-semibold"} ${b.align ? ALIGN[b.align] : ""}`}>{renderInline(b.c)}</Tag>;
        }
        if (b.t === "hr") return <hr key={i} className="my-6 border-border" />;
        // eslint-disable-next-line @next/next/no-img-element
        if (b.t === "img") return <img key={i} src={b.src} alt={b.alt} loading="lazy" className="site-img mb-4 h-auto max-w-full rounded-md" />;
        if (b.t === "table") {
          return (
            <div key={i} className="mb-4 overflow-x-auto">
              <table className="w-full border-collapse text-sm">
                {b.header ? <thead><tr>{b.header.map((c, j) => <th key={j} scope="col" className="border border-border bg-muted px-3 py-2 text-left font-semibold">{renderInline(c)}</th>)}</tr></thead> : null}
                <tbody>{b.rows.map((row, ri) => <tr key={ri}>{row.map((c, ci) => <td key={ci} className="border border-border px-3 py-2">{renderInline(c)}</td>)}</tr>)}</tbody>
              </table>
            </div>
          );
        }
        if (!("items" in b)) return null;
        const items: Inline[][] = b.items;
        const Tag = b.t === "ul" ? "ul" : "ol";
        return (
          <Tag key={i} className={Tag === "ul" ? "mb-4 list-disc space-y-1 pl-6" : "mb-4 list-decimal space-y-1 pl-6"}>
            {items.map((it, j) => <li key={j}>{renderInline(it)}</li>)}
          </Tag>
        );
      })}
    </>
  );
}
