/**
 * RoleEditor — right-hand panel of the Roles tab. Lets the admin
 * edit a single role's name, color, and power level. Below the PL
 * slider there's a live "abilities readout" driven by
 * RoleManager.describePowerLevel, so admins see exactly which
 * homeserver-enforced actions the chosen PL grants.
 *
 * Changes are saved via an explicit Save button — the form is dirty-
 * tracked so Save is disabled until the user has made a real change.
 * Deletion is its own button at the bottom with a confirm prompt.
 *
 * The @everyone entry passes `readOnly` and gets a short explanation
 * instead of an editable form, since @everyone is synthetic and its
 * permissions come from the room's baseline power level defaults.
 */
import { observer } from 'mobx-react-lite';
import { useEffect, useMemo, useState } from 'react';
import { Trash, CheckCircle, XCircle } from '@phosphor-icons/react';
import { Button } from '@brycord/ui';
import { RoleManager } from '@brycord/matrix-client';
import type { Role, PowerLevelAbilities } from '@brycord/matrix-client';
import RoleStore from '@app/stores/RoleStore';
import styles from './RoleEditor.module.css';

interface RoleEditorProps {
	serverId: string;
	role: Role;
	readOnly?: boolean;
}

// A small, curated palette of Discord-like role colors plus a "no
// color" swatch. Admins can always type a custom hex too.
const COLOR_SWATCHES: Array<{ hex: string; name: string }> = [
	{ hex: '#99AAB5', name: 'Default' },
	{ hex: '#1ABC9C', name: 'Teal' },
	{ hex: '#2ECC71', name: 'Green' },
	{ hex: '#3498DB', name: 'Blue' },
	{ hex: '#9B59B6', name: 'Purple' },
	{ hex: '#E91E63', name: 'Magenta' },
	{ hex: '#F1C40F', name: 'Yellow' },
	{ hex: '#E67E22', name: 'Orange' },
	{ hex: '#E74C3C', name: 'Red' },
	{ hex: '#95A5A6', name: 'Gray' },
	{ hex: '#607D8B', name: 'Slate' },
];

const HEX_REGEX = /^#[0-9a-fA-F]{6}$/;

