"use client";

import { ChevronRight, GripVertical, Loader2, Save } from "lucide-react";
import { AnimatePresence, motion, type Variants } from "motion/react";
import dynamic from "next/dynamic";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { createPortal } from "react-dom";
import { useEditorContext } from "./editor-context";
import { RecoveryBanner } from "./recovery-banner";

// Lazy load EditorPane (includes Monaco) - only loaded when drawer opens
const EditorPane = dynamic(
	() => import("./editor/editor-pane").then((mod) => mod.EditorPane),
	{
		loading: () => (
			<div className="flex h-full items-center justify-center bg-background">
				<Loader2 className="size-6 animate-spin text-muted-foreground" />
			</div>
		),
		ssr: false, // Monaco doesn't work server-side
	},
);

import { Button } from "@mdxui/primitives/button";
import { Kbd } from "@mdxui/primitives/kbd";
import { cn } from "@mdxui/primitives/lib/utils";
import {
	Tooltip,
	TooltipContent,
	TooltipProvider,
	TooltipTrigger,
} from "@mdxui/primitives/tooltip";
import { useIsMobile, usePrefersReducedMotion } from "../hooks/use-media-query";

interface EditorDrawerProps {
	isOpen: boolean;
}

const MIN_WIDTH = 320;
const MIN_CONTENT_WIDTH = 375; // Minimum content area when editor is open
const DEFAULT_WIDTH_PERCENT = 1 / 3; // One-third of screen

function getDefaultWidth() {
	if (typeof window === "undefined") return 500;
	return Math.max(
		MIN_WIDTH,
		Math.floor(window.innerWidth * DEFAULT_WIDTH_PERCENT),
	);
}

