/**
 * UserAreaProfilePopout — Discord-style card that opens above the
 * bottom-left user area when the user clicks their own avatar/name.
 *
 * Contents:
 *  - Banner (accent color) with the user's avatar overlapping
 *  - Display name + username + bio
 *  - Status selector (Online / Idle / DND / Invisible) wired to
 *    `api.auth.updateStatus`
 *  - Copy User ID button
 *  - Edit Profile button (fires `brycord:open-user-settings` via the
 *    `onEditProfile` callback)
 *
 * Rendered via createPortal so it escapes the sidebar clipping.
 * Position is fixed and computed from the trigger's
 * getBoundingClientRect() when the popout opens.
 */
import { useEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { useMutation, useQuery } from 'convex/react';
import {
	Circle,
	Moon,
	MinusCircle,
	XCircle,
	Copy,
	PencilSimple,
	CaretRight,
	Check,
} from '@phosphor-icons/react';
import { Avatar, Button } from '@discord-clone/ui';
import { api } from '../../../../../convex/_generated/api';
import styles from './UserAreaProfilePopout.module.css';

type StatusId = 'online' | 'idle' | 'dnd' | 'invisible';

interface UserAreaProfilePopoutProps {
	anchorRect: DOMRect;
	onClose: () => void;
	onEditProfile: () => void;
}

const STATUS_OPTIONS: Array<{
	id: StatusId;
	label: string;
	description?: string;
	icon: React.ReactNode;
	iconClass: string;
}> = [
	{
		id: 'online',
		label: 'Online',
		icon: <Circle size={12} weight="fill" />,
		iconClass: 'statusOnline',
	},
	{
		id: 'idle',
		label: 'Idle',
		description: 'Shown as away',
		icon: <Moon size={12} weight="fill" />,
		iconClass: 'statusIdle',
	},
	{
		id: 'dnd',
		label: 'Do Not Disturb',
		description: 'Notifications suppressed',
		icon: <MinusCircle size={12} weight="fill" />,
		iconClass: 'statusDnd',
	},
	{
		id: 'invisible',
		label: 'Invisible',
		description: 'Appear offline',
		icon: <XCircle size={12} weight="fill" />,
		iconClass: 'statusOffline',
	},
];

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

function getStatusClassName(status: string): string {
	switch (status) {
		case 'online':
			return styles.statusOnline;
		case 'idle':
			return styles.statusIdle;
		case 'dnd':
			return styles.statusDnd;
		case 'invisible':
		case 'offline':
			return styles.statusOffline;
		default:
			return styles.statusOnline;
	}
}

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';
	}
}

const DEFAULT_ACCENT_COLOR = '#4641D9';
const POPOUT_WIDTH = 300;
const GAP = 12;
const VIEWPORT_MARGIN = 8;

