/**
 * Node Context Menu Component — v2
 *
 * Touch-first context menu:
 * - Bottom sheet on touch devices (slides up from bottom)
 * - Centered dialog on mouse devices (right-click)
 * - 48px minimum touch targets for menu items
 * - Pointer events instead of mouse events
 * - Swipe-down-to-dismiss gesture area (drag handle)
 */

import React, { useRef } from 'react';
import { useAtomValue, useSetAtom } from 'jotai';
import type { NodeId } from '../core/types';
import { currentGraphIdAtom } from '../core/graph-store';
import { clearSelectionAtom } from '../core/selection-store';
import { primaryInputSourceAtom } from '../core/input-store';
import type { InputSource } from '../core/input-classifier';
import { ContextMenuAction } from './ContextMenuAction';
import { ContextMenuDivider } from './ContextMenuDivider';

// Re-export sub-components
export { ContextMenuAction } from './ContextMenuAction';
export type { ContextMenuActionProps } from './ContextMenuAction';
export { ContextMenuDivider } from './ContextMenuDivider';
export type { ContextMenuDividerProps } from './ContextMenuDivider';

// =============================================================================
// Types
// =============================================================================

/**
 * Context passed to action handlers.
 */
export interface NodeContextMenuContext {
	nodeId: NodeId;
	graphId: string | null;
	closeMenu: () => void;
}

/**
 * A single action in the context menu.
 */
export interface NodeContextMenuAction {
	/** Unique key for the action */
	key: string;
	/** Display label */
	label: string;
	/** Icon element (optional) */
	icon?: React.ReactNode;
	/** Action handler */
	onClick: (ctx: NodeContextMenuContext) => void;
	/** Whether this is a destructive action (shown in red) */
	destructive?: boolean;
	/** Disable the action */
	disabled?: boolean;
}

export interface NodeContextMenuProps {
	/** Whether the menu is open */
	open: boolean;
	/** Callback when open state changes */
	onOpenChange: (open: boolean) => void;
	/** Node ID the menu is for */
	nodeId: NodeId;
	/** Custom actions to show in the menu */
	actions?: NodeContextMenuAction[];
	/** Render function for custom menu content */
	renderContent?: (ctx: NodeContextMenuContext) => React.ReactNode;
	/** Optional: Custom dialog/modal component */
	DialogComponent?: React.ComponentType<{
		open: boolean;
		onOpenChange: (open: boolean) => void;
		children: React.ReactNode;
	}>;
}

// =============================================================================
// Default Dialog — Adaptive (Bottom Sheet on touch, Centered on mouse)
// =============================================================================

const DefaultDialog: React.FC<{
	open: boolean;
	onOpenChange: (open: boolean) => void;
	children: React.ReactNode;
}> = ({ open, onOpenChange, children }) => {
	const inputSource = useAtomValue(primaryInputSourceAtom);
	const isTouchInput = inputSource === 'finger' || inputSource === 'pencil';

	if (!open) return null;

	if (isTouchInput) {
		return (
			<BottomSheet onClose={() => onOpenChange(false)}>
				{children}
			</BottomSheet>
		);
	}

	// Desktop: centered popover
	return (
		<div
			style={{
				position: 'fixed',
				inset: 0,
				zIndex: 9999,
				display: 'flex',
				alignItems: 'center',
				justifyContent: 'center',
				backgroundColor: 'rgba(0, 0, 0, 0.5)',
			}}
			onClick={() => onOpenChange(false)}
		>
			<div
				style={{
					backgroundColor: 'var(--canvas-bg, #1a1a1a)',
					border: '1px solid var(--canvas-border, #333)',
					borderRadius: '8px',
					padding: '8px 0',
					minWidth: '200px',
					maxWidth: '280px',
					boxShadow: '0 4px 20px rgba(0, 0, 0, 0.3)',
				}}
				onClick={(e) => e.stopPropagation()}
				onPointerDown={(e) => e.stopPropagation()}
			>
				{children}
			</div>
		</div>
	);
};

// =============================================================================
// Bottom Sheet (for touch devices)
// =============================================================================

