/**
 * KeybindsTab — the Keybinds page inside User Settings. Lists every
 * action from KeybindContext grouped by category. Each row shows the
 * current combo as a button; clicking it opens an inline recorder that
 * captures the next keydown and saves the result.
 */
import { useEffect, useRef, useState } from 'react';
import { Button } from '@discord-clone/ui';
import {
	eventToCombo,
	formatCombo,
	useKeybinds,
	type KeybindAction,
	type KeybindCategory,
} from '../../contexts/KeybindContext';
import styles from './KeybindsTab.module.css';

const CATEGORY_ORDER: KeybindCategory[] = [
	'voice',
	'navigation',
	'popouts',
	'messaging',
];

const CATEGORY_LABELS: Record<KeybindCategory, string> = {
	voice: 'Voice',
	navigation: 'Navigation',
	popouts: 'Popouts',
	messaging: 'Messaging',
};

export function KeybindsTab() {
	const keybinds = useKeybinds();
	const [recordingId, setRecordingId] = useState<string | null>(null);

	const actionsByCategory = new Map<KeybindCategory, KeybindAction[]>();
	for (const action of keybinds.actions) {
		const bucket = actionsByCategory.get(action.category) ?? [];
		bucket.push(action);
		actionsByCategory.set(action.category, bucket);
	}

	return (
		<div>
			<div className={styles.header}>
				<div>
					<h3 className={styles.heading}>Keybinds</h3>
					<p className={styles.description}>
						Customize keyboard shortcuts. Click a combo to rebind, or reset
						to defaults.
					</p>
				</div>
				<Button
					variant="secondary"
					size="sm"
					onClick={() => keybinds.resetAll()}
				>
					Reset All
				</Button>
			</div>

			{CATEGORY_ORDER.map((category) => {
				const actions = actionsByCategory.get(category);
				if (!actions || actions.length === 0) return null;
				return (
					<div key={category}>
						<div className={styles.categoryTitle}>
							{CATEGORY_LABELS[category]}
						</div>
						{actions.map((action) => (
							<KeybindRow
								key={action.id}
								action={action}
								isRecording={recordingId === action.id}
								onStartRecording={() => setRecordingId(action.id)}
								onStopRecording={() => setRecordingId(null)}
							/>
						))}
					</div>
				);
			})}
		</div>
	);
}

interface KeybindRowProps {
	action: KeybindAction;
	isRecording: boolean;
	onStartRecording: () => void;
	onStopRecording: () => void;
}

function KeybindRow({
	action,
	isRecording,
	onStartRecording,
	onStopRecording,
}: KeybindRowProps) {
	const keybinds = useKeybinds();
	const currentCombo = keybinds.getCombo(action.id);
	const isDefault = currentCombo === action.defaultCombo;

	return (
		<div className={styles.row}>
			<div className={styles.rowLabel}>
				<span className={styles.rowName}>{action.label}</span>
				<span className={styles.rowDescription}>{action.description}</span>
			</div>
			{isRecording ? (
				<KeybindRecorder
					action={action}
					onSave={(combo) => {
						keybinds.setCombo(action.id, combo);
						onStopRecording();
					}}
					onCancel={onStopRecording}
				/>
			) : (
				<>
					<button
						type="button"
						className={`${styles.comboButton} ${!currentCombo ? styles.comboButtonEmpty : ''}`}
						onClick={onStartRecording}
					>
						{formatCombo(currentCombo)}
					</button>
					<button
						type="button"
						className={styles.resetButton}
						disabled={isDefault}
						onClick={() => keybinds.resetCombo(action.id)}
					>
						Reset
					</button>
				</>
			)}
		</div>
	);
}

interface KeybindRecorderProps {
	action: KeybindAction;
	onSave: (combo: string) => void;
	onCancel: () => void;
}

function KeybindRecorder({ action, onSave, onCancel }: KeybindRecorderProps) {
	const keybinds = useKeybinds();
	const [captured, setCaptured] = useState<string>('');
	const containerRef = useRef<HTMLDivElement>(null);

	useEffect(() => {
		containerRef.current?.focus();
	}, []);

	useEffect(() => {
		const onKeyDown = (e: KeyboardEvent) => {
			if (e.key === 'Escape') {
				e.preventDefault();
				e.stopPropagation();
				onCancel();
				return;
			}
			const combo = eventToCombo(e);
			if (!combo) return;
			e.preventDefault();
			e.stopPropagation();
			setCaptured(combo);
		};
		window.addEventListener('keydown', onKeyDown, { capture: true });
		return () => {
			window.removeEventListener('keydown', onKeyDown, {
				capture: true,
			} as EventListenerOptions);
		};
	}, [onCancel]);

	const conflictId = captured ? keybinds.findConflict(captured, action.id) : null;
	const conflictAction = conflictId
		? keybinds.actions.find((a) => a.id === conflictId)
		: null;

	return (
		<div
			ref={containerRef}
			tabIndex={-1}
			style={{
				display: 'flex',
				flexDirection: 'column',
				alignItems: 'stretch',
				gap: 4,
				flex: 1,
				minWidth: 0,
			}}
		>
			<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
				<button
					type="button"
					className={`${styles.comboButton} ${styles.comboButtonRecording}`}
					style={{ flex: 1 }}
					tabIndex={-1}
				>
					{captured ? formatCombo(captured) : 'Press a key combination…'}
				</button>
				<Button
					variant="primary"
					size="sm"
					disabled={!captured}
					onClick={() => onSave(captured)}
				>
					Save
				</Button>
				<Button variant="secondary" size="sm" onClick={() => onSave('')}>
					Clear
				</Button>
				<Button variant="secondary" size="sm" onClick={onCancel}>
					Cancel
				</Button>
			</div>
			{conflictAction && (
				<div className={styles.conflict}>
					Conflicts with <strong>{conflictAction.label}</strong> — saving
					will clear the other binding.
				</div>
			)}
			{!captured && (
				<div className={styles.recorderHint}>
					Press any key or combo. Press Escape to cancel.
				</div>
			)}
		</div>
	);
}
