import React, { useEffect, useRef, useCallback, useMemo } from "react";
import "@/styles/profile-card.css";

interface ProfileCardProps {
	avatarUrl: string;
	iconUrl?: string;
	grainUrl?: string;
	behindGradient?: string;
	innerGradient?: string;
	showBehindGradient?: boolean;
	className?: string;
	enableTilt?: boolean;
	miniAvatarUrl?: string;
	name?: string;
	title?: string;
	handle?: string;
	status?: string;
	contactText?: string;
	showUserInfo?: boolean;
	onContactClick?: () => void;
}

const DEFAULT_BEHIND_GRADIENT =
	"radial-gradient(farthest-side circle at var(--pointer-x) var(--pointer-y),hsla(266,100%,90%,var(--card-opacity)) 4%,hsla(266,50%,80%,calc(var(--card-opacity)*0.75)) 10%,hsla(266,25%,70%,calc(var(--card-opacity)*0.5)) 50%,hsla(266,0%,60%,0) 100%),radial-gradient(35% 52% at 55% 20%,#00ffaac4 0%,#073aff00 100%),radial-gradient(100% 100% at 50% 50%,#00c1ffff 1%,#073aff00 76%),conic-gradient(from 124deg at 50% 50%,#c137ffff 0%,#07c6ffff 40%,#07c6ffff 60%,#c137ffff 100%)";

const DEFAULT_INNER_GRADIENT =
	"linear-gradient(145deg,#60496e8c 0%,#71C4FF44 100%)";

const ANIMATION_CONFIG = {
	SMOOTH_DURATION: 600,
	INITIAL_DURATION: 1500,
	INITIAL_X_OFFSET: 70,
	INITIAL_Y_OFFSET: 60,
} as const;

const clamp = (value: number, min = 0, max = 100): number =>
	Math.min(Math.max(value, min), max);

const round = (value: number, precision = 3): number =>
	parseFloat(value.toFixed(precision));

const adjust = (
	value: number,
	fromMin: number,
	fromMax: number,
	toMin: number,
	toMax: number
): number =>
	round(toMin + ((toMax - toMin) * (value - fromMin)) / (fromMax - fromMin));

const easeInOutCubic = (x: number): number =>
	x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2;

