import { Switch } from '@/components/ui/switch';
import { mergeAttributes, Node } from '@tiptap/core';
import {
	NodeViewWrapper,
	ReactNodeViewRenderer,
	type ReactNodeViewProps,
} from '@tiptap/react';
import { __ } from '@wordpress/i18n';
import { nanoid } from 'nanoid';
import { useEffect, useRef, useState } from 'react';

type Attrs = {
	label: string;
	required: boolean;
};

type AnswerFieldConfig = {
	/** Node name, e.g. 'longAnswer' */
	name: string;
	/** HTML data-type attribute, e.g. 'long-answer' */
	dataType: string;
	/** Badge label shown inside the card, e.g. 'Long Answer' */
	typeLabel: string;
	/** Text shown in the answer preview area, e.g. 'Long answer…' */
	previewText: string;
	/** Insert command name, e.g. 'insertLongAnswer' */
	commandName: string;
	/** Whether the preview area should have a minimum height (multiline) */
	multiline?: boolean;
};

export function createAnswerField({
	name,
	dataType,
	typeLabel,
	previewText,
	commandName,
	multiline = false,
}: AnswerFieldConfig) {
	return Node.create({
		name,
		group: 'block',
		atom: true,
		selectable: true,
		draggable: true,

		addAttributes() {
			return {
				label: { default: '' },
				required: { default: false },
				autoFocus: { default: false, renderHTML: () => ({}) },
				id: { default: nanoid() },
			};
		},

		parseHTML() {
			return [{ tag: `div[data-type="${dataType}"]` }];
		},

		renderHTML({ HTMLAttributes }) {
			return [
				'div',
				mergeAttributes(HTMLAttributes, { 'data-type': dataType }),
			];
		},

		addNodeView() {
			return ReactNodeViewRenderer((props: ReactNodeViewProps) => (
				<AnswerFieldComponent
					{...props}
					typeLabel={typeLabel}
					previewText={previewText}
					multiline={multiline}
				/>
			));
		},

		addCommands() {
			return {
				[commandName]:
					(attrs: Partial<Attrs> = {}) =>
					// eslint-disable-next-line @typescript-eslint/no-explicit-any
					({ chain }: any) =>
						chain()
							.insertContent({
								type: name,
								attrs: {
									label: attrs.label ?? '',
									required: attrs.required ?? false,
									autoFocus: true,
								},
							})
							.run(),
			};
		},
	});
}

type AnswerFieldComponentProps = ReactNodeViewProps & {
	typeLabel: string;
	previewText: string;
	multiline: boolean;
};

function AnswerFieldComponent({
	node,
	updateAttributes,
	typeLabel,
	previewText,
	multiline,
}: AnswerFieldComponentProps) {
	const { label, required, autoFocus } = node.attrs as Attrs & {
		autoFocus: boolean;
	};
	const [attrs, setAttrs] = useState<Attrs>({ label, required });
	const labelRef = useRef<HTMLInputElement>(null);

	useEffect(() => {
		if (autoFocus) {
			labelRef.current?.focus();
			updateAttributes({ autoFocus: false });
		}
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, []);

	return (
		<NodeViewWrapper className="rounded border bg-gray-50 p-3">
			<div className="rounded-[9px] border border-gray-200 bg-white px-4 py-3.5 transition-colors focus-within:border-teal-400">
				<div className="mb-2.5 flex items-center">
					<span className="text-[10px] font-bold tracking-widest text-teal-500 uppercase">
						{typeLabel}
					</span>
					<div className="ml-auto flex items-center gap-1.5">
						<span className="text-[11px] text-gray-400">
							{__('Required?', 'allcoach')}
						</span>
						<Switch
							size="sm"
							checked={attrs.required ?? false}
							onCheckedChange={(v) => {
								setAttrs((prev) => ({ ...prev, required: v }));
								updateAttributes({ required: v });
							}}
						/>
					</div>
				</div>
				<input
					ref={labelRef}
					value={attrs.label}
					onChange={(e) =>
						setAttrs((prev) => ({ ...prev, label: e.target.value }))
					}
					onBlur={() => updateAttributes({ ...attrs })}
					className="w-full border-b border-dashed border-gray-200 bg-transparent pb-1 text-[14px] font-semibold text-gray-800 outline-none placeholder:font-normal placeholder:text-gray-400 focus:border-teal-400"
					placeholder={__('Question…', 'allcoach')}
				/>
				<div
					className={`mt-3 rounded-md border border-gray-100 bg-gray-50 px-3 py-2 text-[13px] text-gray-400${multiline ? 'min-h-[72px]' : ''}`}
				>
					{previewText}
				</div>
			</div>
		</NodeViewWrapper>
	);
}
