/**
 * PiPOverlay — floating voice-call status widget shown when the user
 * is connected to a voice channel but has navigated to a different
 * channel / DM / route. Presents the channel name, a "Return to
 * channel" button, and a disconnect button. The widget is draggable
 * via pointer events.
 *
 * The new UI's screen-share video PiP required live LiveKit track
 * binding from a MobX store; our Convex/React voice context doesn't
 * expose that the same way, so this is a simpler status widget
 * focused on the common case: "I'm in a call, I want to get back."
 */
import { useCallback, useEffect, useRef, useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import { PhoneDisconnect, ArrowRight } from '@phosphor-icons/react';
import { useVoice } from '../../contexts/VoiceContext';
import styles from './PiPOverlay.module.css';

interface Box {
	x: number;
	y: number;
}

const WIDTH = 260;
const HEIGHT = 96;

function clamp(v: number, min: number, max: number): number {
	return Math.max(min, Math.min(max, v));
}

export function PiPOverlay() {
	const navigate = useNavigate();
	const location = useLocation();
	const voice = useVoice() as any;

	const [box, setBox] = useState<Box>(() => ({
		x: Math.max(16, window.innerWidth - WIDTH - 24),
		y: Math.max(16, window.innerHeight - HEIGHT - 24),
	}));
	const dragRef = useRef<{ startX: number; startY: number; startBox: Box } | null>(null);

	useEffect(() => {
		const handleMove = (e: PointerEvent) => {
			const drag = dragRef.current;
			if (!drag) return;
			const dx = e.clientX - drag.startX;
			const dy = e.clientY - drag.startY;
			setBox({
				x: clamp(drag.startBox.x + dx, 0, window.innerWidth - WIDTH),
				y: clamp(drag.startBox.y + dy, 0, window.innerHeight - HEIGHT),
			});
		};
		const handleUp = () => {
			dragRef.current = null;
		};
		window.addEventListener('pointermove', handleMove);
		window.addEventListener('pointerup', handleUp);
		return () => {
			window.removeEventListener('pointermove', handleMove);
			window.removeEventListener('pointerup', handleUp);
		};
	}, []);

	const startDrag = useCallback(
		(e: React.PointerEvent) => {
			// Don't initiate a drag when the pointer lands on a button.
			const target = e.target as HTMLElement;
			if (target.closest('button')) return;
			e.preventDefault();
			dragRef.current = {
				startX: e.clientX,
				startY: e.clientY,
				startBox: { ...box },
			};
		},
		[box],
	);

	const activeChannelId: string | null = voice?.activeChannelId ?? null;
	const activeChannelName: string | null = voice?.activeChannelName ?? null;

	// Hide the overlay when not in a call or when the user is already
	// looking at the active voice channel.
	if (!activeChannelId) return null;
	const onActiveChannelRoute =
		location.pathname.includes(`/${activeChannelId}`);
	if (onActiveChannelRoute) return null;

	const handleReturn = () => {
		navigate(`/channels/home/${activeChannelId}`);
	};
	const handleDisconnect = () => {
		voice?.disconnect?.();
	};

	return (
		<div
			className={styles.container}
			style={{
				transform: `translate(${box.x}px, ${box.y}px)`,
				width: WIDTH,
				height: HEIGHT,
			}}
			onPointerDown={startDrag}
		>
			<div className={styles.pipContent}>
				<div className={styles.pipLabel}>In voice</div>
				<div className={styles.pipChannel}>
					#{activeChannelName || 'channel'}
				</div>
				<div className={styles.pipActions}>
					<button
						type="button"
						className={styles.pipPrimary}
						onClick={handleReturn}
						aria-label="Return to channel"
					>
						<ArrowRight size={14} weight="bold" />
						<span>Return</span>
					</button>
					<button
						type="button"
						className={styles.pipDanger}
						onClick={handleDisconnect}
						aria-label="Disconnect"
					>
						<PhoneDisconnect size={14} weight="bold" />
					</button>
				</div>
			</div>
		</div>
	);
}
