import { activitiesApi } from '@/admin/api/activities';
import ActivityEditor from '@/admin/features/activity-editor';
import { Button } from '@/components/ui/button';
import { Dialog, DialogClose, DialogContent } from '@/components/ui/dialog';
import { Skeleton } from '@/components/ui/skeleton';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import type { JSONContent } from '@tiptap/core';
import { __ } from '@wordpress/i18n';
import { Pencil, X } from 'lucide-react';
import { useEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { toast } from 'sonner';

const EMPTY_DOC: JSONContent = { type: 'doc', content: [] };

// ---------------------------------------------------------------------------
// Core editor
// ---------------------------------------------------------------------------

type ActivityEditorCoreProps = {
	programId: string;
	activityId: string;
	autoFocusTitle?: boolean;
	onSaved?: () => void;
	onCancel?: () => void;
	renderHeader?: (props: {
		title: string;
		onTitleChange: (t: string) => void;
		titleRef: React.RefObject<HTMLInputElement>;
	}) => React.ReactNode;
	renderFooter?: (props: {
		isPending: boolean;
		onSave: () => void;
	}) => React.ReactNode;
};

export const ActivityEditorCore = ({
	programId,
	activityId,
	autoFocusTitle,
	onSaved,
	onCancel,
	renderHeader,
	renderFooter,
}: ActivityEditorCoreProps) => {
	const pid = Number(programId);
	const aid = Number(activityId);
	const queryClient = useQueryClient();

	const { data, isLoading } = useQuery({
		queryKey: ['activity', programId, activityId],
		queryFn: () => activitiesApi.get(pid, aid),
	});

	const [content, setContent] = useState<JSONContent | undefined>(undefined);
	const [title, setTitle] = useState('');
	const titleRef = useRef<HTMLInputElement>(null);

	useEffect(() => {
		if (!data) return;

		const schema = data.schema;
		setContent(
			schema.version === '2.0' && schema.content
				? (schema.content as JSONContent)
				: EMPTY_DOC,
		);
		setTitle((data.settings.title as string | undefined) ?? '');

		if (autoFocusTitle) {
			setTimeout(() => titleRef.current?.focus(), 50);
		}
	}, [data]);

	const saveMutation = useMutation({
		mutationFn: () =>
			activitiesApi.update(pid, aid, {
				schema: { version: '2.0', content: content ?? EMPTY_DOC },
				settings: { ...data?.settings, title },
			}),
		onSuccess: () => {
			queryClient.invalidateQueries({
				queryKey: ['activity', programId, activityId],
			});
			queryClient.invalidateQueries({ queryKey: ['sections', programId] });
			toast.success(__('Activity saved.', 'allcoach'));
			onSaved?.();
		},
		onError: () => toast.error(__('Failed to save activity.', 'allcoach')),
	});

	if (isLoading || content === undefined) {
		return (
			<div className="flex flex-col gap-3 px-6 py-8">
				<Skeleton className="h-9 w-2/3" />
				<Skeleton className="h-px w-full" />
				{[1, 2].map((i) => (
					<Skeleton key={i} className="h-[100px] w-full rounded-[9px]" />
				))}
			</div>
		);
	}

	return (
		<div className="flex flex-1 flex-col overflow-hidden">
			{renderHeader &&
				renderHeader({ title, onTitleChange: setTitle, titleRef })}

			<div className="flex-1 overflow-y-auto px-6 py-8">
				{!renderHeader && (
					<>
						<div className="mb-4 flex items-start">
							<div className="w-[46px] shrink-0" />
							<input
								ref={titleRef}
								value={title}
								onChange={(e) => setTitle(e.target.value)}
								placeholder={__('Activity title…', 'allcoach')}
								spellCheck={false}
								className="flex-1 bg-transparent text-[22px] font-bold text-gray-900 outline-none placeholder:text-gray-300"
							/>
							<div className="w-8 shrink-0" />
						</div>
						<div className="mb-6 flex items-start">
							<div className="w-[46px] shrink-0" />
							<div className="h-px flex-1 bg-[#e8eaec]" />
							<div className="w-8 shrink-0" />
						</div>
					</>
				)}

				<ActivityEditor initialContent={content} onChange={setContent} />
			</div>

			{renderFooter ? (
				renderFooter({
					isPending: saveMutation.isPending,
					onSave: () => saveMutation.mutate(),
				})
			) : (
				<div className="flex items-center justify-end gap-2 border-t border-gray-200 bg-white px-6 py-4">
					{onCancel && (
						<Button
							variant="outline"
							className="cursor-pointer"
							onClick={onCancel}
						>
							{__('Cancel', 'allcoach')}
						</Button>
					)}
					<Button
						className="cursor-pointer bg-teal-600 text-white hover:bg-teal-700"
						disabled={saveMutation.isPending}
						onClick={() => saveMutation.mutate()}
					>
						{saveMutation.isPending
							? __('Saving…', 'allcoach')
							: __('Save Activity', 'allcoach')}
					</Button>
				</div>
			)}
		</div>
	);
};

// ---------------------------------------------------------------------------
// Modal wrapper
// ---------------------------------------------------------------------------

type ActivityEditorModalProps = {
	programId: string;
	activityId: number | null;
	open: boolean;
	onClose: () => void;
	autoFocusTitle?: boolean;
};

export const ActivityEditorModal = ({
	programId,
	activityId,
	open,
	onClose,
	autoFocusTitle,
}: ActivityEditorModalProps) => {
	return (
		<>
			{open &&
				createPortal(
					<div className="fixed inset-0 z-[49] bg-black/20 backdrop-blur-[2px]" />,
					document.body,
				)}
			<Dialog
				open={open}
				modal={false}
				onOpenChange={(v) => {
					if (!v) onClose();
				}}
			>
				<DialogContent
					showCloseButton={false}
					className="flex h-[90vh] max-h-[90vh] w-full flex-col gap-0 overflow-hidden p-0 sm:max-w-[880px]"
					onInteractOutside={(e) => e.preventDefault()}
					onFocusOutside={(e) => e.preventDefault()}
					onEscapeKeyDown={(e) => e.preventDefault()}
				>
					{activityId !== null && (
						<ActivityEditorCore
							programId={programId}
							activityId={String(activityId)}
							autoFocusTitle={autoFocusTitle}
							onSaved={onClose}
							renderHeader={({ title, onTitleChange, titleRef }) => (
								<div className="group/title flex shrink-0 items-center gap-3 border-b border-gray-200 bg-white px-4 py-3">
									<div className="relative flex min-w-0 flex-1 items-center">
										<input
											ref={titleRef}
											value={title}
											onChange={(e) => onTitleChange(e.target.value)}
											placeholder={__('Untitled Activity', 'allcoach')}
											spellCheck={false}
											className="min-w-0 flex-1 rounded-md bg-transparent py-0.5 pr-6 pl-2 text-[14px] font-semibold text-gray-800 outline-none placeholder:font-normal placeholder:text-gray-400 hover:bg-gray-100 focus:bg-gray-100"
										/>
										<Pencil className="pointer-events-none absolute right-1.5 size-3 text-gray-400 opacity-0 transition-opacity group-hover/title:opacity-100" />
									</div>
									<DialogClose className="ml-auto flex size-7 shrink-0 items-center justify-center rounded-md text-gray-400 transition-colors hover:bg-gray-100 hover:text-gray-700">
										<X className="size-4" />
									</DialogClose>
								</div>
							)}
							renderFooter={({ isPending, onSave }) => (
								<div className="flex shrink-0 items-center justify-end gap-2 border-t border-gray-200 bg-white px-6 py-4">
									<Button
										variant="outline"
										className="cursor-pointer"
										onClick={onClose}
									>
										{__('Cancel', 'allcoach')}
									</Button>
									<Button
										className="cursor-pointer bg-teal-600 text-white hover:bg-teal-700"
										disabled={isPending}
										onClick={onSave}
									>
										{isPending
											? __('Saving…', 'allcoach')
											: __('Save Activity', 'allcoach')}
									</Button>
								</div>
							)}
						/>
					)}
				</DialogContent>
			</Dialog>
		</>
	);
};

export default ActivityEditorCore;
