/**
 * VoiceConnectionStatus — sticky widget above the UserArea showing the
 * current LiveKit connection state when the user is in a voice call.
 * Ported 1:1 from the new UI's layout, adapted for our Convex
 * `VoiceContext`:
 *
 *   ┌─────────────────────────────────────┐
 *   │ 📶  Voice Connected         ⊘ 📞×   │
 *   │ #channel-name                       │
 *   │ 🖥 <participant id>                  │
 *   │ [📷] [🖥]                            │
 *   └─────────────────────────────────────┘
 *
 * Missing pieces (camera toggle, retry/rejoin flow, per-participant
 * signal quality) are stubbed with safe fallbacks since our voice
 * context doesn't model them yet. The screen-share button still
 * works because `VoiceContext.setScreenSharing` is wired.
 */
import { useEffect, useState } from 'react';
import {
	Camera,
	CameraSlash,
	Desktop,
	MonitorPlay,
	PhoneX,
	Record,
	Waveform,
} from '@phosphor-icons/react';
import { useNavigate } from 'react-router-dom';
import { Tooltip } from '@discord-clone/ui';
import { useVoice } from '../../contexts/VoiceContext';
import { usePlatform } from '../../platform';
import { RecordingIndicator } from './RecordingIndicator';
import styles from './VoiceConnectionStatus.module.css';

/**
 * Read the user's saved voice settings (Settings → Voice & Video)
 * from localStorage so we can show a persistent active state on the
 * noise-suppression button. Also re-reads on the change event fired
 * by UserSettingsModal so toggling the setting updates the widget
 * without a reload.
 */
function useVoiceSettingsSnapshot() {
	const [settings, setSettings] = useState<{ noiseSuppression: boolean }>(
		() => readVoiceSettings(),
	);
	useEffect(() => {
		const onChange = (e: Event) => {
			const detail = (e as CustomEvent<{ noiseSuppression?: boolean }>).detail;
			if (detail) setSettings((prev) => ({ ...prev, ...detail }));
			else setSettings(readVoiceSettings());
		};
		window.addEventListener('brycord:voice-settings-changed', onChange);
		return () =>
			window.removeEventListener('brycord:voice-settings-changed', onChange);
	}, []);
	return settings;
}

function readVoiceSettings(): { noiseSuppression: boolean } {
	try {
		const raw = localStorage.getItem('voiceSettings');
		if (!raw) return { noiseSuppression: true };
		const parsed = JSON.parse(raw);
		return {
			noiseSuppression:
				typeof parsed?.noiseSuppression === 'boolean'
					? parsed.noiseSuppression
					: true,
		};
	} catch {
		return { noiseSuppression: true };
	}
}

interface StatusDescriptor {
	text: string;
	className: string;
}

function describeStatus(state: string): StatusDescriptor {
	switch (state) {
		case 'connecting':
			return { text: 'Connecting…', className: styles.statusConnecting };
		case 'reconnecting':
			return { text: 'Reconnecting…', className: styles.statusReconnecting };
		case 'disconnecting':
			return { text: 'Disconnecting…', className: styles.statusConnecting };
		case 'error':
		case 'failed':
			return { text: 'Call failed', className: styles.statusFailed };
		case 'connected':
			return { text: 'Voice Connected', className: '' };
		default:
			return { text: 'Disconnected', className: styles.statusFailed };
	}
}

