/**
 * AddFriendsSheet — bottom sheet reached from the "Add Friends" button
 * in the DM sidebar. Discord Clone has no friends/pending-request
 * backend (it stores DMs directly via `api.dms.openDM`), so this sheet
 * functions as a username search that opens a DM with the matched user.
 *
 * The new UI's Pending/Ignored tabs are preserved as placeholders with
 * an empty state. They will light up when the Convex schema grows a
 * friends table.
 */
import { useEffect, useMemo, useState } from 'react';
import { useMutation, useQuery } from 'convex/react';
import { useNavigate } from 'react-router-dom';
import { X } from '@phosphor-icons/react';
import { Avatar, BottomSheet } from '@discord-clone/ui';
import { api } from '../../../../../convex/_generated/api';
import type { Id } from '../../../../../convex/_generated/dataModel';
import styles from './AddFriendsSheet.module.css';

interface AddFriendsSheetProps {
	isOpen: boolean;
	onClose: () => void;
}

type Tab = 'add' | 'pending';

interface PublicUser {
	id: string;
	username?: string;
	displayName?: string | null;
	avatarUrl?: string | null;
}

export function AddFriendsSheet({ isOpen, onClose }: AddFriendsSheetProps) {
	const navigate = useNavigate();
	const [activeTab, setActiveTab] = useState<Tab>('add');
	const [username, setUsername] = useState('');
	const [busy, setBusy] = useState(false);
	const [status, setStatus] = useState<
		{ type: 'error' | 'success'; message: string } | null
	>(null);

	const allUsers = (useQuery(api.auth.getPublicKeys) ?? []) as PublicUser[];
	const openDM = useMutation(api.dms.openDM);

	const myUserId =
		typeof localStorage !== 'undefined' ? localStorage.getItem('userId') : null;

	// Filter candidates by the search query (case-insensitive on
	// username OR display name), excluding the current user.
	const matches = useMemo<PublicUser[]>(() => {
		const q = username.trim().toLowerCase();
		if (!q) return [];
		return allUsers
			.filter((u) => u.id !== myUserId)
			.filter((u) => {
				const uname = (u.username || '').toLowerCase();
				const display = (u.displayName || '').toLowerCase();
				return uname.includes(q) || display.includes(q);
			})
			.slice(0, 20);
	}, [allUsers, username, myUserId]);

	useEffect(() => {
		if (isOpen) {
			setStatus(null);
			setUsername('');
			setBusy(false);
			setActiveTab('add');
		}
	}, [isOpen]);

	const handleStartDM = async (target: PublicUser) => {
		if (busy || !myUserId) return;
		setBusy(true);
		setStatus(null);
		try {
			const result = await openDM({
				userId: myUserId as Id<'userProfiles'>,
				targetUserId: target.id as Id<'userProfiles'>,
			});
			navigate(`/channels/@me/${result.channelId}`);
			onClose();
		} catch (err: any) {
			setStatus({
				type: 'error',
				message: err?.message || 'Failed to start DM.',
			});
		} finally {
			setBusy(false);
		}
	};

	return (
		<BottomSheet isOpen={isOpen} onClose={onClose} disableDefaultHeader showHandle>
			<div className={styles.root}>
				<div className={styles.topBar}>
					<div />
					<h2 className={styles.topBarTitle}>Add Friend</h2>
					<button
						type="button"
						className={styles.topBarButton}
						onClick={onClose}
						aria-label="Close"
					>
						<X size={20} weight="bold" />
					</button>
				</div>

				<div className={styles.tabBar} role="tablist">
					<button
						type="button"
						role="tab"
						aria-selected={activeTab === 'add'}
						className={`${styles.tabButton} ${
							activeTab === 'add' ? styles.tabButtonActive : ''
						}`}
						onClick={() => setActiveTab('add')}
					>
						<span>Add</span>
					</button>
					<button
						type="button"
						role="tab"
						aria-selected={activeTab === 'pending'}
						className={`${styles.tabButton} ${
							activeTab === 'pending' ? styles.tabButtonActive : ''
						}`}
						onClick={() => setActiveTab('pending')}
					>
						Pending
					</button>
				</div>

				<div className={styles.body}>
					{activeTab === 'add' ? (
						<>
							<div className={styles.usernameRow}>
								<input
									type="text"
									className={styles.usernameInput}
									placeholder="Search by username or display name"
									value={username}
									onChange={(e) => setUsername(e.target.value)}
									autoCapitalize="off"
									autoCorrect="off"
									spellCheck={false}
									disabled={busy}
								/>
								{status && (
									<div
										className={
											status.type === 'error'
												? styles.statusError
												: styles.statusSuccess
										}
									>
										{status.message}
									</div>
								)}
							</div>

							<div className={styles.sectionLabel}>
								{username.trim() ? `Results — ${matches.length}` : 'Start typing to search'}
							</div>
							{username.trim() && matches.length === 0 ? (
								<div className={styles.empty}>No users match "{username}".</div>
							) : (
								<div className={styles.rowList}>
									{matches.map((u) => (
										<UserRow
											key={u.id}
											user={u}
											onStartDM={() => handleStartDM(u)}
											disabled={busy}
										/>
									))}
								</div>
							)}
						</>
					) : (
						<>
							<div className={styles.sectionLabel}>Pending requests</div>
							<div className={styles.empty}>
								Pending friend requests aren't supported yet.
							</div>
						</>
					)}
				</div>
			</div>
		</BottomSheet>
	);
}

interface UserRowProps {
	user: PublicUser;
	onStartDM: () => void;
	disabled?: boolean;
}

function UserRow({ user, onStartDM, disabled }: UserRowProps) {
	const name = user.displayName || user.username || 'User';
	return (
		<div className={styles.row}>
			<Avatar src={user.avatarUrl ?? undefined} fallback={name} size={40} />
			<div className={styles.rowText}>
				<span className={styles.rowName}>{name}</span>
				{user.username && (
					<span className={styles.rowSubtitle}>@{user.username}</span>
				)}
			</div>
			<div className={styles.rowActions}>
				<button
					type="button"
					className={`${styles.pillButton} ${styles.pillButtonPrimary}`}
					onClick={onStartDM}
					disabled={disabled}
				>
					Start DM
				</button>
			</div>
		</div>
	);
}
