/**
 * VoiceUserContextMenu — right-click menu for a participant in the
 * voice channel rows on the sidebar. Surfaces:
 *
 *   - Personal volume slider (local, doesn't affect other clients)
 *   - Personal mute toggle (local only)
 *   - Server mute toggle (admins only)
 *   - Disconnect user from the call (admins only)
 *   - View profile (opens the big MemberProfileModal)
 *
 * Reuses `ChannelListContextMenu.module.css` for visual parity with
 * the other context menus in the app. Permissions come from
 * `api.roles.getMyPermissions` so only admins with the right power
 * level see the destructive server-side actions.
 */
import { useEffect, useRef } from 'react';
import { createPortal } from 'react-dom';
import { useQuery } from 'convex/react';
import {
	MicrophoneSlash,
	PhoneDisconnect,
	ShieldCheck,
	SpeakerSlash,
	User as UserIcon,
} from '@phosphor-icons/react';
import { api } from '../../../../../convex/_generated/api';
import type { Id } from '../../../../../convex/_generated/dataModel';
import { useVoice } from '../../contexts/VoiceContext';
import menuStyles from '../layout/ChannelListContextMenu.module.css';

interface VoiceUserContextMenuProps {
	x: number;
	y: number;
	userId: string;
	username: string;
	onViewProfile: () => void;
	onClose: () => void;
}

export function VoiceUserContextMenu({
	x,
	y,
	userId,
	username,
	onViewProfile,
	onClose,
}: VoiceUserContextMenuProps) {
	const ref = useRef<HTMLDivElement>(null);
	const voice = useVoice() as any;

	const localUserId =
		typeof localStorage !== 'undefined' ? localStorage.getItem('userId') : null;
	const myPerms = useQuery(
		api.roles.getMyPermissions,
		localUserId ? { userId: localUserId as Id<'userProfiles'> } : 'skip',
	);
	// Server-side mute / disconnect are gated on `move_members`. If
	// your deployment doesn't expose that flag fall back to `manage_channels`
	// so admins still get the actions — matches the previous behaviour.
	const canModerate =
		!!myPerms?.move_members || !!myPerms?.manage_channels;

	const isSelf = userId === localUserId;
	const personalVolume: number =
		voice?.getUserVolume?.(userId) ?? 100;
	const isPersonallyMuted: boolean = !!voice?.isPersonallyMuted?.(userId);
	const isServerMuted: boolean = !!voice?.isServerMuted?.(userId);

	useEffect(() => {
		const handleClick = (e: MouseEvent) => {
			if (ref.current && !ref.current.contains(e.target as Node)) onClose();
		};
		const handleEsc = (e: KeyboardEvent) => {
			if (e.key === 'Escape') onClose();
		};
		document.addEventListener('mousedown', handleClick);
		document.addEventListener('keydown', handleEsc);
		return () => {
			document.removeEventListener('mousedown', handleClick);
			document.removeEventListener('keydown', handleEsc);
		};
	}, [onClose]);

	// Wider than the default channel-list menu so the volume slider
	// doesn't feel cramped. Clamp to viewport to avoid clipping.
	const WIDTH = 240;
	const HEIGHT_ESTIMATE = 220;
	const style: React.CSSProperties = {
		top: Math.min(y, window.innerHeight - HEIGHT_ESTIMATE),
		left: Math.min(x, window.innerWidth - WIDTH),
		width: WIDTH,
	};

	const handlePersonalMute = () => {
		voice?.togglePersonalMute?.(userId);
	};
	const handleServerMute = async () => {
		await voice?.serverMute?.(userId, !isServerMuted);
		onClose();
	};
	const handleDisconnect = async () => {
		await voice?.disconnectUser?.(userId);
		onClose();
	};

	return createPortal(
		<div className={menuStyles.overlay}>
			<div className={menuStyles.menu} ref={ref} style={style}>
				{/* Username label — read-only, mirrors the "{Member} / Member"
				    header the new UI puts on its context menus. */}
				<div
					style={{
						padding: '10px 14px 4px',
						fontSize: 12,
						fontWeight: 700,
						color: 'var(--text-tertiary, #a0a3a8)',
						textTransform: 'uppercase',
						letterSpacing: '0.04em',
					}}
				>
					{username}
				</div>

				<button
					className={menuStyles.menuItem}
					type="button"
					onClick={() => {
						onViewProfile();
						onClose();
					}}
				>
					<UserIcon size={18} weight="fill" />
					<span>View Profile</span>
				</button>

				{!isSelf && (
					<>
						<div className={menuStyles.separator} />

						<button
							className={menuStyles.menuItem}
							type="button"
							onClick={handlePersonalMute}
						>
							<MicrophoneSlash size={18} weight="fill" />
							<span>{isPersonallyMuted ? 'Unmute' : 'Mute'}</span>
						</button>

						<div
							style={{
								padding: '8px 14px 12px',
								display: 'flex',
								flexDirection: 'column',
								gap: 6,
							}}
						>
							<label
								style={{
									fontSize: 12,
									color: 'var(--text-secondary, #b5bac1)',
								}}
							>
								User Volume · {personalVolume}%
							</label>
							<input
								type="range"
								min={0}
								max={200}
								value={personalVolume}
								onChange={(e) =>
									voice?.setUserVolume?.(userId, Number(e.target.value))
								}
								style={{ width: '100%' }}
							/>
						</div>

						{canModerate && (
							<>
								<div className={menuStyles.separator} />
								<button
									className={menuStyles.menuItem}
									type="button"
									onClick={handleServerMute}
								>
									<SpeakerSlash size={18} weight="fill" />
									<span>
										{isServerMuted ? 'Unmute on Server' : 'Server Mute'}
									</span>
								</button>
								<button
									className={`${menuStyles.menuItem} ${menuStyles.menuItemDanger ?? ''}`}
									type="button"
									onClick={handleDisconnect}
									style={{ color: 'var(--status-danger, #ed4245)' }}
								>
									<PhoneDisconnect size={18} weight="fill" />
									<span>Disconnect</span>
								</button>
							</>
						)}

						{!canModerate && (
							<>
								<div className={menuStyles.separator} />
								<button
									className={menuStyles.menuItem}
									type="button"
									disabled
									title="Requires Move Members permission"
									style={{ opacity: 0.5, cursor: 'not-allowed' }}
								>
									<ShieldCheck size={18} weight="fill" />
									<span>Server Controls</span>
								</button>
							</>
						)}
					</>
				)}
			</div>
		</div>,
		document.body,
	);
}
