import { Fragment, ReactNode } from "react";
import { SanityPortableTextBlock, SanityPortableTextMarkDef, SanityPortableTextSpan } from "@/lib/sanity/queries";

type Props = {
  text?: string | null;
  richBlocks?: SanityPortableTextBlock[] | null;
};

function renderSpan(span: SanityPortableTextSpan, markDefs: SanityPortableTextMarkDef[], key: string): ReactNode {
  const text = span.text || "";
  const marks = Array.isArray(span.marks) ? span.marks : [];
  const textWithBreaks = text.split("\n").map((part, index) => (
    <Fragment key={`${key}-part-${index}`}>
      {index > 0 ? <br /> : null}
      {part}
    </Fragment>
  ));

  if (!marks.length) {
    return <Fragment key={key}>{textWithBreaks}</Fragment>;
  }

  const content = marks.reduce<ReactNode>((acc, mark) => {
    if (mark === "strong") return <strong>{acc}</strong>;
    if (mark === "em") return <em>{acc}</em>;
    if (mark === "underline") return <span className="underline underline-offset-2">{acc}</span>;
    if (mark === "code") return <code className="rounded bg-black/5 px-1 py-0.5 font-mono text-[0.92em]">{acc}</code>;

    const linkDef = markDefs.find((def) => def._key === mark && def._type === "link");
    if (linkDef?.href) {
      return (
        <a href={linkDef.href} target="_blank" rel="noreferrer noopener" className="underline underline-offset-2">
          {acc}
        </a>
      );
    }

    return acc;
  }, textWithBreaks);

  return <Fragment key={key}>{content}</Fragment>;
}

function renderBlockContent(block: SanityPortableTextBlock, keyPrefix: string) {
  const children = Array.isArray(block.children) ? block.children : [];
  const markDefs = Array.isArray(block.markDefs) ? block.markDefs : [];
  return children.map((child, childIndex) => renderSpan(child, markDefs, `${keyPrefix}-${child._key || childIndex}`));
}

function renderParagraphBlock(block: SanityPortableTextBlock, key: string) {
  const style = block.style || "normal";
  const content = renderBlockContent(block, key);

  if (style === "h2") return <h2 key={key} className="mt-5 text-2xl font-semibold text-[var(--foreground)]">{content}</h2>;
  if (style === "h3") return <h3 key={key} className="mt-4 text-xl font-semibold text-[var(--foreground)]">{content}</h3>;
  if (style === "blockquote") return <blockquote key={key} className="border-l-4 border-[var(--line)] pl-4 italic">{content}</blockquote>;
  return <p key={key}>{content}</p>;
}

function renderRichBlocks(blocks: SanityPortableTextBlock[]) {
  const nodes: ReactNode[] = [];
  let index = 0;

  while (index < blocks.length) {
    const block = blocks[index];
    const key = block._key || `block-${index}`;

    if (!block.listItem) {
      nodes.push(renderParagraphBlock(block, key));
      index += 1;
      continue;
    }

    const listType = block.listItem;
    const level = block.level || 1;
    const listItems: SanityPortableTextBlock[] = [];

    while (index < blocks.length) {
      const candidate = blocks[index];
      if (candidate.listItem !== listType || (candidate.level || 1) !== level) {
        break;
      }
      listItems.push(candidate);
      index += 1;
    }

    const Tag = listType === "number" ? "ol" : "ul";
    nodes.push(
      <Tag key={`list-${key}`} className={listType === "number" ? "list-decimal space-y-2 pl-6" : "list-disc space-y-2 pl-6"}>
        {listItems.map((item, itemIndex) => {
          const itemKey = item._key || `${key}-item-${itemIndex}`;
          return <li key={itemKey}>{renderBlockContent(item, itemKey)}</li>;
        })}
      </Tag>,
    );
  }

  return nodes;
}

export function ProductDescription({ text, richBlocks }: Props) {
  const blocks = Array.isArray(richBlocks)
    ? richBlocks.filter((item) => item && item._type === "block")
    : [];
  const fallback = (text || "").trim();

  if (!blocks.length) {
    return <div className="whitespace-pre-line leading-8 text-[var(--muted)]">{fallback}</div>;
  }

  return <div className="space-y-4 leading-8 text-[var(--muted)]">{renderRichBlocks(blocks)}</div>;
}
