import { MentionNote, useArk, useSuggestion, useWidget } from "@lume/ark";
import { CancelIcon, LoaderIcon } from "@lume/icons";
import { WIDGET_KIND } from "@lume/utils";
import { NDKKind } from "@nostr-dev-kit/ndk";
import CharacterCount from "@tiptap/extension-character-count";
import Image from "@tiptap/extension-image";
import Mention from "@tiptap/extension-mention";
import Placeholder from "@tiptap/extension-placeholder";
import { EditorContent, useEditor } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import { convert } from "html-to-text";
import { nip19 } from "nostr-tools";
import { useLayoutEffect, useRef, useState } from "react";
import { useNavigate, useSearchParams } from "react-router-dom";
import { toast } from "sonner";
import { MediaUploader, MentionPopup } from "./components";

export function NewPostScreen() {
	const ark = useArk();
	const { addWidget } = useWidget();
	const { suggestion } = useSuggestion();

	const [loading, setLoading] = useState(false);
	const [height, setHeight] = useState(0);
	const [searchParams, setSearchParams] = useSearchParams();

	const navigate = useNavigate();
	const containerRef = useRef(null);
	const editor = useEditor({
		extensions: [
			StarterKit.configure(),
			Placeholder.configure({ placeholder: "Sharing some thoughts..." }),
			Image.configure({
				HTMLAttributes: {
					class:
						"rounded-lg w-full object-cover h-auto max-h-[400px] border border-neutral-200 dark:border-neutral-800 outline outline-1 outline-offset-0 outline-neutral-300 dark:outline-neutral-700",
				},
			}),
			CharacterCount.configure(),
			Mention.configure({
				suggestion,
				// eslint-disable-next-line @typescript-eslint/no-unused-vars
				renderLabel({ options, node }) {
					const npub = nip19.npubEncode(node.attrs.id);
					return `nostr:${npub}`;
				},
			}),
		],
		content: JSON.parse(localStorage.getItem("editor-post") || "{}"),
		editorProps: {
			attributes: {
				class:
					"outline-none prose prose-lg prose-neutral max-w-none select-text whitespace-pre-line break-words dark:prose-invert hover:prose-a:text-blue-500",
			},
		},
		onUpdate: ({ editor }) => {
			const jsonContent = JSON.stringify(editor.getJSON());
			localStorage.setItem("editor-post", jsonContent);
		},
	});

	const submit = async () => {
		try {
			if (!ark.ndk.signer) return navigate("/new/privkey");

			setLoading(true);

			// get plaintext content
			const html = editor.getHTML();
			const serializedContent = convert(html, {
				selectors: [
					{ selector: "a", options: { linkBrackets: false } },
					{ selector: "img", options: { linkBrackets: false } },
				],
			});

			// add reply to tags if present
			const replyTo = searchParams.get("replyTo");
			const rootReplyTo = searchParams.get("rootReplyTo");

			// publish event
			const publish = await ark.createEvent({
				kind: NDKKind.Text,
				tags: [],
				content: serializedContent,
				replyTo,
				rootReplyTo,
			});

			if (publish) {
				toast.success(
					`Broadcasted to ${publish.seens.length} relays successfully.`,
				);

				// update state
				setLoading(false);
				setSearchParams({});

				// open new widget with this event id
				if (!replyTo) {
					addWidget.mutate({
						title: "Thread",
						content: publish.id,
						kind: WIDGET_KIND.thread,
					});
				}

				// reset editor
				editor.commands.clearContent();
				localStorage.setItem("editor-post", "{}");
			}
		} catch (e) {
			setLoading(false);
			toast.error(e);
		}
	};

	useLayoutEffect(() => {
		setHeight(containerRef.current.clientHeight);
	}, []);

	return (
		<div className="flex h-[500px] flex-1 flex-col gap-4">
			<div className="flex-1 overflow-y-auto">
				<div ref={containerRef} style={{ height: `${height}px` }}>
					<EditorContent
						editor={editor}
						spellCheck="false"
						autoComplete="off"
						autoCorrect="off"
						autoCapitalize="off"
					/>
					{searchParams.get("replyTo") && (
						<div className="relative max-w-lg">
							<MentionNote eventId={searchParams.get("replyTo")} />
							<button
								type="button"
								onClick={() => setSearchParams({})}
								className="absolute right-3 top-3 inline-flex h-6 w-6 items-center justify-center rounded bg-neutral-200 px-2 dark:bg-neutral-800"
							>
								<CancelIcon className="h-5 w-5" />
							</button>
						</div>
					)}
				</div>
			</div>
			<div className="inline-flex h-16 w-full items-center justify-between border-t border-neutral-100 bg-neutral-50 dark:border-neutral-900 dark:bg-neutral-950">
				<span className="text-sm font-medium tabular-nums text-neutral-600 dark:text-neutral-400">
					{editor?.storage?.characterCount.characters()} characters
				</span>
				<div className="flex items-center">
					<div className="inline-flex items-center gap-2">
						<MediaUploader editor={editor} />
						<MentionPopup editor={editor} />
					</div>
					<div className="mx-3 h-6 w-px bg-neutral-200 dark:bg-neutral-800" />
					<button
						type="button"
						onClick={() => submit()}
						disabled={editor?.isEmpty}
						className="inline-flex h-9 w-20 items-center justify-center rounded-lg bg-blue-500 px-2 font-medium text-white hover:bg-blue-600 disabled:opacity-50"
					>
						{loading === true ? (
							<LoaderIcon className="h-5 w-5 animate-spin" />
						) : (
							"Post"
						)}
					</button>
				</div>
			</div>
		</div>
	);
}