export function UserAreaProfilePopout({
	anchorRect,
	onClose,
	onEditProfile,
}: UserAreaProfilePopoutProps) {
	const ref = useRef<HTMLDivElement>(null);
	const [statusPickerOpen, setStatusPickerOpen] = useState(false);
	const [copiedId, setCopiedId] = useState(false);

	const userId =
		typeof localStorage !== 'undefined' ? localStorage.getItem('userId') : null;
	const allUsers = useQuery(api.auth.getPublicKeys) ?? [];
	const me = allUsers.find((u) => u.id === userId);
	const updateStatus = useMutation(api.auth.updateStatus);

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

	if (!me || !userId) return null;

	// Pull the current user's saved accent color from their profile
	// row. Reactive via `useQuery` so the popout updates instantly
	// when the value changes in Settings → My Account.
	const accentColor = (me as any)?.accentColor || DEFAULT_ACCENT_COLOR;
	const presence = me.status || 'online';
	const bio = me.aboutMe?.trim();
	const displayName = me.displayName || me.username || 'User';

	// Position: bottom of popout is anchored to top of trigger with a
	// small gap. Left-align to trigger's left edge, clamp to viewport.
	const left = Math.max(
		VIEWPORT_MARGIN,
		Math.min(anchorRect.left, window.innerWidth - POPOUT_WIDTH - VIEWPORT_MARGIN),
	);
	const bottom = Math.max(VIEWPORT_MARGIN, window.innerHeight - anchorRect.top + GAP);

	const style: React.CSSProperties = {
		left,
		bottom,
		width: POPOUT_WIDTH,
		borderColor: accentColor,
		boxShadow: `0 16px 32px rgba(0, 0, 0, 0.5), 0 0 0 1px ${accentColor}55, 0 0 28px ${accentColor}30`,
	};

	const handleStatusSelect = async (status: StatusId) => {
		try {
			await updateStatus({ userId: userId as any, status });
		} catch (err) {
			console.error('Failed to update status:', err);
		}
		setStatusPickerOpen(false);
	};

	const handleCopyUserId = async () => {
		try {
			await navigator.clipboard.writeText(userId);
			setCopiedId(true);
			setTimeout(() => setCopiedId(false), 1500);
		} catch {
			// Clipboard API can be blocked in some contexts — silently fail.
		}
	};

	return createPortal(
		<div className={styles.overlay}>
			<div className={styles.card} ref={ref} style={style}>
				{/* Banner + avatar header */}
				<div className={styles.header}>
					<div
						className={styles.banner}
						style={{ backgroundColor: accentColor }}
					/>
					<div className={styles.avatarWrap}>
						<Avatar
							src={me.avatarUrl ?? null}
							fallback={displayName}
							size={72}
							status={mapAvatarStatus(presence)}
						/>
					</div>
				</div>

				{/* Name + handle */}
				<div className={styles.identity}>
					<div className={styles.displayName}>{displayName}</div>
					<div className={styles.handle}>{me.username}</div>
					{bio && bio.length > 0 && <div className={styles.bio}>{bio}</div>}
				</div>

				{/* Action group */}
				<div className={styles.actionGroup}>
					<div className={styles.statusRow}>
						<button
							type="button"
							className={styles.actionButton}
							onClick={() => setStatusPickerOpen((v) => !v)}
						>
							<span
								className={`${styles.statusDot} ${getStatusClassName(presence)}`}
							/>
							<span className={styles.actionLabel}>
								{getStatusLabel(presence)}
							</span>
							<CaretRight
								size={14}
								weight="bold"
								className={`${styles.chevron} ${statusPickerOpen ? styles.chevronOpen : ''}`}
							/>
						</button>

						{statusPickerOpen && (
							<div className={styles.statusMenu}>
								{STATUS_OPTIONS.map((opt) => {
									const isActive =
										presence === opt.id ||
										(opt.id === 'invisible' && presence === 'offline');
									return (
										<button
											key={opt.id}
											type="button"
											className={styles.statusMenuItem}
											onClick={() => handleStatusSelect(opt.id)}
										>
											<span
												className={`${styles.statusMenuIcon} ${styles[opt.iconClass]}`}
											>
												{opt.icon}
											</span>
											<span className={styles.statusMenuText}>
												<span className={styles.statusMenuLabel}>
													{opt.label}
												</span>
												{opt.description && (
													<span className={styles.statusMenuDescription}>
														{opt.description}
													</span>
												)}
											</span>
											{isActive && (
												<Check
													size={14}
													weight="bold"
													className={styles.statusMenuCheck}
												/>
											)}
										</button>
									);
								})}
							</div>
						)}
					</div>

					<div className={styles.divider} />

					<button
						type="button"
						className={styles.actionButton}
						onClick={handleCopyUserId}
					>
						<Copy size={16} weight="regular" className={styles.actionIcon} />
						<span className={styles.actionLabel}>
							{copiedId ? 'Copied!' : 'Copy User ID'}
						</span>
					</button>
				</div>

				{/* Edit profile CTA */}
				<div className={styles.footer}>
					<Button
						variant="primary"
						size="sm"
						fitContainer
						icon={<PencilSimple size={16} />}
						onClick={() => {
							onEditProfile();
							onClose();
						}}
					>
						Edit Profile
					</Button>
				</div>
			</div>
		</div>,
		document.body,
	);
}
