/**
 * RolesTab — left column lists every role in the server (with
 * @everyone pinned at the bottom), right column is the RoleEditor for
 * the currently selected role. The create button at the top spawns a
 * new role with default values and immediately selects it.
 *
 * Role reordering is via native HTML5 drag-and-drop — no new deps.
 * `@everyone` is non-draggable, non-selectable, non-deletable, and
 * has its own "read-only" notice in the editor.
 */
import { observer } from 'mobx-react-lite';
import { useEffect, useMemo, useState } from 'react';
import { Plus } from '@phosphor-icons/react';
import { Button } from '@brycord/ui';
import { RoleManager } from '@brycord/matrix-client';
import type { Role } from '@brycord/matrix-client';
import { MAX_ROLES_PER_SERVER } from '@brycord/constants';
import RoleStore from '@app/stores/RoleStore';
import SelectionStore from '@app/stores/SelectionStore';
import { RoleEditor } from './RoleEditor';
import { MobileRolesTab } from './MobileRolesTab';
import styles from './RolesTab.module.css';

interface RolesTabProps {
	serverId: string;
}

export const RolesTab = observer(function RolesTab({ serverId }: RolesTabProps) {
	// Mobile gets a completely different full-screen layout — a
	// Fluxer-style list of rounded cards that pushes the role editor
	// as a sub-screen. Delegates to a separate component so the
	// desktop hooks below don't run on the mobile path (and vice
	// versa), which keeps React's rules-of-hooks happy.
	if (SelectionStore.isMobileViewport) {
		return <MobileRolesTab serverId={serverId} />;
	}
	return <DesktopRolesTab serverId={serverId} />;
});

