/**
 * ChannelSettingsModal — opens from the hover gear icon on a channel
 * row (via the `brycord:open-channel-settings` event, dispatched by
 * GuildNavbar). Lets the user edit the channel name + topic and delete
 * the channel. Gated by the `manage_channels` permission.
 */
import { useEffect, useState } from 'react';
import { useMutation, useQuery } from 'convex/react';
import { Hash, SpeakerHigh, Trash } from '@phosphor-icons/react';
import { Button, Modal } from '@discord-clone/ui';
import { api } from '../../../../../convex/_generated/api';
import type { Id } from '../../../../../convex/_generated/dataModel';
import styles from './ChannelSettingsModal.module.css';

interface ChannelSettingsModalProps {
	isOpen: boolean;
	onClose: () => void;
	channelId: string | null;
}

const NAME_MAX = 100;
const TOPIC_MAX = 1024;

export function ChannelSettingsModal({
	isOpen,
	onClose,
	channelId,
}: ChannelSettingsModalProps) {
	const channel = useQuery(
		api.channels.get,
		isOpen && channelId ? { id: channelId as Id<'channels'> } : 'skip',
	);

	const myUserId =
		typeof localStorage !== 'undefined' ? localStorage.getItem('userId') : null;
	const myPerms = useQuery(
		api.roles.getMyPermissions,
		myUserId ? { userId: myUserId as Id<'userProfiles'> } : 'skip',
	);
	const canModify = !!myPerms?.manage_channels;

	const renameChannel = useMutation(api.channels.rename);
	const updateTopic = useMutation(api.channels.updateTopic);
	const removeChannel = useMutation(api.channels.remove);

	const [name, setName] = useState('');
	const [topic, setTopic] = useState('');
	const [saving, setSaving] = useState(false);
	const [deleting, setDeleting] = useState(false);
	const [status, setStatus] = useState<
		{ type: 'success' | 'error'; message: string } | null
	>(null);
	const [confirmDelete, setConfirmDelete] = useState(false);

	useEffect(() => {
		if (isOpen && channel) {
			setName(channel.name || '');
			setTopic(channel.topic || '');
			setStatus(null);
			setConfirmDelete(false);
		}
	}, [isOpen, channel?._id, channel?.name, channel?.topic]);

	if (!channel) return null;

	const trimmedName = name.trim();
	const trimmedTopic = topic.trim();
	const originalName = (channel.name || '').trim();
	const originalTopic = (channel.topic || '').trim();
	const isDirty = trimmedName !== originalName || trimmedTopic !== originalTopic;
	const nameValid = trimmedName.length > 0 && trimmedName.length <= NAME_MAX;
	const topicValid = trimmedTopic.length <= TOPIC_MAX;

	const handleSave = async () => {
		if (!canModify || !isDirty || !nameValid || !topicValid) return;
		setSaving(true);
		setStatus(null);
		try {
			if (trimmedName !== originalName) {
				await renameChannel({
					id: channel._id as Id<'channels'>,
					name: trimmedName,
				});
			}
			if (trimmedTopic !== originalTopic) {
				await updateTopic({
					id: channel._id as Id<'channels'>,
					topic: trimmedTopic,
				});
			}
			setStatus({ type: 'success', message: 'Channel updated.' });
		} catch (err: any) {
			setStatus({
				type: 'error',
				message: err?.message || 'Failed to update channel.',
			});
		} finally {
			setSaving(false);
		}
	};

	const handleDelete = async () => {
		if (!canModify) return;
		setDeleting(true);
		try {
			await removeChannel({ id: channel._id as Id<'channels'> });
			onClose();
		} catch (err: any) {
			setStatus({
				type: 'error',
				message: err?.message || 'Failed to delete channel.',
			});
			setDeleting(false);
		}
	};

	const isVoice = channel.type === 'voice';

	return (
		<Modal.Root isOpen={isOpen} onClose={onClose} size="medium">
			<Modal.Header
				title={`Edit ${isVoice ? 'Voice Channel' : 'Channel'}`}
				onClose={onClose}
			/>
			<Modal.Content>
				<div className={styles.body}>
					{!canModify && (
						<div className={styles.permissionWarning}>
							You don't have permission to edit this channel.
						</div>
					)}

					<div className={styles.channelHeader}>
						<div className={styles.channelHeaderIcon}>
							{isVoice ? (
								<SpeakerHigh size={18} />
							) : (
								<Hash size={18} weight="bold" />
							)}
						</div>
						<div className={styles.channelHeaderText}>
							<div className={styles.channelHeaderName}>{channel.name}</div>
							<div className={styles.channelHeaderSubtitle}>
								{isVoice ? 'Voice Channel' : 'Text Channel'}
							</div>
						</div>
					</div>

					<fieldset className={styles.field} disabled={!canModify}>
						<label className={styles.label} htmlFor="channel-settings-name">
							Channel Name
						</label>
						<input
							id="channel-settings-name"
							type="text"
							className={styles.input}
							value={name}
							maxLength={NAME_MAX}
							onChange={(e) => setName(e.target.value)}
							placeholder="channel-name"
						/>
						<div className={styles.fieldFooter}>
							<span className={styles.fieldHint}>
								{isVoice
									? 'Displayed in the voice channel list.'
									: 'Displayed in the channel list and at the top of the chat.'}
							</span>
							<span
								className={
									name.length >= NAME_MAX ? styles.counterFull : styles.counter
								}
							>
								{name.length}/{NAME_MAX}
							</span>
						</div>
					</fieldset>

					<fieldset className={styles.field} disabled={!canModify}>
						<label className={styles.label} htmlFor="channel-settings-topic">
							Channel Topic
						</label>
						<textarea
							id="channel-settings-topic"
							className={styles.textarea}
							value={topic}
							maxLength={TOPIC_MAX}
							rows={4}
							onChange={(e) => setTopic(e.target.value)}
							placeholder="Let people know what this channel is about."
						/>
						<div className={styles.fieldFooter}>
							<span className={styles.fieldHint}>
								Shown next to the channel name in the header.
							</span>
							<span
								className={
									topic.length >= TOPIC_MAX ? styles.counterFull : styles.counter
								}
							>
								{topic.length}/{TOPIC_MAX}
							</span>
						</div>
					</fieldset>

					{status && (
						<p
							className={`${styles.statusMessage} ${
								status.type === 'success'
									? styles.statusSuccess
									: styles.statusError
							}`}
						>
							{status.message}
						</p>
					)}

					{canModify && (
						<div className={styles.dangerZone}>
							<div className={styles.dangerHeader}>Delete Channel</div>
							<p className={styles.dangerDescription}>
								Removes this channel for everyone. All messages in it will be
								permanently deleted.
							</p>
							{confirmDelete ? (
								<div className={styles.dangerConfirmRow}>
									<span className={styles.dangerConfirmText}>Are you sure?</span>
									<Button
										variant="secondary"
										size="sm"
										onClick={() => setConfirmDelete(false)}
										disabled={deleting}
									>
										Cancel
									</Button>
									<Button
										variant="danger"
										size="sm"
										icon={<Trash size={16} />}
										loading={deleting}
										onClick={handleDelete}
									>
										Delete Channel
									</Button>
								</div>
							) : (
								<Button
									variant="danger"
									size="sm"
									icon={<Trash size={16} />}
									onClick={() => setConfirmDelete(true)}
								>
									Delete Channel
								</Button>
							)}
						</div>
					)}
				</div>
			</Modal.Content>
			<Modal.Footer>
				<Button variant="secondary" size="sm" onClick={onClose}>
					Cancel
				</Button>
				<Button
					variant="primary"
					size="sm"
					disabled={
						!canModify || !isDirty || !nameValid || !topicValid || saving
					}
					loading={saving}
					onClick={handleSave}
				>
					Save Changes
				</Button>
			</Modal.Footer>
		</Modal.Root>
	);
}