function BottomSheet({
	onClose,
	children,
}: {
	onClose: () => void;
	children: React.ReactNode;
}) {
	const sheetRef = useRef<HTMLDivElement>(null);
	const startYRef = useRef<number | null>(null);
	const DISMISS_THRESHOLD = 60;

	// Close on backdrop tap
	const handleBackdropClick = () => {
		onClose();
	};

	// Swipe-down-to-dismiss
	const handlePointerDown = (e: React.PointerEvent) => {
		startYRef.current = e.clientY;
	};

	const handlePointerMove = (e: React.PointerEvent) => {
		if (startYRef.current === null || !sheetRef.current) return;
		const dy = e.clientY - startYRef.current;
		if (dy > 0) {
			sheetRef.current.style.transform = `translateY(${dy}px)`;
		}
	};

	const handlePointerUp = (e: React.PointerEvent) => {
		if (startYRef.current === null) return;
		const dy = e.clientY - startYRef.current;
		startYRef.current = null;

		if (dy > DISMISS_THRESHOLD) {
			onClose();
		} else if (sheetRef.current) {
			sheetRef.current.style.transform = 'translateY(0)';
		}
	};

	return (
		<div
			style={{
				position: 'fixed',
				inset: 0,
				zIndex: 9999,
				display: 'flex',
				flexDirection: 'column',
				justifyContent: 'flex-end',
				backgroundColor: 'rgba(0, 0, 0, 0.4)',
			}}
			onClick={handleBackdropClick}
		>
			<div
				ref={sheetRef}
				style={{
					backgroundColor: 'var(--canvas-bg, #1a1a1a)',
					borderTop: '1px solid var(--canvas-border, #333)',
					borderRadius: '16px 16px 0 0',
					padding: '0 0 env(safe-area-inset-bottom, 16px)',
					maxHeight: '60vh',
					overflowY: 'auto',
					transition: 'transform 200ms ease-out',
					WebkitOverflowScrolling: 'touch',
				}}
				onClick={(e) => e.stopPropagation()}
				onPointerDown={(e) => {
					e.stopPropagation();
					handlePointerDown(e);
				}}
				onPointerMove={handlePointerMove}
				onPointerUp={handlePointerUp}
				onPointerCancel={(e) => {
					startYRef.current = null;
					if (sheetRef.current) sheetRef.current.style.transform = 'translateY(0)';
				}}
			>
				{/* Drag handle indicator */}
				<div style={{
					display: 'flex',
					justifyContent: 'center',
					padding: '8px 0 4px',
					touchAction: 'none',
				}}>
					<div style={{
						width: '36px',
						height: '4px',
						borderRadius: '2px',
						backgroundColor: 'var(--canvas-border, #666)',
					}} />
				</div>
				{children}
			</div>
		</div>
	);
}

// =============================================================================
// Component
// =============================================================================

/**
 * Context menu for nodes.
 *
 * Adapts to input source:
 * - Touch/pencil → slides up as a bottom sheet (iOS-style)
 * - Mouse → centered dialog (right-click style)
 *
 * @example
 * ```tsx
 * <NodeContextMenu
 *   open={showMenu}
 *   onOpenChange={setShowMenu}
 *   nodeId={nodeId}
 *   actions={[
 *     { key: 'delete', label: 'Delete', destructive: true, onClick: handleDelete },
 *     { key: 'duplicate', label: 'Duplicate', onClick: handleDuplicate },
 *   ]}
 * />
 * ```
 */
export function NodeContextMenu({
	open,
	onOpenChange,
	nodeId,
	actions = [],
	renderContent,
	DialogComponent = DefaultDialog,
}: NodeContextMenuProps) {
	const currentGraphId = useAtomValue(currentGraphIdAtom);
	const clearSelection = useSetAtom(clearSelectionAtom);

	const closeMenu = () => {
		onOpenChange(false);
	};

	const ctx: NodeContextMenuContext = {
		nodeId,
		graphId: currentGraphId,
		closeMenu,
	};

	// If custom content is provided, use that
	if (renderContent) {
		return (
			<DialogComponent open={open} onOpenChange={onOpenChange}>
				{renderContent(ctx)}
			</DialogComponent>
		);
	}

	// Default menu with actions
	return (
		<DialogComponent open={open} onOpenChange={onOpenChange}>
			<ContextMenuDivider label="Node Options" />
			<div style={{ padding: '0 4px' }}>
				{actions.map((action) => (
					<ContextMenuAction
						key={action.key}
						label={action.label}
						icon={action.icon}
						onClick={() => action.onClick(ctx)}
						destructive={action.destructive}
						disabled={action.disabled}
					/>
				))}
			</div>
		</DialogComponent>
	);
}

// =============================================================================
// Default Actions
// =============================================================================

/**
 * Icon for delete action.
 */
export const DeleteIcon = () => (
	<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
		<path strokeLinecap="round" strokeLinejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
	</svg>
);

/**
 * Icon for zoom/fit action.
 */
export const FitToViewIcon = () => (
	<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
		<path strokeLinecap="round" strokeLinejoin="round" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM10 7v3m0 0v3m0-3h3m-3 0H7" />
	</svg>
);
