import { LinkSelector } from '@/admin/features/activity-editor/selectors/link-selector';
import { NodeSelector } from '@/admin/features/activity-editor/selectors/node-selector';
import { TextButtons } from '@/admin/features/activity-editor/selectors/text-buttons';
import { Separator } from '@/components/ui/separator';
import { __ } from '@wordpress/i18n';
import { Command } from 'cmdk';
import { useState } from 'react';
import {
	EditorBubble,
	EditorCommand,
	EditorCommandEmpty,
	EditorCommandItem,
	EditorCommandList,
	EditorContent,
	type EditorInstance,
	EditorRoot,
	type JSONContent,
	type SuggestionItem,
	handleCommandNavigation,
} from './core';
import { defaultExtensions, dragging } from './extensions';
import { slashCommand, suggestionItems } from './slash-command';

const extensions = [...defaultExtensions, slashCommand];

const GROUP_ORDER = ['Content', 'Input Elements', 'Media Elements'] as const;

const groupedItems = suggestionItems.reduce<Record<string, SuggestionItem[]>>(
	(acc, item) => {
		const key = item.group ?? 'Other';
		(acc[key] ??= []).push(item);
		return acc;
	},
	{},
);

type Props = {
	initialContent?: JSONContent;
	onChange?: (content: JSONContent) => void;
};

export const ActivityEditor = ({ initialContent, onChange }: Props) => {
	const [openNode, setOpenNode] = useState(false);
	const [openLink, setOpenLink] = useState(false);

	const handleCreate = ({ editor }: { editor: EditorInstance }) => {
		const container = editor.view.dom.parentElement;
		if (container && getComputedStyle(container).position === 'static') {
			container.style.position = 'relative';
		}
		requestAnimationFrame(() => {
			if (!editor.isDestroyed) {
				editor.view.dispatch(editor.view.state.tr);
			}
		});
	};

	const handleUpdate = ({ editor }: { editor: EditorInstance }) => {
		onChange?.(editor.getJSON());
	};

	return (
		<div className="h-full w-full">
			<EditorRoot>
				<EditorContent
					initialContent={initialContent}
					extensions={extensions}
					className="h-full w-full"
					onCreate={handleCreate}
					editorProps={{
						handleDOMEvents: {
							keydown: (_view, event) => handleCommandNavigation(event),
						},
						attributes: {
							class:
								'prose prose-lg p-5 pl-10 dark:prose-invert prose-headings:font-title font-default focus:outline-none max-w-full flex flex-col gap-2',
						},
					}}
					onUpdate={handleUpdate}
				>
					<EditorBubble
						appendTo={document.body}
						shouldShow={({ editor, state }) => {
							if (dragging) return false;
							if (!editor.isFocused) return false;
							return !state.selection.empty;
						}}
						className="z-[999999] flex w-fit max-w-[90vw] overflow-hidden rounded-md bg-[#1d2327] text-[#e5e7eb]"
					>
						<NodeSelector open={openNode} onOpenChange={setOpenNode} />
						<Separator orientation="vertical" />
						<LinkSelector open={openLink} onOpenChange={setOpenLink} />
						<Separator orientation="vertical" />
						<TextButtons />
					</EditorBubble>

					<EditorCommand className="z-50 w-[270px] overflow-hidden rounded-[10px] border border-gray-200 bg-white shadow-[0_8px_30px_rgba(0,0,0,0.12)] [&_[cmdk-group-heading]]:px-2.5 [&_[cmdk-group-heading]]:pt-2 [&_[cmdk-group-heading]]:pb-1 [&_[cmdk-group-heading]]:text-[10px] [&_[cmdk-group-heading]]:font-bold [&_[cmdk-group-heading]]:tracking-[0.07em] [&_[cmdk-group-heading]]:text-teal-600 [&_[cmdk-group-heading]]:uppercase">
						{/* Header */}
						<div className="border-b border-gray-100 px-3 py-2.5">
							<span className="text-[10px] font-bold tracking-[0.08em] text-gray-400 uppercase">
								{__('Add a block', 'allcoach')}
							</span>
						</div>

						<EditorCommandEmpty className="py-3.5 text-center text-[13px] text-gray-400">
							{__('No results', 'allcoach')}
						</EditorCommandEmpty>

						<EditorCommandList className="max-h-[320px] overflow-y-auto p-1">
							{GROUP_ORDER.map((group) =>
								groupedItems[group]?.length ? (
									<Command.Group key={group} heading={group}>
										{groupedItems[group].map((item) => (
											<EditorCommandItem
												key={item.title}
												value={item.title}
												onCommand={(val) => item?.command?.(val)}
												className="flex cursor-pointer items-center gap-2.5 rounded-md px-2.5 py-[7px] text-left hover:bg-teal-50 aria-selected:bg-teal-50"
											>
												<div className="flex h-[30px] w-[30px] shrink-0 items-center justify-center rounded-md bg-gray-100 text-gray-500">
													{item.icon}
												</div>
												<div>
													<strong className="block text-xs font-semibold text-gray-900">
														{item.title}
													</strong>
													<span className="text-[11px] text-gray-400">
														{item.description}
													</span>
												</div>
											</EditorCommandItem>
										))}
									</Command.Group>
								) : null,
							)}
						</EditorCommandList>
					</EditorCommand>
				</EditorContent>
			</EditorRoot>
		</div>
	);
};

export default ActivityEditor;
