/**
 * PrivacySettingsModal — controls who can join the space by writing the
 * m.room.join_rules state event. Fluxer's privacy modal is DM-related
 * (controls whether other members can DM you); in Matrix the equivalent
 * server-level privacy setting is the join rule, which is more useful
 * to expose in a Brycord community.
 */
import { observer } from 'mobx-react-lite';
import { useEffect, useState } from 'react';
import { Globe, Lock, Check, ShieldCheck } from '@phosphor-icons/react';
import { Modal, Button } from '@brycord/ui';
import { RoomManager, MatrixClientManager } from '@brycord/matrix-client';
import ServerStore from '@app/stores/ServerStore';
import styles from './PrivacySettingsModal.module.css';

interface PrivacySettingsModalProps {
	isOpen: boolean;
	onClose: () => void;
	serverId: string;
}

type JoinRule = 'public' | 'invite';

/**
 * Same power-level check as the channel settings modal / sidebar gear —
 * state-event power required. Writing m.room.join_rules is gated at
 * state_default (typically 50) or higher.
 */
function canModifyRoom(roomId: string): boolean {
	const client = MatrixClientManager.getInstance().getClient();
	const room = client.getRoom(roomId);
	if (!room) return false;
	const userId = client.getUserId();
	if (!userId) return false;
	const myPower = room.getMember(userId)?.powerLevel ?? 0;
	const plEvent = room.currentState.getStateEvents('m.room.power_levels', '');
	const stateDefault = (plEvent?.getContent()?.state_default ?? 50) as number;
	return myPower >= stateDefault;
}