const ProfileCardComponent: React.FC<ProfileCardProps> = ({
	avatarUrl = "<Placeholder for avatar URL>",
	iconUrl = "<Placeholder for icon URL>",
	grainUrl = "<Placeholder for grain URL>",
	behindGradient,
	innerGradient,
	showBehindGradient = true,
	className = "",
	enableTilt = true,
	miniAvatarUrl,
	name = "Javi A. Torres",
	title = "Software Engineer",
	handle = "javicodes",
	status = "Online",
	contactText = "Contact",
	showUserInfo = true,
	onContactClick,
}) => {
	const wrapRef = useRef<HTMLDivElement>(null);
	const cardRef = useRef<HTMLDivElement>(null);

	const animationHandlers = useMemo(() => {
		if (!enableTilt) return null;

		let rafId: number | null = null;

		const updateCardTransform = (
			offsetX: number,
			offsetY: number,
			card: HTMLElement,
			wrap: HTMLElement
		) => {
			const width = card.clientWidth;
			const height = card.clientHeight;

			const percentX = clamp((100 / width) * offsetX);
			const percentY = clamp((100 / height) * offsetY);

			const centerX = percentX - 50;
			const centerY = percentY - 50;

			const properties = {
				"--pointer-x": `${percentX}%`,
				"--pointer-y": `${percentY}%`,
				"--background-x": `${adjust(percentX, 0, 100, 35, 65)}%`,
				"--background-y": `${adjust(percentY, 0, 100, 35, 65)}%`,
				"--pointer-from-center": `${clamp(
					Math.hypot(percentY - 50, percentX - 50) / 50,
					0,
					1
				)}`,
				"--pointer-from-top": `${percentY / 100}`,
				"--pointer-from-left": `${percentX / 100}`,
				"--rotate-x": `${round(-(centerX / 5))}deg`,
				"--rotate-y": `${round(centerY / 4)}deg`,
			};

			Object.entries(properties).forEach(([property, value]) => {
				wrap.style.setProperty(property, value);
			});
		};

		const createSmoothAnimation = (
			duration: number,
			startX: number,
			startY: number,
			card: HTMLElement,
			wrap: HTMLElement
		) => {
			const startTime = performance.now();
			const targetX = wrap.clientWidth / 2;
			const targetY = wrap.clientHeight / 2;

			const animationLoop = (currentTime: number) => {
				const elapsed = currentTime - startTime;
				const progress = clamp(elapsed / duration);
				const easedProgress = easeInOutCubic(progress);

				const currentX = adjust(easedProgress, 0, 1, startX, targetX);
				const currentY = adjust(easedProgress, 0, 1, startY, targetY);

				updateCardTransform(currentX, currentY, card, wrap);

				if (progress < 1) {
					rafId = requestAnimationFrame(animationLoop);
				}
			};

			rafId = requestAnimationFrame(animationLoop);
		};

		return {
			updateCardTransform,
			createSmoothAnimation,
			cancelAnimation: () => {
				if (rafId) {
					cancelAnimationFrame(rafId);
					rafId = null;
				}
			},
		};
	}, [enableTilt]);

	const handlePointerMove = useCallback(
		(event: PointerEvent) => {
			const card = cardRef.current;
			const wrap = wrapRef.current;

			if (!card || !wrap || !animationHandlers) return;

			const rect = card.getBoundingClientRect();
			animationHandlers.updateCardTransform(
				event.clientX - rect.left,
				event.clientY - rect.top,
				card,
				wrap
			);
		},
		[animationHandlers]
	);

	const handlePointerEnter = useCallback(() => {
		const card = cardRef.current;
		const wrap = wrapRef.current;

		if (!card || !wrap || !animationHandlers) return;

		animationHandlers.cancelAnimation();
		wrap.classList.add("active");
		card.classList.add("active");
	}, [animationHandlers]);

	const handlePointerLeave = useCallback(
		(event: PointerEvent) => {
			const card = cardRef.current;
			const wrap = wrapRef.current;

			if (!card || !wrap || !animationHandlers) return;

			animationHandlers.createSmoothAnimation(
				ANIMATION_CONFIG.SMOOTH_DURATION,
				event.offsetX,
				event.offsetY,
				card,
				wrap
			);
			wrap.classList.remove("active");
			card.classList.remove("active");
		},
		[animationHandlers]
	);

	useEffect(() => {
		if (!enableTilt || !animationHandlers) return;

		const card = cardRef.current;
		const wrap = wrapRef.current;

		if (!card || !wrap) return;

		const pointerMoveHandler = handlePointerMove as EventListener;
		const pointerEnterHandler = handlePointerEnter as EventListener;
		const pointerLeaveHandler = handlePointerLeave as EventListener;

		card.addEventListener("pointerenter", pointerEnterHandler);
		card.addEventListener("pointermove", pointerMoveHandler);
		card.addEventListener("pointerleave", pointerLeaveHandler);

		const initialX = wrap.clientWidth - ANIMATION_CONFIG.INITIAL_X_OFFSET;
		const initialY = ANIMATION_CONFIG.INITIAL_Y_OFFSET;

		animationHandlers.updateCardTransform(initialX, initialY, card, wrap);
		animationHandlers.createSmoothAnimation(
			ANIMATION_CONFIG.INITIAL_DURATION,
			initialX,
			initialY,
			card,
			wrap
		);

		return () => {
			card.removeEventListener("pointerenter", pointerEnterHandler);
			card.removeEventListener("pointermove", pointerMoveHandler);
			card.removeEventListener("pointerleave", pointerLeaveHandler);
			animationHandlers.cancelAnimation();
		};
	}, [
		enableTilt,
		animationHandlers,
		handlePointerMove,
		handlePointerEnter,
		handlePointerLeave,
	]);

	const cardStyle = useMemo(
		() =>
			({
				"--icon": iconUrl ? `url(${iconUrl})` : "none",
				"--grain": grainUrl ? `url(${grainUrl})` : "none",
				"--behind-gradient": showBehindGradient
					? behindGradient ?? DEFAULT_BEHIND_GRADIENT
					: "none",
				"--inner-gradient": innerGradient ?? DEFAULT_INNER_GRADIENT,
			} as React.CSSProperties),
		[iconUrl, grainUrl, showBehindGradient, behindGradient, innerGradient]
	);

	const handleContactClick = useCallback(() => {
		onContactClick?.();
	}, [onContactClick]);

	return (
		<div
			ref={wrapRef}
			className={`pc-card-wrapper ${className}`.trim()}
			style={cardStyle}
		>
			<section ref={cardRef} className="pc-card">
				<div className="pc-inside">
					<div className="pc-shine" />
					<div className="pc-glare" />
					<div className="pc-content pc-avatar-content">
						<img
							className="avatar"
							src={avatarUrl}
							alt={`${name || "User"} avatar`}
							loading="lazy"
							onError={(e) => {
								const target = e.target as HTMLImageElement;
								target.style.display = "none";
							}}
						/>
						{showUserInfo && (
							<div className="pc-user-info">
								<div className="pc-user-details">
									<div className="pc-mini-avatar">
										<img
											src={miniAvatarUrl || avatarUrl}
											alt={`${name || "User"} mini avatar`}
											loading="lazy"
											onError={(e) => {
												const target = e.target as HTMLImageElement;
												target.style.opacity = "0.5";
												target.src = avatarUrl;
											}}
										/>
									</div>
									<div className="pc-user-text">
										<div className="pc-handle">@{handle}</div>
										<div className="pc-status">{status}</div>
									</div>
								</div>
								<button
									className="pc-contact-btn"
									onClick={handleContactClick}
									style={{ pointerEvents: "auto" }}
									type="button"
									aria-label={`Contact ${name || "user"}`}
								>
									{contactText}
								</button>
							</div>
						)}
					</div>
					<div className="pc-content">
						<div className="pc-details">
							<h3>{name}</h3>
							<p>{title}</p>
						</div>
					</div>
				</div>
			</section>
		</div>
	);
};

const ProfileCard = React.memo(ProfileCardComponent);

export default ProfileCard;
