/**
 * MemberProfileModal — full-screen "View Profile" card used from the
 * DM header and (optionally) from member list rows. Ported from the
 * new UI's MemberProfileModal, rebuilt against Convex:
 *
 *   - Accent, banner, avatar, bio, status all come from
 *     `api.auth.getPublicKeys` for the target user (live — `useQuery`).
 *   - Presence is reconciled through `PresenceContext.resolveStatus`
 *     so the dot matches the live heartbeat set.
 *   - "Message" opens / creates the 1:1 DM via `api.dms.openDM`.
 *   - "Edit Profile" fires the global `brycord:open-user-settings`
 *     event when the viewer is themselves.
 *   - "Rotate Encryption Key" is shown when the caller passes
 *     `onRotateKey` (i.e. the modal was opened from a DM header).
 */
import { useEffect, useMemo, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { useNavigate } from 'react-router-dom';
import { AnimatePresence, motion } from 'framer-motion';
import { useMutation, useQuery } from 'convex/react';
import {
	CheckCircle,
	ChatCircleDots,
	Copy,
	DotsThree,
	Key,
	PencilSimple,
	X,
} from '@phosphor-icons/react';
import { Avatar } from '@discord-clone/ui';
import { api } from '../../../../../convex/_generated/api';
import { useOnlineUsers } from '../../contexts/PresenceContext';
import styles from './MemberProfileModal.module.css';

interface MemberProfileModalMember {
	userId: string;
}

interface MemberProfileModalProps {
	isOpen: boolean;
	onClose: () => void;
	member: MemberProfileModalMember | null;
	/**
	 * Optional handler for the "Rotate Encryption Key" button. When
	 * provided (and the viewer is not themselves), an icon button next
	 * to Message fires it. A resolved promise shows a success line; a
	 * rejected one shows the error message.
	 */
	onRotateKey?: () => Promise<void>;
}

const DEFAULT_ACCENT = '#4641D9';

interface StatusDisplay {
	label: string;
	dotClass: string;
}

function getStatusDisplay(presence: string): StatusDisplay {
	switch (presence) {
		case 'online':
			return { label: 'Online', dotClass: styles.statusOnline };
		case 'idle':
			return { label: 'Idle', dotClass: styles.statusIdle };
		case 'dnd':
			return { label: 'Do Not Disturb', dotClass: styles.statusDnd };
		case 'offline':
		default:
			return { label: 'Offline', dotClass: styles.statusOffline };
	}
}

export function MemberProfileModal({
	isOpen,
	onClose,
	member,
	onRotateKey,
}: MemberProfileModalProps) {
	const navigate = useNavigate();
	const { resolveStatus } = useOnlineUsers();

	const [copied, setCopied] = useState(false);
	const [moreOpen, setMoreOpen] = useState(false);
	const [rotating, setRotating] = useState(false);
	const [rotateStatus, setRotateStatus] = useState<
		{ type: 'success' | 'error'; message: string } | null
	>(null);
	const moreButtonRef = useRef<HTMLButtonElement>(null);
	const moreMenuRef = useRef<HTMLDivElement>(null);

	const allUsers = useQuery(api.auth.getPublicKeys, isOpen ? {} : 'skip') ?? [];
	const localUserId =
		typeof localStorage !== 'undefined' ? localStorage.getItem('userId') : null;

	const profile = useMemo(
		() => (member ? allUsers.find((u) => u.id === member.userId) : undefined),
		[allUsers, member],
	);

	const openDM = useMutation(api.dms.openDM);

	useEffect(() => {
		if (!moreOpen) return;
		const handler = (e: MouseEvent) => {
			const target = e.target as Node;
			if (moreMenuRef.current?.contains(target)) return;
			if (moreButtonRef.current?.contains(target)) return;
			setMoreOpen(false);
		};
		document.addEventListener('mousedown', handler);
		return () => document.removeEventListener('mousedown', handler);
	}, [moreOpen]);

	useEffect(() => {
		if (!isOpen) {
			setMoreOpen(false);
			setRotateStatus(null);
			setRotating(false);
		}
	}, [isOpen]);

	useEffect(() => {
		if (!isOpen) return;
		const handler = (e: KeyboardEvent) => {
			if (e.key === 'Escape') onClose();
		};
		document.addEventListener('keydown', handler);
		return () => document.removeEventListener('keydown', handler);
	}, [isOpen, onClose]);

	if (!isOpen || !member) return null;

	const displayName =
		profile?.displayName || profile?.username || 'Unknown User';
	const username = profile?.username || '';
	const avatarUrl = profile?.avatarUrl ?? null;
	const bio = profile?.aboutMe?.trim();
	const accent = (profile as any)?.accentColor || DEFAULT_ACCENT;
	const storedStatus = (profile?.status as string | undefined) || 'offline';
	const livePresence = resolveStatus(storedStatus, member.userId);
	const statusDisplay = getStatusDisplay(livePresence);

	const isMeLocal = localUserId === member.userId;

	const handleCopy = () => {
		void navigator.clipboard.writeText(member.userId).then(
			() => {
				setCopied(true);
				setTimeout(() => setCopied(false), 1500);
			},
			() => {},
		);
	};

	const handleEditProfile = () => {
		window.dispatchEvent(new CustomEvent('brycord:open-user-settings'));
		onClose();
	};

	const handleMessage = async () => {
		if (!localUserId) return;
		try {
			const result = await openDM({
				userId: localUserId as any,
				targetUserId: member.userId as any,
			});
			navigate(`/channels/@me/${result.channelId}`);
			onClose();
		} catch (err) {
			console.warn('Failed to open DM from profile modal:', err);
		}
	};

	const handleRotate = async () => {
		if (!onRotateKey || rotating) return;
		setRotating(true);
		setRotateStatus(null);
		try {
			await onRotateKey();
			setRotateStatus({
				type: 'success',
				message: 'Encryption key rotated.',
			});
		} catch (err: any) {
			setRotateStatus({
				type: 'error',
				message: err?.message ?? 'Rotation failed.',
			});
		} finally {
			setRotating(false);
		}
	};

	return createPortal(
		<AnimatePresence>
			{isOpen && (
				<motion.div
					className={styles.backdrop}
					initial={{ opacity: 0 }}
					animate={{ opacity: 1 }}
					exit={{ opacity: 0 }}
					transition={{ duration: 0.15 }}
					onClick={onClose}
				>
					<motion.div
						className={styles.cardWrap}
						initial={{ opacity: 0, scale: 0.94 }}
						animate={{ opacity: 1, scale: 1 }}
						exit={{ opacity: 0, scale: 0.94 }}
						transition={{ duration: 0.18, ease: 'easeOut' }}
						style={{
							borderColor: accent,
							boxShadow: `0 10px 30px rgba(0, 0, 0, 0.35), 0 0 0 1px ${accent}55, 0 0 40px ${accent}30`,
						}}
						onClick={(e) => e.stopPropagation()}
					>
						<button
							type="button"
							className={styles.closeButton}
							onClick={onClose}
							aria-label="Close profile"
						>
							<X size={18} weight="bold" />
						</button>

						<div
							className={styles.banner}
							style={{ backgroundColor: accent }}
						/>

						<div className={styles.headerRow}>
							<div className={styles.avatarWrap}>
								<Avatar src={avatarUrl} fallback={displayName} size={96} />
								<div
									className={`${styles.statusDot} ${statusDisplay.dotClass}`}
									aria-label={statusDisplay.label}
								/>
							</div>

							<div className={styles.actionRow}>
								{isMeLocal ? (
									<button
										type="button"
										className={styles.primaryButton}
										onClick={handleEditProfile}
									>
										<PencilSimple size={16} weight="fill" />
										<span>Edit Profile</span>
									</button>
								) : (
									<>
										<button
											type="button"
											className={styles.primaryButton}
											onClick={handleMessage}
										>
											<ChatCircleDots size={16} weight="fill" />
											<span>Message</span>
										</button>
										{onRotateKey && (
											<button
												type="button"
												className={styles.iconButton}
												onClick={handleRotate}
												disabled={rotating}
												aria-label="Rotate Encryption Key"
												title="Rotate Encryption Key"
											>
												<Key size={18} weight="bold" />
											</button>
										)}
									</>
								)}
								<div className={styles.moreWrap}>
									<button
										ref={moreButtonRef}
										type="button"
										className={styles.iconButton}
										onClick={() => setMoreOpen((v) => !v)}
										aria-label="More options"
									>
										<DotsThree size={22} weight="bold" />
									</button>
								</div>
							</div>
						</div>

						<div className={styles.body}>
							<div className={styles.nameBlock}>
								<h2 className={styles.displayName}>{displayName}</h2>
								{username && (
									<div className={styles.realName}>@{username}</div>
								)}
							</div>

							{bio && (
								<>
									<div className={styles.divider} />
									<div className={styles.section}>
										<div className={styles.sectionLabel}>About Me</div>
										<div className={styles.bioText}>{bio}</div>
									</div>
								</>
							)}

							{rotateStatus && (
								<>
									<div className={styles.divider} />
									<div className={styles.section}>
										<div
											style={{
												fontSize: 13,
												color:
													rotateStatus.type === 'success'
														? '#3ba55d'
														: 'var(--status-danger, #ed4245)',
											}}
										>
											{rotateStatus.message}
										</div>
									</div>
								</>
							)}

							<div className={styles.divider} />

							<div className={styles.section}>
								<div className={styles.sectionLabel}>User ID</div>
								<div className={styles.idRow}>
									<span className={styles.idValue}>{member.userId}</span>
									<button
										type="button"
										className={styles.copyButton}
										onClick={handleCopy}
										aria-label="Copy user ID"
									>
										{copied ? (
											<CheckCircle size={16} weight="fill" />
										) : (
											<Copy size={16} weight="fill" />
										)}
									</button>
								</div>
							</div>
						</div>
					</motion.div>
				</motion.div>
			)}
		</AnimatePresence>,
		document.body,
	);
}
