/*! © 2026 Yahoo, Inc. UDS v0.0.0-development */
import { DROP_SHADOW_PREFIX } from "../css-tokens/dist/index.js";
import { parseShadow } from "../utils/parseShadow.js";
import { generateSvgFloatingContentPath, getArrowClampDelta, getArrowSide } from "../utils/svgFloatingContentUtils.js";
import { useCallback, useEffect, useId, useMemo, useRef, useState } from "react";

//#region src/hooks/useSvgFloatingContent.ts
function useSvgFloatingContent({ open, effectivePlacement, borderRadius, arrowRef, animationDuration, hideArrow = false, arrowWidth, arrowHeight, arrowTipRadiusFraction }) {
	const internalRef = useRef(null);
	const shadowFilterId = useId();
	const [dimensions, setDimensions] = useState({
		width: 0,
		height: 0
	});
	useEffect(() => {
		const el = internalRef.current;
		if (!el) return;
		const observer = new ResizeObserver(() => {
			setDimensions({
				width: el.offsetWidth,
				height: el.offsetHeight
			});
		});
		observer.observe(el);
		return () => observer.disconnect();
	}, [open]);
	const [shadows, setShadows] = useState([]);
	const shadowValueRef = useRef("");
	const readShadows = useCallback(() => {
		if (!internalRef.current) return;
		const shadowValue = getComputedStyle(internalRef.current).getPropertyValue(`--${DROP_SHADOW_PREFIX}`);
		if (shadowValue !== shadowValueRef.current) {
			shadowValueRef.current = shadowValue;
			setShadows(parseShadow(shadowValue));
		}
	}, []);
	const shadowPadding = useMemo(() => {
		if (shadows.length === 0) return 0;
		return shadows.reduce((max, s) => {
			const extentX = Math.abs(s.x) + s.blur + Math.abs(s.spread);
			const extentY = Math.abs(s.y) + s.blur + Math.abs(s.spread);
			return Math.max(max, extentX, extentY);
		}, 0);
	}, [shadows]);
	const [arrowCenter, setArrowCenter] = useState(void 0);
	const computeArrowCenter = useCallback(() => {
		const arrowEl = arrowRef.current;
		const el = internalRef.current;
		if (!arrowEl || !el) return;
		const arrowRect = arrowEl.getBoundingClientRect();
		const rect = el.getBoundingClientRect();
		const side = getArrowSide(effectivePlacement);
		const raw = side === "top" || side === "bottom" ? arrowRect.left + arrowRect.width / 2 - rect.left : arrowRect.top + arrowRect.height / 2 - rect.top;
		return Math.round(raw);
	}, [arrowRef, effectivePlacement]);
	const onPositionUpdate = useCallback(async ({ updatePosition }) => {
		await updatePosition();
		const el = internalRef.current;
		if (el) {
			const { offsetWidth, offsetHeight } = el;
			if (offsetWidth > 0 && offsetHeight > 0) setDimensions((prev) => {
				if (prev.width === offsetWidth && prev.height === offsetHeight) return prev;
				return {
					width: offsetWidth,
					height: offsetHeight
				};
			});
			readShadows();
		}
		if (!hideArrow) {
			const next = computeArrowCenter();
			if (next !== void 0) setArrowCenter((prev) => prev === next ? prev : next);
		}
	}, [
		computeArrowCenter,
		readShadows,
		hideArrow
	]);
	const svgPath = useMemo(() => {
		return dimensions.width > 0 && dimensions.height > 0 ? generateSvgFloatingContentPath({
			width: dimensions.width,
			height: dimensions.height,
			placement: effectivePlacement,
			borderRadius,
			arrowCenter: hideArrow ? void 0 : arrowCenter,
			arrowWidth,
			arrowHeight,
			arrowTipRadiusFraction,
			...hideArrow && {
				arrowWidth: 0,
				arrowHeight: 0
			}
		}) : null;
	}, [
		effectivePlacement,
		dimensions.width,
		dimensions.height,
		borderRadius,
		arrowCenter,
		hideArrow,
		arrowWidth,
		arrowHeight,
		arrowTipRadiusFraction
	]);
	const blurClipPath = useMemo(() => {
		if (dimensions.width <= 0 || dimensions.height <= 0) return null;
		if (hideArrow) return generateSvgFloatingContentPath({
			width: dimensions.width,
			height: dimensions.height,
			placement: effectivePlacement,
			borderRadius,
			arrowWidth: 0,
			arrowHeight: 0,
			arrowTipRadiusFraction
		});
		const arrowSide = getArrowSide(effectivePlacement);
		const offsetX = arrowSide === "left" ? arrowHeight : 0;
		const offsetY = arrowSide === "top" ? arrowHeight : 0;
		return generateSvgFloatingContentPath({
			width: dimensions.width,
			height: dimensions.height,
			placement: effectivePlacement,
			borderRadius,
			arrowCenter,
			offsetX,
			offsetY,
			arrowWidth,
			arrowHeight,
			arrowTipRadiusFraction
		});
	}, [
		effectivePlacement,
		dimensions.width,
		dimensions.height,
		borderRadius,
		arrowCenter,
		hideArrow,
		arrowHeight,
		arrowWidth,
		arrowTipRadiusFraction
	]);
	const blurStyle = useMemo(() => {
		const style = {};
		if (blurClipPath && dimensions.width > 0 && dimensions.height > 0) {
			let maskWidth = dimensions.width;
			let maskHeight = dimensions.height;
			if (!hideArrow) {
				const arrowSide = getArrowSide(effectivePlacement);
				if (arrowSide === "top" || arrowSide === "bottom") maskHeight += arrowHeight;
				else maskWidth += arrowHeight;
			}
			const svgMask = `<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 ${maskWidth} ${maskHeight}'><path d='${blurClipPath}' fill='white'/></svg>`;
			const maskUrl = `url("data:image/svg+xml,${encodeURIComponent(svgMask)}")`;
			style.WebkitMaskImage = maskUrl;
			style.maskImage = maskUrl;
			style.WebkitMaskSize = "100% 100%";
			style.maskSize = "100% 100%";
		}
		if (!hideArrow) switch (getArrowSide(effectivePlacement)) {
			case "top":
				style.height = `calc(100% + ${arrowHeight}px)`;
				style.top = "auto";
				style.bottom = "0";
				break;
			case "bottom":
				style.height = `calc(100% + ${arrowHeight}px)`;
				break;
			case "left":
				style.width = `calc(100% + ${arrowHeight}px)`;
				style.left = "auto";
				style.right = "0";
				break;
			case "right":
				style.width = `calc(100% + ${arrowHeight}px)`;
				break;
		}
		return style;
	}, [
		blurClipPath,
		dimensions.width,
		dimensions.height,
		effectivePlacement,
		hideArrow,
		arrowHeight
	]);
	const [visible, setVisible] = useState(false);
	useEffect(() => {
		const raf = requestAnimationFrame(() => {
			setVisible(open && !!svgPath);
		});
		return () => cancelAnimationFrame(raf);
	}, [open, svgPath]);
	return {
		internalRef,
		shadowFilterId,
		dimensions,
		shadows,
		shadowPadding,
		svgPath,
		blurClipPath,
		blurStyle,
		visible,
		childTransitionStyle: {
			opacity: visible ? 1 : 0,
			transition: `opacity ${animationDuration}ms ease-in-out`
		},
		shift: useMemo(() => {
			if (hideArrow || arrowCenter === void 0 || dimensions.width <= 0 || dimensions.height <= 0) return {
				x: 0,
				y: 0
			};
			return getArrowClampDelta({
				width: dimensions.width,
				height: dimensions.height,
				placement: effectivePlacement,
				borderRadius,
				arrowCenter,
				arrowWidth
			});
		}, [
			hideArrow,
			arrowCenter,
			dimensions.width,
			dimensions.height,
			effectivePlacement,
			borderRadius,
			arrowWidth
		]),
		onPositionUpdate
	};
}

//#endregion
export { useSvgFloatingContent };