"use client";

import { Button } from "@mdxui/primitives/button";
import { Card } from "@mdxui/primitives/card";
import { cn } from "@mdxui/primitives/lib/utils";
import Placeholder from "@tiptap/extension-placeholder";
import { type Editor, EditorContent, useEditor } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import {
	Code,
	Heading1,
	Heading2,
	Heading3,
	List,
	ListOrdered,
	Quote,
	Type,
} from "lucide-react";
import type React from "react";
import { useState } from "react";

export interface BlockEditorProps {
	/** Initial JSON content */
	initialValue?: any;
	/** Callback when content changes */
	onChange?: (json: any) => void;
	/** Placeholder text */
	placeholder?: string;
	/** Height of the editor */
	height?: string | number;
	/** Additional CSS class */
	className?: string;
	/** Whether the editor is read-only */
	readOnly?: boolean;
	/** Available block types */
	availableBlocks?: BlockType[];
}

export type BlockType =
	| "paragraph"
	| "heading1"
	| "heading2"
	| "heading3"
	| "bulletList"
	| "orderedList"
	| "quote"
	| "code"
	| "image";

interface BlockMenuItem {
	type: BlockType;
	label: string;
	icon: React.ReactNode;
	action: (editor: Editor) => void;
}

const getBlockMenuItems = (_editor: Editor): BlockMenuItem[] => [
	{
		type: "paragraph",
		label: "Text",
		icon: <Type className="h-4 w-4" />,
		action: (e) => e.chain().focus().setParagraph().run(),
	},
	{
		type: "heading1",
		label: "Heading 1",
		icon: <Heading1 className="h-4 w-4" />,
		action: (e) => e.chain().focus().setHeading({ level: 1 }).run(),
	},
	{
		type: "heading2",
		label: "Heading 2",
		icon: <Heading2 className="h-4 w-4" />,
		action: (e) => e.chain().focus().setHeading({ level: 2 }).run(),
	},
	{
		type: "heading3",
		label: "Heading 3",
		icon: <Heading3 className="h-4 w-4" />,
		action: (e) => e.chain().focus().setHeading({ level: 3 }).run(),
	},
	{
		type: "bulletList",
		label: "Bullet List",
		icon: <List className="h-4 w-4" />,
		action: (e) => e.chain().focus().toggleBulletList().run(),
	},
	{
		type: "orderedList",
		label: "Numbered List",
		icon: <ListOrdered className="h-4 w-4" />,
		action: (e) => e.chain().focus().toggleOrderedList().run(),
	},
	{
		type: "quote",
		label: "Quote",
		icon: <Quote className="h-4 w-4" />,
		action: (e) => e.chain().focus().toggleBlockquote().run(),
	},
	{
		type: "code",
		label: "Code",
		icon: <Code className="h-4 w-4" />,
		action: (e) => e.chain().focus().toggleCodeBlock().run(),
	},
];

const BlockMenu: React.FC<{
	editor: Editor;
	onClose: () => void;
	availableBlocks?: BlockType[];
}> = ({ editor, onClose, availableBlocks }) => {
	const items = getBlockMenuItems(editor).filter(
		(item) => !availableBlocks || availableBlocks.includes(item.type),
	);

	return (
		<div className="absolute left-0 top-full z-50 mt-1 w-64 rounded-md border border-border bg-background shadow-lg">
			<div className="p-2">
				<div className="mb-2 text-xs font-medium text-muted-foreground">
					Turn into
				</div>
				<div className="space-y-1">
					{items.map((item) => (
						<Button
							key={item.type}
							variant="ghost"
							size="sm"
							className="w-full justify-start"
							onClick={() => {
								item.action(editor);
								onClose();
							}}
						>
							<span className="mr-2">{item.icon}</span>
							{item.label}
						</Button>
					))}
				</div>
			</div>
		</div>
	);
};

export const BlockEditor: React.FC<BlockEditorProps> = ({
	initialValue,
	onChange,
	placeholder = "Type '/' for commands...",
	height = 600,
	className,
	readOnly = false,
	availableBlocks,
}) => {
	const [showMenu, setShowMenu] = useState(false);

	const editor = useEditor({
		extensions: [
			StarterKit.configure({
				heading: {
					levels: [1, 2, 3],
				},
			}),
			Placeholder.configure({
				placeholder: ({ node }) => {
					if (node.type.name === "heading") {
						return `Heading ${node.attrs.level}`;
					}
					return placeholder;
				},
				showOnlyWhenEditable: true,
			}),
		],
		content: initialValue,
		editable: !readOnly,
		onUpdate: ({ editor }) => {
			const json = editor.getJSON();
			onChange?.(json);
		},
		editorProps: {
			attributes: {
				class: cn(
					"prose prose-sm max-w-none focus:outline-none dark:prose-invert",
					"[&_*]:relative [&_*]:group",
				),
			},
			handleDOMEvents: {
				keydown: (_view, event) => {
					// Show menu on '/'
					if (event.key === "/" && !showMenu) {
						setShowMenu(true);
						return true;
					}
					// Hide menu on escape
					if (event.key === "Escape" && showMenu) {
						setShowMenu(false);
						return true;
					}
					return false;
				},
			},
		},
	});

	if (!editor) {
		return null;
	}

	return (
		<Card className={cn("relative overflow-hidden", className)}>
			<div className="border-b border-border p-2">
				<div className="text-sm text-muted-foreground">
					Press <kbd className="rounded bg-muted px-1.5 py-0.5 text-xs">/</kbd>{" "}
					for commands
				</div>
			</div>
			<div
				className="relative pl-12"
				style={{
					height: typeof height === "number" ? `${height}px` : height,
					overflowY: "auto",
				}}
			>
				<EditorContent editor={editor} className="p-4" />
				{showMenu && (
					<BlockMenu
						editor={editor}
						onClose={() => setShowMenu(false)}
						availableBlocks={availableBlocks}
					/>
				)}
			</div>
		</Card>
	);
};
