// components/Popover.tsx
import { motion, AnimatePresence } from "framer-motion";
import React, {
	ReactNode,
	useState,
	cloneElement,
	isValidElement,
	ReactElement,
} from "react";

type PopoverPosition = "top" | "bottom" | "left" | "right";
type TriggerType = "hover" | "click" | "focus";

interface PopoverProps {
	title?: string;
	content: ReactNode;
	position?: PopoverPosition;
	trigger?: TriggerType;
	children: ReactNode;
	// 可选的延迟时间（毫秒），用于 hover 模式
	hoverDelay?: number;
}

const positionStyles = {
	top: {
		initial: { opacity: 0, y: 10, scale: 0.95 },
		animate: { opacity: 1, y: 0, scale: 1 },
		className: "bottom-full left-1/2 -translate-x-1/2 mb-2",
	},
	bottom: {
		initial: { opacity: 0, y: -10, scale: 0.95 },
		animate: { opacity: 1, y: 0, scale: 1 },
		className: "top-full left-1/2 -translate-x-1/2 mt-2",
	},
	left: {
		initial: { opacity: 0, x: 10, scale: 0.95 },
		animate: { opacity: 1, x: 0, scale: 1 },
		className: "right-full top-1/2 -translate-y-1/2 mr-2",
	},
	right: {
		initial: { opacity: 0, x: -10, scale: 0.95 },
		animate: { opacity: 1, x: 0, scale: 1 },
		className: "left-full top-1/2 -translate-y-1/2 ml-2",
	},
};

export const Popover: React.FC<PopoverProps> = ({
	title,
	content,
	position = "right",
	trigger = "hover",
	children,
	hoverDelay = 200,
}) => {
	const [isOpen, setIsOpen] = useState(false);
	const [hoverTimeout, setHoverTimeout] = useState<number | null>(null);

	const handleMouseEnter = () => {
		if (trigger === "hover") {
			if (hoverTimeout) window.clearTimeout(hoverTimeout);
			setIsOpen(true);
		}
	};

	const handleMouseLeave = () => {
		if (trigger === "hover") {
			// window.setTimeout 返回 number 类型
			const timeout = window.setTimeout(
				() => setIsOpen(false),
				hoverDelay
			);
			setHoverTimeout(timeout);
		}
	};

	const handleClick = (e: React.MouseEvent) => {
		if (trigger === "click") {
			setIsOpen(!isOpen);
		}
	};

	const handleFocus = () => {
		if (trigger === "focus") {
			setIsOpen(true);
		}
	};

	const handleBlur = () => {
		if (trigger === "focus") {
			setIsOpen(false);
		}
	};

	// 添加类型断言来处理 children 的类型
	const childrenWithProps = isValidElement(children)
		? cloneElement(children as ReactElement<any>, {
				onClick: (e: React.MouseEvent) => {
					handleClick(e);
					const child = children as ReactElement<{
						onClick?: (e: React.MouseEvent) => void;
					}>;
					if (child.props.onClick) {
						child.props.onClick(e);
					}
				},
				onMouseEnter: (e: React.MouseEvent) => {
					handleMouseEnter();
					const child = children as ReactElement<{
						onMouseEnter?: (e: React.MouseEvent) => void;
					}>;
					if (child.props.onMouseEnter) {
						child.props.onMouseEnter(e);
					}
				},
				onMouseLeave: (e: React.MouseEvent) => {
					handleMouseLeave();
					const child = children as ReactElement<{
						onMouseLeave?: (e: React.MouseEvent) => void;
					}>;
					if (child.props.onMouseLeave) {
						child.props.onMouseLeave(e);
					}
				},
				onFocus: (e: React.FocusEvent) => {
					handleFocus();
					const child = children as ReactElement<{
						onFocus?: (e: React.FocusEvent) => void;
					}>;
					if (child.props.onFocus) {
						child.props.onFocus(e);
					}
				},
				onBlur: (e: React.FocusEvent) => {
					handleBlur();
					const child = children as ReactElement<{
						onBlur?: (e: React.FocusEvent) => void;
					}>;
					if (child.props.onBlur) {
						child.props.onBlur(e);
					}
				},
			})
		: children;

	return (
		<div
			className="relative inline-block"
			onMouseEnter={handleMouseEnter}
			onMouseLeave={handleMouseLeave}>
			{childrenWithProps}

			<AnimatePresence>
				{isOpen && (
					<motion.div
						initial={positionStyles[position].initial}
						animate={positionStyles[position].animate}
						exit={{ opacity: 0, scale: 0.95 }}
						transition={{ duration: 0.2, ease: "easeOut" }}
						className={`
              absolute z-50 min-w-[200px] bg-white
              rounded-lg shadow-lg border border-gray-200
              ${positionStyles[position].className}
            `}>
						{title && (
							<div className="px-4 py-2 border-b border-gray-100">
								<h3 className="font-medium text-gray-900">
									{title}
								</h3>
							</div>
						)}
						<div className="p-4">{content}</div>
					</motion.div>
				)}
			</AnimatePresence>
		</div>
	);
};
