import { useEffect, useRef, useState } from 'react';
import { useQuery } from 'convex/react';
import { Gear, Microphone, MicrophoneSlash, SpeakerHigh, SpeakerSlash } from '@phosphor-icons/react';
import { Avatar, Tooltip } from '@discord-clone/ui';
import { useVoice } from '../../contexts/VoiceContext';
import { useOnlineUsers } from '../../contexts/PresenceContext';
import { useKeybinds } from '../../contexts/KeybindContext';
import { api } from '../../../../../convex/_generated/api';
import { UserAreaProfilePopout } from './UserAreaProfilePopout';
import { VoiceConnectionStatus } from '../voice/VoiceConnectionStatus';
import styles from './UserArea.module.css';

/**
 * UserArea — bottom of the sidebar. Shows the signed-in user's avatar,
 * display name, and mic/speaker/settings controls. Clicking the user
 * info area opens the UserAreaProfilePopout. The gear button dispatches
 * `brycord:open-user-settings` (the settings modal is mounted higher
 * up in the tree).
 */
export function UserArea() {
	const userId = typeof localStorage !== 'undefined' ? localStorage.getItem('userId') : null;
	const username = typeof localStorage !== 'undefined' ? localStorage.getItem('username') : null;
	const allUsers = useQuery(api.auth.getPublicKeys) ?? [];
	const me = allUsers.find((u) => u.id === userId);
	const voice = useVoice();
	const keybinds = useKeybinds();

	const userInfoRef = useRef<HTMLButtonElement>(null);
	const [popoutAnchor, setPopoutAnchor] = useState<DOMRect | null>(null);

	const displayName = me?.displayName || username || 'User';
	const avatarUrl = me?.avatarUrl || null;
	// The current user is always "online" to themselves unless they
	// have a stored status — invisible users should see their own dot
	// as invisible so the setting reflects their actual choice.
	const { resolveStatus } = useOnlineUsers();
	const storedStatus = me?.status || 'online';
	const status = userId ? resolveStatus(storedStatus, userId) : storedStatus;

	const isMuted = voice?.isMuted ?? false;
	const isDeafened = voice?.isDeafened ?? false;

	const handleToggleMute = () => voice?.toggleMute?.();
	const handleToggleDeafen = () => voice?.toggleDeafen?.();
	const openUserSettings = () => {
		window.dispatchEvent(new CustomEvent('brycord:open-user-settings'));
	};

	// Wire the voice keybinds — they're dispatched globally by
	// KeybindProvider and picked up here where the mute/deafen state
	// actually lives.
	useEffect(() => {
		const onMute = () => voice?.toggleMute?.();
		const onDeafen = () => voice?.toggleDeafen?.();
		const onDisconnect = () => voice?.disconnect?.();
		window.addEventListener('brycord:keybind:voice.toggleMute', onMute);
		window.addEventListener('brycord:keybind:voice.toggleDeafen', onDeafen);
		window.addEventListener('brycord:keybind:voice.disconnect', onDisconnect);
		return () => {
			window.removeEventListener('brycord:keybind:voice.toggleMute', onMute);
			window.removeEventListener('brycord:keybind:voice.toggleDeafen', onDeafen);
			window.removeEventListener(
				'brycord:keybind:voice.disconnect',
				onDisconnect,
			);
		};
	}, [voice]);

	const handleOpenPopout = () => {
		if (userInfoRef.current) {
			setPopoutAnchor(userInfoRef.current.getBoundingClientRect());
		}
	};

	return (
		<div className={styles.wrapper}>
			<VoiceConnectionStatus />
			<div className={styles.container}>
				<button
					ref={userInfoRef}
					className={styles.userInfo}
					type="button"
					onClick={handleOpenPopout}
				>
					<Avatar src={avatarUrl} size={32} fallback={displayName} status={mapAvatarStatus(status)} />
					<div className={styles.nameBlock}>
						<span className={styles.displayName}>{displayName}</span>
						<span className={styles.status}>{presenceLabel(status)}</span>
					</div>
				</button>

				<div className={styles.controls}>
					<Tooltip
						content={isMuted ? 'Unmute' : 'Mute'}
						shortcut={keybinds.getCombo('voice.toggleMute')}
						placement="top"
					>
						<button
							type="button"
							className={`${styles.controlButton} ${isMuted ? styles.controlButtonActive : ''}`}
							onClick={handleToggleMute}
							aria-label={isMuted ? 'Unmute' : 'Mute'}
						>
							{isMuted ? <MicrophoneSlash size={20} /> : <Microphone size={20} />}
						</button>
					</Tooltip>
					<Tooltip
						content={isDeafened ? 'Undeafen' : 'Deafen'}
						shortcut={keybinds.getCombo('voice.toggleDeafen')}
						placement="top"
					>
						<button
							type="button"
							className={`${styles.controlButton} ${isDeafened ? styles.controlButtonActive : ''}`}
							onClick={handleToggleDeafen}
							aria-label={isDeafened ? 'Undeafen' : 'Deafen'}
						>
							{isDeafened ? <SpeakerSlash size={20} /> : <SpeakerHigh size={20} />}
						</button>
					</Tooltip>
					<Tooltip
						content="User Settings"
						shortcut={keybinds.getCombo('popouts.openUserSettings')}
						placement="top"
					>
						<button
							type="button"
							className={styles.controlButton}
							onClick={openUserSettings}
							aria-label="User Settings"
						>
							<Gear size={20} />
						</button>
					</Tooltip>
				</div>
			</div>

			{popoutAnchor && (
				<UserAreaProfilePopout
					anchorRect={popoutAnchor}
					onClose={() => setPopoutAnchor(null)}
					onEditProfile={openUserSettings}
				/>
			)}
		</div>
	);
}

function mapAvatarStatus(status: string): 'online' | 'idle' | 'dnd' | 'offline' {
	switch (status) {
		case 'online':
			return 'online';
		case 'idle':
			return 'idle';
		case 'dnd':
			return 'dnd';
		default:
			return 'offline';
	}
}

function presenceLabel(presence: string): string {
	switch (presence) {
		case 'online':
			return 'Online';
		case 'idle':
			return 'Idle';
		case 'dnd':
			return 'Do Not Disturb';
		case 'offline':
		case 'invisible':
			return 'Invisible';
		default:
			return 'Online';
	}
}