export function EditorDrawer({ isOpen }: EditorDrawerProps) {
	// Get shared state from context
	const { path, isDirty, isSaving, onSave, onClose, recovery } =
		useEditorContext();

	const prefersReducedMotion = usePrefersReducedMotion();
	const isMobile = useIsMobile() ?? false;
	const [drawerWidth, setDrawerWidth] = useState(getDefaultWidth);
	const [isResizing, setIsResizing] = useState(false);
	const drawerRef = useRef<HTMLDivElement>(null);

	// Handle escape key
	const handleKeyDown = useCallback(
		(e: KeyboardEvent) => {
			if (e.key === "Escape" && !isResizing && onClose) {
				onClose();
			}
		},
		[onClose, isResizing],
	);

	useEffect(() => {
		if (isOpen) {
			document.addEventListener("keydown", handleKeyDown);
		}
		return () => document.removeEventListener("keydown", handleKeyDown);
	}, [isOpen, handleKeyDown]);

	// Resize handling
	const handleResizeStart = useCallback((e: React.MouseEvent) => {
		e.preventDefault();
		setIsResizing(true);
	}, []);

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

		let rafId: number | null = null;
		let latestX = 0;

		const handleMouseMove = (e: MouseEvent) => {
			latestX = e.clientX;
			if (rafId) return; // Skip if RAF pending
			rafId = requestAnimationFrame(() => {
				const maxWidth = window.innerWidth - MIN_CONTENT_WIDTH;
				const newWidth = window.innerWidth - latestX;
				setDrawerWidth(Math.max(MIN_WIDTH, Math.min(maxWidth, newWidth)));
				rafId = null;
			});
		};

		const handleMouseUp = () => {
			setIsResizing(false);
		};

		document.addEventListener("mousemove", handleMouseMove, { passive: true });
		document.addEventListener("mouseup", handleMouseUp);

		// Add cursor style to body during resize
		document.body.style.cursor = "ew-resize";
		document.body.style.userSelect = "none";

		return () => {
			document.removeEventListener("mousemove", handleMouseMove);
			document.removeEventListener("mouseup", handleMouseUp);
			document.body.style.cursor = "";
			document.body.style.userSelect = "";
			if (rafId) cancelAnimationFrame(rafId);
		};
	}, [isResizing]);

	// Set CSS custom property for drawer width (used by page content to adjust)
	useEffect(() => {
		if (typeof window === "undefined") return;

		const root = document.documentElement;

		if (!isOpen || isMobile) {
			// Reset when drawer closes or on mobile (full-screen overlay)
			root.style.removeProperty("--editor-drawer-width");
			return;
		}

		root.style.setProperty("--editor-drawer-width", `${drawerWidth}px`);

		return () => {
			root.style.removeProperty("--editor-drawer-width");
		};
	}, [isOpen, drawerWidth, isMobile]);

	// Memoized animation variants for slide-in from right
	const drawerVariants = useMemo<Variants>(
		() => ({
			hidden: {
				x: "100%",
			},
			visible: {
				x: 0,
				transition: {
					type: "spring",
					damping: 30,
					stiffness: 300,
					duration: prefersReducedMotion ? 0 : undefined,
				},
			},
			exit: {
				x: "100%",
				transition: {
					type: "spring",
					damping: 30,
					stiffness: 300,
					duration: prefersReducedMotion ? 0 : undefined,
				},
			},
		}),
		[prefersReducedMotion],
	);

	// SSR guard for portal
	if (typeof window === "undefined") return null;

	return createPortal(
		<AnimatePresence>
			{isOpen && (
				<motion.div
					ref={drawerRef}
					variants={drawerVariants}
					initial="hidden"
					animate="visible"
					exit="exit"
					role="dialog"
					aria-modal="true"
					aria-label="Content editor"
					data-editor-drawer-open="true"
					style={isMobile ? undefined : { width: drawerWidth }}
					className={cn(
						"fixed right-0 top-0 z-9999 h-full",
						"flex flex-col",
						"border-l border-border bg-background text-foreground shadow-2xl",
						isResizing && "select-none",
						// Full-screen on mobile
						isMobile && "w-full",
					)}
				>
					{/* Resize handle - hidden on mobile */}
					{!isMobile && (
						// biome-ignore lint/a11y/noStaticElementInteractions: <we need to be able to interact with the resize handle>
						<div
							onMouseDown={handleResizeStart}
							className={cn(
								"absolute left-0 top-0 z-10 h-full w-px cursor-ew-resize",
								"group flex items-center justify-center",
								"hover:bg-primary/10 active:bg-primary/20",
								"transition-colors",
								isResizing && "bg-primary/20",
							)}
						>
							<div
								className={cn(
									"absolute left-0 flex h-10 w-4 -translate-x-1/2 items-center justify-center",
									"rounded-md border border-border bg-card opacity-0 transition-opacity shadow-sm",
									"group-hover:opacity-100",
									isResizing && "opacity-100",
								)}
							>
								<GripVertical className="size-4 text-muted-foreground" />
							</div>
						</div>
					)}

					{/* Header */}
					<TooltipProvider>
						<div className="flex h-12 shrink-0 items-center border-b border-border bg-card px-2">
							{/* Close button - left side */}
							<Tooltip>
								<TooltipTrigger asChild>
									<Button
										variant="ghost"
										size="icon"
										onClick={onClose}
										aria-label="Close editor"
										className="shrink-0"
									>
										<ChevronRight className="size-4" />
									</Button>
								</TooltipTrigger>
								<TooltipContent side="bottom">
									<p className="flex items-center gap-2">
										Close <Kbd>⌘</Kbd>
										<Kbd>I</Kbd>
									</p>
								</TooltipContent>
							</Tooltip>

							{/* File path - center */}
							<span className="flex-1 truncate px-2 font-mono text-sm text-muted-foreground">
								{path || "untitled.mdx"}
							</span>

							{/* Save button - right side */}
							{onSave && (
								<Tooltip>
									<TooltipTrigger asChild>
										<Button
											variant="ghost"
											size="icon"
											onClick={onSave}
											disabled={isSaving || !isDirty}
											className="shrink-0"
											aria-label={
												isSaving
													? "Saving..."
													: isDirty
														? "Save changes"
														: "No changes to save"
											}
										>
											{isSaving ? (
												<Loader2 className="size-4 animate-spin" />
											) : (
												<Save className="size-4" />
											)}
										</Button>
									</TooltipTrigger>
									<TooltipContent side="bottom">
										<p className="flex items-center gap-2">
											Save <Kbd>⌘</Kbd>
											<Kbd>S</Kbd>
										</p>
									</TooltipContent>
								</Tooltip>
							)}
						</div>
					</TooltipProvider>

					{/* Recovery banner - shown when autosaved content is available */}
					{recovery && (
						<RecoveryBanner
							timestamp={recovery.timestamp}
							onRestore={recovery.onRestore}
							onDismiss={recovery.onDismiss}
						/>
					)}

					{/* Editor content - uses EditorContext for state */}
					<div className="flex-1 overflow-hidden">
						<EditorPane hideHeader />
					</div>
				</motion.div>
			)}
		</AnimatePresence>,
		document.body,
	);
}
