/**
 * NicknameModal — lets the user set or clear a room-scoped nickname
 * for a member. Writes a new `m.room.member` state event via
 * `MemberManager.setRoomNickname`, which preserves the existing
 * membership and avatar and overwrites the displayname.
 *
 * The nickname is scoped to the Matrix room (i.e. the Brycord
 * channel), which in Brycord's model means "the server this channel
 * lives in as far as the member panel is concerned". The displayname
 * field is the exact field matrix-js-sdk's RoomMember.name reads
 * from, so every observer of the member list picks up the change as
 * soon as the state event syncs.
 */
import { useEffect, useState } from 'react';
import { Modal, Button } from '@brycord/ui';
import { MemberManager } from '@brycord/matrix-client';
import type { Member } from '@brycord/matrix-client';
import styles from './NicknameModal.module.css';

const MAX_NICKNAME = 80;

interface NicknameModalProps {
	isOpen: boolean;
	onClose: () => void;
	member: Member | null;
	channelId: string;
	/** The parent space — when provided the nickname is set server-wide. */
	serverId?: string;
}

export function NicknameModal({ isOpen, onClose, member, channelId, serverId }: NicknameModalProps) {
	const [value, setValue] = useState('');
	const [saving, setSaving] = useState(false);
	const [error, setError] = useState<string | null>(null);

	useEffect(() => {
		if (!isOpen || !member) return;
		// Seed with the current room nickname (if any); blank it out
		// when there's no override so the placeholder hints at the
		// user's global display name.
		setValue(member.nickname || '');
		setError(null);
		setSaving(false);
	}, [isOpen, member]);

	if (!member) return null;

	const trimmed = value.trim();
	const original = (member.nickname || '').trim();
	const isDirty = trimmed !== original;
	const tooLong = trimmed.length > MAX_NICKNAME;
	const canSave = !saving && isDirty && !tooLong;

	const setNickname = async (nick: string) => {
		const mgr = MemberManager.getInstance();
		if (serverId) {
			await mgr.setServerNickname(serverId, member.user.id, nick);
		} else {
			await mgr.setRoomNickname(channelId, member.user.id, nick);
		}
	};

	const handleSave = async () => {
		if (!canSave) return;
		setSaving(true);
		setError(null);
		try {
			await setNickname(trimmed);
			onClose();
		} catch (err: any) {
			const code = err?.errcode || err?.data?.errcode;
			if (code === 'M_FORBIDDEN') {
				setError("You don't have permission to rename this user.");
			} else {
				setError(err?.message || 'Failed to set nickname.');
			}
		} finally {
			setSaving(false);
		}
	};

	const handleClear = async () => {
		setSaving(true);
		setError(null);
		try {
			await setNickname('');
			onClose();
		} catch (err: any) {
			const code = err?.errcode || err?.data?.errcode;
			if (code === 'M_FORBIDDEN') {
				setError("You don't have permission to rename this user.");
			} else {
				setError(err?.message || 'Failed to clear nickname.');
			}
		} finally {
			setSaving(false);
		}
	};

	const globalName = member.user.displayName || member.user.username;

	return (
		<Modal.Root isOpen={isOpen} onClose={onClose} size="small">
			<Modal.Header title="Change Nickname" onClose={onClose} />
			<Modal.Content>
				<div className={styles.body}>
					<div className={styles.description}>
						Set a nickname for <strong>{globalName}</strong> in this server.
						Leave blank to restore their normal name.
					</div>
					<label className={styles.label}>
						<span className={styles.labelText}>Nickname</span>
						<input
							type="text"
							className={styles.input}
							value={value}
							onChange={(e) => setValue(e.target.value)}
							placeholder={globalName}
							maxLength={MAX_NICKNAME + 10}
							autoFocus
							onKeyDown={(e) => {
								if (e.key === 'Enter' && canSave) {
									e.preventDefault();
									handleSave();
								}
							}}
						/>
						<span className={`${styles.counter} ${tooLong ? styles.counterBad : ''}`}>
							{trimmed.length}/{MAX_NICKNAME}
						</span>
					</label>
					{error && <div className={styles.error}>{error}</div>}
				</div>
			</Modal.Content>
			<Modal.Footer>
				{original && (
					<Button variant="ghost" onClick={handleClear} disabled={saving}>
						Reset Nickname
					</Button>
				)}
				<Button variant="secondary" onClick={onClose} disabled={saving}>
					Cancel
				</Button>
				<Button variant="primary" onClick={handleSave} disabled={!canSave}>
					{saving ? 'Saving…' : 'Save'}
				</Button>
			</Modal.Footer>
		</Modal.Root>
	);
}
