"use client";

// Renders a Tiptap JSON document as plain, inert markup — no live NodeViews,
// no side effects. Needed because the real block NodeViews (sub-pages,
// reminders) create real database rows the moment they mount with no linked
// id yet, which must never happen just from opening a preview.

import type { ReactNode } from "react";
import { cn } from "@/lib/utils";
import { getSticker } from "@/lib/notes/note-stickers";

interface TiptapNode {
  type?: string;
  attrs?: Record<string, unknown>;
  content?: TiptapNode[];
  text?: string;
  marks?: Array<{ type: string }>;
}

function renderText(node: TiptapNode, key: number): ReactNode {
  let el: ReactNode = node.text ?? "";
  for (const mark of node.marks || []) {
    if (mark.type === "bold") el = <strong key={key}>{el}</strong>;
    if (mark.type === "italic") el = <em key={key}>{el}</em>;
  }
  return el;
}

function renderInline(nodes: TiptapNode[] | undefined): ReactNode {
  return (nodes || []).map((n, i) => (n.type === "text" ? <span key={i}>{renderText(n, i)}</span> : null));
}

function renderBlock(node: TiptapNode, key: string): ReactNode {
  switch (node.type) {
    case "heading": {
      const level = Math.min((node.attrs?.level as number) || 2, 3);
      return (
        <div
          key={key}
          className={cn(
            "mt-4 first:mt-0 text-white/90",
            level === 1 ? "text-xl font-bold" : level === 2 ? "text-[15px] font-semibold" : "text-[13px] font-semibold",
          )}
        >
          {renderInline(node.content)}
        </div>
      );
    }
    case "paragraph":
      return (
        <p key={key} className="text-[13px] leading-relaxed text-white/60">
          {renderInline(node.content)}
        </p>
      );
    case "bulletList":
    case "orderedList":
      return (
        <ul key={key} className="list-disc space-y-1 pl-5 text-[13px] text-white/60">
          {(node.content || []).map((item, i) => (
            <li key={i}>{renderInline(item.content?.[0]?.content)}</li>
          ))}
        </ul>
      );
    case "taskList":
      return (
        <div key={key} className="space-y-1.5">
          {(node.content || []).map((item, i) => (
            <label key={i} className="flex items-center gap-2 text-[13px] text-white/60">
              <input type="checkbox" checked={!!item.attrs?.checked} readOnly className="rounded border-white/20" />
              {renderInline(item.content?.[0]?.content)}
            </label>
          ))}
        </div>
      );
    case "blockquote":
      return (
        <blockquote key={key} className="border-l-2 border-white/20 pl-3 text-[13px] italic text-white/45">
          {(node.content || []).map((p, i) => renderBlock(p, `${key}-${i}`))}
        </blockquote>
      );
    case "table":
      return (
        <div key={key} className="overflow-x-auto rounded-lg border border-white/10">
          <table className="w-full text-[12px]">
            <tbody>
              {(node.content || []).map((row, ri) => (
                <tr key={ri} className={ri === 0 ? "bg-white/[0.06]" : ""}>
                  {(row.content || []).map((cell, ci) => {
                    const Tag = cell.type === "tableHeader" ? "th" : "td";
                    return (
                      <Tag key={ci} className="border border-white/10 px-2 py-1 text-left align-top text-white/65">
                        {renderInline(cell.content?.[0]?.content)}
                      </Tag>
                    );
                  })}
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      );
    case "actionChecklist": {
      const items = (node.attrs?.items as Array<{ text: string; done: boolean }>) || [];
      return (
        <div key={key} className="space-y-1.5 rounded-lg border border-white/10 bg-white/[0.03] p-3">
          {items.map((item, i) => (
            <label key={i} className="flex items-center gap-2 text-[13px] text-white/60">
              <input type="checkbox" checked={item.done} readOnly className="rounded border-white/20" />
              {item.text}
            </label>
          ))}
          <p className="pt-1 text-[11px] text-white/30">Open the note to turn this into real tasks.</p>
        </div>
      );
    }
    case "chartBlock": {
      const dataSource = node.attrs?.dataSource as { type?: string } | null;
      if (dataSource) {
        return (
          <div key={key} className="rounded-lg border border-sky-500/20 bg-sky-500/[0.05] p-3">
            <p className="mb-1 flex items-center gap-1.5 text-[11px] font-semibold text-sky-400">
              📊 {String(node.attrs?.title || "Live chart")}
            </p>
            <p className="text-[11px] text-white/35">Computed live from your own data once you open the note.</p>
          </div>
        );
      }
      const data = (node.attrs?.data as Array<{ label: string; value: number }>) || [];
      const max = Math.max(1, ...data.map((d) => d.value));
      return (
        <div key={key} className="rounded-lg border border-white/10 bg-white/[0.03] p-3">
          <p className="mb-2 text-[11px] font-semibold text-white/45">{String(node.attrs?.title || "Chart")}</p>
          <div className="flex h-16 items-end gap-1.5">
            {data.map((d, i) => (
              <div
                key={i}
                title={`${d.label}: ${d.value}`}
                className="flex-1 rounded-t bg-sky-400/60"
                style={{ height: `${(d.value / max) * 100}%` }}
              />
            ))}
          </div>
        </div>
      );
    }
    case "noteImage": {
      const src = node.attrs?.src as string | null;
      if (!src) return null;
      // eslint-disable-next-line @next/next/no-img-element
      return <img key={key} src={src} alt={(node.attrs?.alt as string) || ""} className="max-h-48 w-full rounded-lg object-cover" />;
    }
    case "stickerBlock": {
      const sticker = getSticker(node.attrs?.stickerId as string);
      return (
        <span key={key} className="inline-block text-2xl">
          {sticker.emoji}
        </span>
      );
    }
    case "noteLink":
      return (
        <div key={key} className="rounded-lg border border-white/10 bg-white/[0.03] px-3 py-2 text-[12.5px] text-white/50">
          🔗 Linked sub-page
        </div>
      );
    case "reminderBlock":
      return (
        <div key={key} className="rounded-lg border border-white/10 bg-white/[0.03] px-3 py-2 text-[12.5px] text-white/50">
          ⏰ Reminder
        </div>
      );
    default:
      return null;
  }
}

export function TemplateContentPreview({ content }: { content: Record<string, unknown> }) {
  const nodes = (content?.content as TiptapNode[]) || [];
  return <div className="space-y-2.5">{nodes.map((node, i) => renderBlock(node, `n-${i}`))}</div>;
}