const DesktopRolesTab = observer(function DesktopRolesTab({ serverId }: RolesTabProps) {
	const [selectedRoleId, setSelectedRoleId] = useState<string | null>(null);
	const [error, setError] = useState<string | null>(null);
	const [creating, setCreating] = useState(false);
	const [dragOverId, setDragOverId] = useState<string | null>(null);

	const canManage = useMemo(() => {
		try {
			return RoleManager.getInstance().canManageRoles(serverId);
		} catch {
			return false;
		}
	}, [serverId]);

	// All roles including synthetic @everyone. Everyone is at index 0
	// in the store; split it out for rendering.
	const allRoles = RoleStore.getRoles(serverId);
	const editableRoles = allRoles
		.filter((r) => r.id !== 'everyone')
		.sort((a, b) => b.position - a.position); // show highest at the top
	const everyone = allRoles.find((r) => r.id === 'everyone');

	// Auto-select the first editable role when one exists and nothing
	// is currently selected.
	useEffect(() => {
		if (selectedRoleId) return;
		if (editableRoles.length > 0) setSelectedRoleId(editableRoles[0].id);
	}, [editableRoles, selectedRoleId]);

	// If the currently selected role was deleted, fall back.
	useEffect(() => {
		if (!selectedRoleId) return;
		if (!allRoles.some((r) => r.id === selectedRoleId)) {
			setSelectedRoleId(editableRoles[0]?.id ?? null);
		}
	}, [allRoles, editableRoles, selectedRoleId]);

	if (!canManage) {
		return (
			<div className={styles.gate}>
				<h2 className={styles.gateTitle}>Manage Roles</h2>
				<p className={styles.gateBody}>
					You need permission to manage roles in this server. Ask an
					admin to grant you a role with a higher power level.
				</p>
			</div>
		);
	}

	const handleCreate = async () => {
		if (creating) return;
		if (editableRoles.length >= MAX_ROLES_PER_SERVER) {
			setError(`A server can have at most ${MAX_ROLES_PER_SERVER} roles.`);
			return;
		}
		setCreating(true);
		setError(null);
		try {
			const role = await RoleManager.getInstance().createRole(serverId, {
				name: 'New Role',
				powerLevel: 0,
			});
			RoleStore.handleRoleCreated(serverId, role);
			setSelectedRoleId(role.id);
		} catch (err: any) {
			setError(err?.message || 'Failed to create role.');
		} finally {
			setCreating(false);
		}
	};

	const handleDragStart = (e: React.DragEvent, roleId: string) => {
		e.dataTransfer.effectAllowed = 'move';
		e.dataTransfer.setData('text/plain', roleId);
	};

	const handleDragOver = (e: React.DragEvent, overId: string) => {
		e.preventDefault();
		e.dataTransfer.dropEffect = 'move';
		setDragOverId(overId);
	};

	const handleDrop = async (e: React.DragEvent, dropOnId: string) => {
		e.preventDefault();
		setDragOverId(null);
		const draggedId = e.dataTransfer.getData('text/plain');
		if (!draggedId || draggedId === dropOnId) return;
		const order = editableRoles.map((r) => r.id);
		const fromIdx = order.indexOf(draggedId);
		const toIdx = order.indexOf(dropOnId);
		if (fromIdx === -1 || toIdx === -1) return;
		const next = [...order];
		next.splice(fromIdx, 1);
		next.splice(toIdx, 0, draggedId);
		// Since the list is displayed with highest position first,
		// reverse to match the RoleManager's ascending position order.
		const orderedIds = [...next].reverse();
		try {
			await RoleManager.getInstance().reorderRoles(serverId, orderedIds);
		} catch (err: any) {
			setError(err?.message || 'Failed to reorder roles.');
		}
	};

	const selectedRole: Role | undefined = selectedRoleId
		? allRoles.find((r) => r.id === selectedRoleId)
		: undefined;

	return (
		<div className={styles.container}>
			<div className={styles.list}>
				<div className={styles.listHeader}>
					<span className={styles.listTitle}>Roles</span>
					<span className={styles.listCount}>
						{editableRoles.length}/{MAX_ROLES_PER_SERVER}
					</span>
				</div>
				<Button
					variant="primary"
					onClick={handleCreate}
					disabled={creating || editableRoles.length >= MAX_ROLES_PER_SERVER}
				>
					<Plus size={14} weight="bold" /> Create Role
				</Button>

				<div className={styles.rolesList}>
					{editableRoles.map((role) => {
						const selected = role.id === selectedRoleId;
						return (
							<div
								key={role.id}
								draggable
								onDragStart={(e) => handleDragStart(e, role.id)}
								onDragOver={(e) => handleDragOver(e, role.id)}
								onDragLeave={() => setDragOverId((id) => (id === role.id ? null : id))}
								onDrop={(e) => handleDrop(e, role.id)}
								onClick={() => setSelectedRoleId(role.id)}
								className={`${styles.roleItem} ${selected ? styles.roleItemSelected : ''} ${dragOverId === role.id ? styles.roleItemDragOver : ''}`}
							>
								<span
									className={styles.roleDot}
									style={{ backgroundColor: role.color || 'var(--text-primary-muted, #a0a3a8)' }}
								/>
								<span className={styles.roleName}>{role.name}</span>
								<span className={styles.rolePower}>PL {role.powerLevel}</span>
							</div>
						);
					})}
					{everyone && (
						<div
							className={`${styles.roleItem} ${styles.roleItemEveryone} ${selectedRoleId === 'everyone' ? styles.roleItemSelected : ''}`}
							onClick={() => setSelectedRoleId('everyone')}
						>
							<span className={styles.roleDot} style={{ backgroundColor: 'var(--text-primary-muted, #a0a3a8)' }} />
							<span className={styles.roleName}>@everyone</span>
							<span className={styles.rolePower}>PL 0</span>
						</div>
					)}
				</div>

				{error && <div className={styles.error}>{error}</div>}
			</div>

			<div className={styles.editor}>
				{selectedRole ? (
					<RoleEditor
						serverId={serverId}
						role={selectedRole}
						readOnly={selectedRole.id === 'everyone'}
					/>
				) : (
					<div className={styles.placeholder}>
						Select a role on the left to edit, or create a new one.
					</div>
				)}
			</div>
		</div>
	);
});