export const PrivacySettingsModal = observer(function PrivacySettingsModal({
	isOpen,
	onClose,
	serverId,
}: PrivacySettingsModalProps) {
	const server = ServerStore.getServer(serverId);
	const [currentRule, setCurrentRule] = useState<JoinRule>('invite');
	const [saving, setSaving] = useState(false);
	const [status, setStatus] = useState<{ type: 'success' | 'error'; message: string } | null>(null);
	const [repairing, setRepairing] = useState(false);
	const [repairStatus, setRepairStatus] = useState<{
		type: 'success' | 'error';
		message: string;
	} | null>(null);

	useEffect(() => {
		if (!isOpen) return;
		setStatus(null);
		setRepairStatus(null);
		const rule = RoomManager.getInstance().getJoinRule(serverId);
		// Only 'public' and 'invite' are selectable in this UI; anything
		// else (knock, restricted, etc.) shows as "Invite Only" by default
		// to keep the UX simple. Advanced rules can be set via direct
		// Matrix state events if needed.
		setCurrentRule(rule === 'public' ? 'public' : 'invite');
	}, [isOpen, serverId]);

	const canModify = canModifyRoom(serverId);

	const handleSelect = (rule: JoinRule) => {
		if (!canModify) return;
		setCurrentRule(rule);
		setStatus(null);
	};

	const handleSave = async () => {
		if (!canModify) return;
		setSaving(true);
		setStatus(null);
		try {
			await RoomManager.getInstance().setJoinRule(serverId, currentRule);
			setStatus({ type: 'success', message: 'Privacy settings updated.' });
		} catch (err: any) {
			setStatus({
				type: 'error',
				message: err?.message || 'Failed to update privacy settings.',
			});
		} finally {
			setSaving(false);
		}
	};

	const handleRepair = async () => {
		if (!canModify) return;
		setRepairing(true);
		setRepairStatus(null);
		try {
			const result = await RoomManager.getInstance().repairChannelJoinRules(serverId);
			const parts: string[] = [];
			if (result.updated > 0) {
				parts.push(
					`${result.updated} channel${result.updated === 1 ? '' : 's'} updated`,
				);
			}
			if (result.autoJoinUpdated > 0) {
				parts.push(
					`${result.autoJoinUpdated} marked for auto-join`,
				);
			}
			if (result.skipped > 0) {
				parts.push(`${result.skipped} already OK`);
			}
			if (result.failed > 0) {
				parts.push(
					`${result.failed} couldn't be updated (old room version)`,
				);
			}
			setRepairStatus({
				type: result.failed > 0 && result.updated === 0 ? 'error' : 'success',
				message:
					parts.length > 0
						? parts.join(' · ')
						: 'No channels needed updating.',
			});
		} catch (err: any) {
			setRepairStatus({
				type: 'error',
				message: err?.message || 'Failed to repair channel access.',
			});
		} finally {
			setRepairing(false);
		}
	};

	return (
		<Modal.Root isOpen={isOpen} onClose={onClose} size="medium">
			<Modal.Header
				title={`Privacy Settings — ${server?.name || 'Community'}`}
				onClose={onClose}
			/>
			<Modal.Content>
				<div className={styles.body}>
					{!canModify && (
						<div className={styles.permissionWarning}>
							You don't have permission to change this community's
							privacy settings.
						</div>
					)}

					<div className={styles.sectionLabel}>Who Can Join</div>
					<div className={styles.sectionDescription}>
						Choose who is allowed to enter this community.
					</div>

					<div className={styles.optionList}>
						<button
							type="button"
							className={`${styles.option} ${
								currentRule === 'invite' ? styles.optionSelected : ''
							}`}
							onClick={() => handleSelect('invite')}
							disabled={!canModify}
						>
							<div className={styles.optionIcon}>
								<Lock size={22} weight="regular" />
							</div>
							<div className={styles.optionBody}>
								<div className={styles.optionTitle}>Invite Only</div>
								<div className={styles.optionDescription}>
									Only people you invite (or who are invited by
									members with permission) can join this community.
									Recommended for private groups.
								</div>
							</div>
							{currentRule === 'invite' && (
								<div className={styles.optionCheck}>
									<Check size={16} weight="bold" />
								</div>
							)}
						</button>

						<button
							type="button"
							className={`${styles.option} ${
								currentRule === 'public' ? styles.optionSelected : ''
							}`}
							onClick={() => handleSelect('public')}
							disabled={!canModify}
						>
							<div className={styles.optionIcon}>
								<Globe size={22} weight="regular" />
							</div>
							<div className={styles.optionBody}>
								<div className={styles.optionTitle}>Public</div>
								<div className={styles.optionDescription}>
									Anyone who has this community's address can join
									without an invite. Use this for open communities
									where discovery matters.
								</div>
							</div>
							{currentRule === 'public' && (
								<div className={styles.optionCheck}>
									<Check size={16} weight="bold" />
								</div>
							)}
						</button>
					</div>

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

					{/* Channel Access repair section — one-shot fix for legacy
					    channels created before restricted join rules were
					    the default. */}
					{canModify && (
						<div className={styles.repairSection}>
							<div className={styles.sectionLabel}>Channel Access</div>
							<div className={styles.sectionDescription}>
								New channels let any community member join automatically.
								If members joining this community can't see existing
								channels, run this to update the older channels' access
								rules so anyone in the community can join them without
								a separate invite.
							</div>
							<Button
								variant="secondary"
								size="sm"
								icon={<ShieldCheck size={16} />}
								loading={repairing}
								onClick={handleRepair}
							>
								Repair Channel Access
							</Button>
							{repairStatus && (
								<p
									className={`${styles.status} ${
										repairStatus.type === 'success'
											? styles.statusSuccess
											: styles.statusError
									}`}
								>
									{repairStatus.message}
								</p>
							)}
						</div>
					)}
				</div>
			</Modal.Content>
			<Modal.Footer>
				<Button variant="secondary" size="sm" onClick={onClose}>
					Cancel
				</Button>
				<Button
					variant="primary"
					size="sm"
					disabled={!canModify || saving}
					loading={saving}
					onClick={handleSave}
				>
					Save Changes
				</Button>
			</Modal.Footer>
		</Modal.Root>
	);
});