export function VoiceConnectionStatus() {
	const voice = useVoice() as any;
	const navigate = useNavigate();
	const voiceSettings = useVoiceSettingsSnapshot();
	const platform = usePlatform() as any;
	const canRecord = !!platform?.features?.hasRecording;
	const isRecording = !!voice?.isRecording;

	const handleStartRecording = async () => {
		if (!canRecord) return;
		const ok = window.confirm(
			'Start recording this call?\n\n' +
				'Each participant will be saved to a separate audio file on your computer. ' +
				'You are responsible for obtaining consent from participants where required by law.',
		);
		if (!ok) return;
		try {
			await voice?.startRecording?.();
		} catch (err) {
			console.error('Failed to start recording:', err);
		}
	};

	if (!voice?.activeChannelId) return null;
	const state: string = voice.connectionState || 'disconnected';
	if (state === 'disconnected') return null;

	const channelName: string = voice.activeChannelName || 'Voice Channel';
	const channelId: string = voice.activeChannelId;
	const status = describeStatus(state);
	const isConnected = state === 'connected';

	const screenShareActive: boolean = !!voice.isScreenSharing;
	const cameraActive: boolean = !!voice.isCameraOn;
	const noiseSuppressionActive = voiceSettings.noiseSuppression;

	// Derived participant identity for the connection-id row. Our
	// LiveKit identity is just the Convex user id (no `@user:domain`
	// prefix), so show the trailing 12 chars for a compact display.
	const localIdentity: string | undefined =
		voice.room?.localParticipant?.identity ?? undefined;
	const connectionId = localIdentity ? localIdentity.slice(-12) : null;

	const handleJump = () => {
		navigate(`/channels/home/${channelId}`);
	};

	const handleDisconnect = () => {
		voice.disconnectVoice?.();
	};

	const handleToggleScreenShare = () => {
		voice.setScreenSharing?.(!screenShareActive);
	};

	const handleToggleCamera = () => {
		voice.toggleCamera?.();
	};

	const handleOpenVoiceSettings = () => {
		window.dispatchEvent(
			new CustomEvent('brycord:open-user-settings', {
				detail: { tab: 'voice' },
			}),
		);
	};

	return (
		<div className={styles.voiceConnectionContainer}>
			<div className={styles.statusRow}>
				{isConnected && (
					<div className={styles.signalIcon} title="Connection quality">
						<Waveform size={16} weight="fill" />
					</div>
				)}
				<button
					type="button"
					className={`${styles.statusButton} ${status.className}`}
					onClick={handleJump}
					title={status.text}
				>
					{status.text}
				</button>
				<div className={styles.controls}>
					{canRecord && isConnected && !isRecording && (
						<Tooltip content="Record call" placement="top">
							<button
								type="button"
								className={styles.controlButton}
								onClick={handleStartRecording}
								aria-label="Record call"
							>
								<Record weight="fill" className={styles.icon} />
							</button>
						</Tooltip>
					)}
					{canRecord && isConnected && isRecording && <RecordingIndicator />}
					<Tooltip
						content={
							noiseSuppressionActive
								? 'Noise Suppression · On'
								: 'Noise Suppression · Off'
						}
						placement="top"
					>
						<button
							type="button"
							className={`${styles.controlButton} ${
								noiseSuppressionActive ? styles.controlButtonActive : ''
							}`}
							onClick={handleOpenVoiceSettings}
							aria-label="Noise Suppression"
							aria-pressed={noiseSuppressionActive}
						>
							<Waveform weight="fill" className={styles.icon} />
						</button>
					</Tooltip>
					<Tooltip content="Disconnect" placement="top">
						<button
							type="button"
							className={`${styles.controlButton} ${styles.controlButtonDanger}`}
							onClick={handleDisconnect}
							aria-label="Disconnect"
						>
							<PhoneX weight="fill" className={styles.icon} />
						</button>
					</Tooltip>
				</div>
			</div>

			<div className={styles.connectionInfo}>
				<div className={styles.channelSourceRow}>
					<button
						type="button"
						className={styles.channelSourceLink}
						onClick={handleJump}
						aria-label={`Jump to ${channelName}`}
					>
						<span className={styles.channelSourceText}>
							<span className={styles.channelSourceChannel}>{channelName}</span>
						</span>
					</button>
				</div>
				{connectionId && (
					<div className={styles.connectionIdRow}>
						<Desktop weight="regular" className={styles.connectionIdIcon} />
						<div className={styles.connectionIdValue}>
							<span
								className={styles.connectionIdValueText}
								title={localIdentity}
							>
								{connectionId}
							</span>
						</div>
					</div>
				)}
			</div>

			<div className={styles.mediaSection}>
				<Tooltip
					content={cameraActive ? 'Turn Off Camera' : 'Turn On Camera'}
					placement="top"
				>
					<button
						type="button"
						className={`${styles.mediaButton} ${cameraActive ? styles.cameraActive : ''}`}
						onClick={handleToggleCamera}
						aria-label={cameraActive ? 'Turn Off Camera' : 'Turn On Camera'}
						aria-pressed={cameraActive}
					>
						{cameraActive ? (
							<Camera weight="fill" className={styles.mediaIcon} />
						) : (
							<CameraSlash weight="fill" className={styles.mediaIcon} />
						)}
					</button>
				</Tooltip>
				<Tooltip
					content={screenShareActive ? 'Stop Sharing' : 'Share Your Screen'}
					placement="top"
				>
					<button
						type="button"
						className={`${styles.mediaButton} ${screenShareActive ? styles.screenShareActive : ''}`}
						onClick={handleToggleScreenShare}
						aria-label={screenShareActive ? 'Stop Sharing' : 'Share Your Screen'}
						aria-pressed={screenShareActive}
					>
						<MonitorPlay weight="fill" className={styles.mediaIcon} />
					</button>
				</Tooltip>
			</div>
		</div>
	);
}