export const RoleEditor = observer(function RoleEditor({ serverId, role, readOnly }: RoleEditorProps) {
	const [name, setName] = useState(role.name);
	const [color, setColor] = useState<string | undefined>(role.color);
	const [powerLevel, setPowerLevel] = useState(role.powerLevel);
	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);

	// Reset local form state whenever the selected role changes.
	useEffect(() => {
		setName(role.name);
		setColor(role.color);
		setPowerLevel(role.powerLevel);
		setStatus(null);
		setConfirmDelete(false);
	}, [role.id]);

	// Compute what abilities the current slider PL unlocks — reads the
	// space's live `m.room.power_levels` via RoleManager so the list
	// reflects reality (admins may have customized thresholds).
	const abilities: PowerLevelAbilities = useMemo(
		() => RoleManager.getInstance().describePowerLevel(serverId, powerLevel),
		[serverId, powerLevel],
	);

	const trimmedName = name.trim();
	const isDirty =
		trimmedName !== role.name ||
		(color ?? undefined) !== (role.color ?? undefined) ||
		powerLevel !== role.powerLevel;
	const nameValid = trimmedName.length > 0 && trimmedName.length <= 32;
	const canSave = isDirty && nameValid && !saving && !readOnly;

	const handleSave = async () => {
		if (!canSave) return;
		setSaving(true);
		setStatus(null);
		try {
			await RoleManager.getInstance().updateRole(serverId, role.id, {
				name: trimmedName,
				color: color,
				powerLevel,
			});
			// Optimistically update the store so the left-column list
			// reflects the new values immediately.
			RoleStore.handleRoleUpdated(serverId, {
				...role,
				name: trimmedName,
				color,
				powerLevel,
			});
			setStatus({ type: 'success', message: 'Role saved.' });
		} catch (err: any) {
			setStatus({ type: 'error', message: err?.message || 'Failed to save role.' });
		} finally {
			setSaving(false);
		}
	};

	const handleDelete = async () => {
		if (readOnly || deleting) return;
		if (!confirmDelete) {
			setConfirmDelete(true);
			return;
		}
		setDeleting(true);
		setStatus(null);
		try {
			await RoleManager.getInstance().deleteRole(serverId, role.id);
			RoleStore.handleRoleDeleted(serverId, role.id);
		} catch (err: any) {
			setStatus({ type: 'error', message: err?.message || 'Failed to delete role.' });
			setDeleting(false);
		}
	};

	if (readOnly) {
		return (
			<div className={styles.container}>
				<div className={styles.header}>
					<h2 className={styles.heading}>{role.name}</h2>
				</div>
				<div className={styles.readOnlyNote}>
					<p>
						<strong>@everyone</strong> is the baseline role every member
						has. Its abilities come from the server's default power
						level thresholds in <code>m.room.power_levels</code>, not
						from a per-role configuration.
					</p>
					<p>
						To change what @everyone can do, edit the baseline power
						level values directly (channel-level permission editing
						will arrive in a future update).
					</p>
				</div>
				<AbilitiesReadout powerLevel={0} abilities={
					RoleManager.getInstance().describePowerLevel(serverId, 0)
				} />
			</div>
		);
	}

	return (
		<div className={styles.container}>
			<div className={styles.header}>
				<h2 className={styles.heading}>Edit Role</h2>
			</div>

			<div className={styles.field}>
				<label className={styles.label}>
					Role Name
					<input
						type="text"
						className={styles.input}
						value={name}
						onChange={(e) => setName(e.target.value)}
						maxLength={40}
						placeholder="new role"
					/>
				</label>
				<span className={`${styles.counter} ${trimmedName.length > 32 ? styles.counterBad : ''}`}>
					{trimmedName.length}/32
				</span>
			</div>

			<div className={styles.field}>
				<span className={styles.label}>Role Color</span>
				<div className={styles.swatchRow}>
					<button
						type="button"
						className={`${styles.swatch} ${!color ? styles.swatchActive : ''} ${styles.swatchNone}`}
						onClick={() => setColor(undefined)}
						aria-label="No color"
					>
						<XCircle size={16} weight="bold" />
					</button>
					{COLOR_SWATCHES.map((s) => (
						<button
							key={s.hex}
							type="button"
							className={`${styles.swatch} ${color === s.hex ? styles.swatchActive : ''}`}
							style={{ backgroundColor: s.hex }}
							onClick={() => setColor(s.hex)}
							aria-label={s.name}
						/>
					))}
				</div>
				<input
					type="text"
					className={styles.hexInput}
					value={color ?? ''}
					placeholder="#5865F2"
					onChange={(e) => {
						const val = e.target.value;
						if (val === '' || HEX_REGEX.test(val)) {
							setColor(val || undefined);
						} else if (val.startsWith('#') && val.length <= 7) {
							// Let the user type hex chars without immediate validation
							setColor(val);
						}
					}}
				/>
			</div>

			<div className={styles.field}>
				<div className={styles.powerHeader}>
					<span className={styles.label}>Power Level</span>
					<span className={styles.powerValue}>{powerLevel}</span>
				</div>
				<input
					type="range"
					min={0}
					max={100}
					value={powerLevel}
					onChange={(e) => setPowerLevel(Number(e.target.value))}
					className={styles.slider}
				/>
				<p className={styles.powerHint}>
					Power level determines what members with this role can do
					at the Matrix protocol layer. Multiple roles can share the
					same power level — they'll have identical abilities but
					different names and colors.
				</p>
			</div>

			<AbilitiesReadout powerLevel={powerLevel} abilities={abilities} />

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

			<div className={styles.actions}>
				<Button variant="primary" onClick={handleSave} disabled={!canSave}>
					{saving ? 'Saving…' : 'Save Role'}
				</Button>
				<Button
					variant="danger"
					onClick={handleDelete}
					disabled={deleting}
				>
					<Trash size={14} weight="fill" />
					{confirmDelete ? 'Click again to confirm' : 'Delete Role'}
				</Button>
			</div>
		</div>
	);
});

// ── Abilities readout ──────────────────────────────────────────────

const ABILITY_LABELS: Array<{ key: keyof PowerLevelAbilities; label: string }> = [
	{ key: 'canSendMessages', label: 'Send messages' },
	{ key: 'canInvite', label: 'Invite members' },
	{ key: 'canRenameNicknames', label: 'Rename other members' },
	{ key: 'canRedact', label: "Delete others' messages" },
	{ key: 'canKick', label: 'Kick members' },
	{ key: 'canBan', label: 'Ban members' },
	{ key: 'canSendState', label: 'Send room state events' },
	{ key: 'canRenameChannels', label: 'Rename channels' },
	{ key: 'canManageRoles', label: 'Manage roles' },
	{ key: 'canEditPowerLevels', label: 'Edit server power levels' },
];

function AbilitiesReadout({
	powerLevel,
	abilities,
}: {
	powerLevel: number;
	abilities: PowerLevelAbilities;
}) {
	return (
		<div className={styles.abilities}>
			<div className={styles.abilitiesHeader}>
				At power level <strong>{powerLevel}</strong>, members with this role can:
			</div>
			<ul className={styles.abilitiesList}>
				{ABILITY_LABELS.map(({ key, label }) => {
					const allowed = abilities[key];
					return (
						<li key={key} className={allowed ? styles.abilityOn : styles.abilityOff}>
							{allowed ? (
								<CheckCircle size={14} weight="fill" />
							) : (
								<XCircle size={14} weight="fill" />
							)}
							<span>{label}</span>
						</li>
					);
				})}
			</ul>
		</div>
	);
}
