import { useEffect, useMemo, useReducer, useRef } from "react";
import { EditorContent, useEditor } from "@tiptap/react";
import { jsx, jsxs } from "react/jsx-runtime";
import { Bold } from "@tiptap/extension-bold";
import { BulletList } from "@tiptap/extension-bullet-list";
import { Document } from "@tiptap/extension-document";
import { Heading } from "@tiptap/extension-heading";
import { History } from "@tiptap/extension-history";
import { Italic } from "@tiptap/extension-italic";
import { ListItem } from "@tiptap/extension-list-item";
import { Paragraph } from "@tiptap/extension-paragraph";
import { Text } from "@tiptap/extension-text";
import { TextDirection } from "tiptap-text-direction";
//#region src/DefaultToolbar.tsx
const btnStyle = {
	border: "1px solid #ccc",
	background: "transparent",
	borderRadius: 4,
	padding: "2px 8px",
	cursor: "pointer"
};
function ToolbarButton({ label, pressed, onClick, children }) {
	return /* @__PURE__ */ jsx("button", {
		type: "button",
		"aria-label": label,
		"aria-pressed": pressed,
		onClick,
		style: btnStyle,
		children
	});
}
/** Default Bold / Italic / H2 / Bullet-list toolbar. */
function DefaultToolbar({ editor, isBold, isItalic, isH2, isBullet }) {
	return /* @__PURE__ */ jsxs("div", {
		role: "toolbar",
		"aria-label": "Formatting",
		style: {
			display: "flex",
			gap: 4,
			marginBottom: 4
		},
		children: [
			/* @__PURE__ */ jsx(ToolbarButton, {
				label: "Bold",
				pressed: isBold,
				onClick: () => {
					if (editor?.can().toggleBold()) editor.chain().focus().toggleBold().run();
				},
				children: "B"
			}),
			/* @__PURE__ */ jsx(ToolbarButton, {
				label: "Italic",
				pressed: isItalic,
				onClick: () => {
					if (editor?.can().toggleItalic()) editor.chain().focus().toggleItalic().run();
				},
				children: "I"
			}),
			/* @__PURE__ */ jsx(ToolbarButton, {
				label: "Heading 2",
				pressed: isH2,
				onClick: () => {
					if (editor?.can().toggleHeading({ level: 2 })) editor.chain().focus().toggleHeading({ level: 2 }).run();
				},
				children: "H2"
			}),
			/* @__PURE__ */ jsx(ToolbarButton, {
				label: "Bullet list",
				pressed: isBullet,
				onClick: () => {
					if (editor?.can().toggleBulletList()) editor.chain().focus().toggleBulletList().run();
				},
				children: "•"
			})
		]
	});
}
//#endregion
//#region src/extensions.ts
/** Production-proven default set (no StarterKit). */
function createDefaultExtensions() {
	return [
		Document,
		Paragraph,
		Text,
		History,
		Bold,
		Italic,
		Heading.configure({ levels: [1, 2] }),
		BulletList,
		ListItem,
		TextDirection.configure({ types: ["heading", "paragraph"] })
	];
}
//#endregion
//#region src/RichTextEditor.tsx
function useToolbarState(editor) {
	const [, rerender] = useReducer((n) => n + 1, 0);
	useEffect(() => {
		if (!editor) return;
		const update = () => rerender();
		editor.on("selectionUpdate", update);
		editor.on("transaction", update);
		return () => {
			editor.off("selectionUpdate", update);
			editor.off("transaction", update);
		};
	}, [editor]);
	return {
		editor,
		isBold: editor?.isActive("bold") ?? false,
		isItalic: editor?.isActive("italic") ?? false,
		isH2: editor?.isActive("heading", { level: 2 }) ?? false,
		isBullet: editor?.isActive("bulletList") ?? false
	};
}
function sameOptionValue(left, right, seen = /* @__PURE__ */ new WeakMap()) {
	if (Object.is(left, right)) return true;
	if (typeof left !== "object" || left === null || typeof right !== "object" || right === null) return false;
	if (Object.getPrototypeOf(left) !== Object.getPrototypeOf(right)) return false;
	if (seen.get(left) === right) return true;
	seen.set(left, right);
	const leftKeys = Object.keys(left);
	const rightKeys = Object.keys(right);
	if (leftKeys.length !== rightKeys.length) return false;
	return leftKeys.every((key) => Object.prototype.hasOwnProperty.call(right, key) && sameOptionValue(left[key], right[key], seen));
}
function sameExtensionImplementation(left, right) {
	const leftKeys = Object.keys(left);
	const rightKeys = Object.keys(right);
	if (leftKeys.length !== rightKeys.length) return false;
	return leftKeys.every((key) => {
		if (!Object.prototype.hasOwnProperty.call(right, key)) return false;
		const leftValue = Reflect.get(left, key);
		const rightValue = Reflect.get(right, key);
		if (typeof leftValue === "function" || typeof rightValue === "function") return typeof leftValue === "function" && typeof rightValue === "function" && Function.prototype.toString.call(leftValue) === Function.prototype.toString.call(rightValue);
		return sameOptionValue(leftValue, rightValue);
	});
}
function sameExtensionConfig(left, right) {
	if (left === right) return true;
	if (!left || !right || left.extensions.length !== right.extensions.length) return false;
	return left.extensions.every((extension, index) => {
		const candidate = right.extensions[index];
		return candidate !== void 0 && extension.name === candidate.name && sameOptionValue(extension.options, candidate.options) && sameExtensionImplementation(extension.config, candidate.config);
	});
}
function useStableExtensionConfig(config) {
	const stable = useRef(config);
	if (!sameExtensionConfig(stable.current, config)) stable.current = config;
	return stable.current;
}
function RichTextEditor({ value, onChange, dir = "ltr", "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, extensions, readOnly = false, className, renderToolbar }) {
	const stableExtensions = useStableExtensionConfig(extensions);
	const resolvedExtensions = useMemo(() => stableExtensions?.extensions ?? createDefaultExtensions(), [stableExtensions]);
	const onChangeRef = useRef(onChange);
	const synchronizingRef = useRef(false);
	const lastEmittedRef = useRef(null);
	const previousValueRef = useRef(value);
	const [documentRevision, resetDocumentState] = useReducer((revision) => revision + 1, 0);
	onChangeRef.current = onChange;
	const editor = useEditor({
		extensions: resolvedExtensions,
		content: value,
		editable: !readOnly,
		immediatelyRender: false,
		onUpdate: ({ editor: ed }) => {
			if (synchronizingRef.current) return;
			const nextHtml = ed.getHTML();
			lastEmittedRef.current = nextHtml;
			onChangeRef.current(nextHtml);
		},
		editorProps: { attributes: {
			dir,
			role: "textbox",
			"aria-multiline": "true",
			"aria-label": ariaLabel,
			...ariaDescribedBy ? { "aria-describedby": ariaDescribedBy } : {},
			"aria-readonly": String(readOnly)
		} }
	}, [resolvedExtensions, documentRevision]);
	useEffect(() => {
		if (!editor) return;
		const lastEmitted = lastEmittedRef.current;
		const propChanged = value !== previousValueRef.current;
		const acceptedUserEcho = lastEmitted !== null && value === lastEmitted && value === editor.getHTML();
		previousValueRef.current = value;
		if (acceptedUserEcho) {
			lastEmittedRef.current = null;
			return;
		}
		if (lastEmitted === null && !propChanged) return;
		lastEmittedRef.current = null;
		synchronizingRef.current = true;
		try {
			editor.chain().setMeta("addToHistory", false).setContent(value, { emitUpdate: false }).run();
		} finally {
			synchronizingRef.current = false;
		}
		resetDocumentState();
	});
	useEffect(() => {
		if (!editor) return;
		editor.setEditable(!readOnly, false);
	}, [editor, readOnly]);
	useEffect(() => {
		if (!editor) return;
		const root = editor.view.dom;
		root.setAttribute("dir", dir);
		root.setAttribute("aria-label", ariaLabel);
		root.setAttribute("aria-readonly", String(readOnly));
		if (ariaDescribedBy) root.setAttribute("aria-describedby", ariaDescribedBy);
		else root.removeAttribute("aria-describedby");
	}, [
		editor,
		dir,
		ariaLabel,
		ariaDescribedBy,
		readOnly
	]);
	const toolbarState = useToolbarState(editor);
	return /* @__PURE__ */ jsxs("div", {
		className,
		children: [renderToolbar ? renderToolbar(toolbarState) : /* @__PURE__ */ jsx(DefaultToolbar, { ...toolbarState }), /* @__PURE__ */ jsx(EditorContent, { editor })]
	});
}
//#endregion
export { DefaultToolbar, RichTextEditor, createDefaultExtensions };
