<script lang="ts">
	import { OverrideLevel, ToolType } from '$lib/proto/llm_multiverse/v1/common_pb';
	import type { SessionConfig } from '$lib/proto/llm_multiverse/v1/orchestrator_pb';
	import { SessionConfigSchema } from '$lib/proto/llm_multiverse/v1/orchestrator_pb';
	import { create } from '@bufbuild/protobuf';
	import { presetStore } from '$lib/stores/presets.svelte';
	import { isNonDefaultConfig } from '$lib/utils/sessionConfig';
	import Backdrop from '$lib/components/Backdrop.svelte';

	let {
		config,
		onConfigChange,
		onClose
	}: {
		config: SessionConfig;
		onConfigChange: (config: SessionConfig) => void;
		onClose?: () => void;
	} = $props();

	let newPermission = $state('');
	let newPresetName = $state('');
	let showSavePreset = $state(false);
	let saveError = $state('');

	const toolTypes = [
		{ value: ToolType.MEMORY_READ, label: 'Memory Read' },
		{ value: ToolType.MEMORY_WRITE, label: 'Memory Write' },
		{ value: ToolType.WEB_SEARCH, label: 'Web Search' },
		{ value: ToolType.FS_READ, label: 'FS Read' },
		{ value: ToolType.FS_WRITE, label: 'FS Write' },
		{ value: ToolType.RUN_CODE, label: 'Run Code' },
		{ value: ToolType.RUN_SHELL, label: 'Run Shell' },
		{ value: ToolType.PACKAGE_INSTALL, label: 'Package Install' }
	];

	const overrideLevels = [
		{ value: OverrideLevel.NONE, label: 'None', description: 'Full enforcement' },
		{ value: OverrideLevel.RELAX, label: 'Relax', description: 'High-risk tools unlocked' },
		{ value: OverrideLevel.ALL, label: 'All', description: 'No enforcement' }
	];

	const isNonDefault = $derived(isNonDefaultConfig(config));

	function setOverrideLevel(level: OverrideLevel) {
		const updated = create(SessionConfigSchema, {
			...config,
			overrideLevel: level
		});
		onConfigChange(updated);
	}

	function toggleTool(tool: string) {
		const disabled = [...config.disabledTools];
		const idx = disabled.indexOf(tool);
		if (idx >= 0) {
			disabled.splice(idx, 1);
		} else {
			disabled.push(tool);
		}
		const updated = create(SessionConfigSchema, {
			...config,
			disabledTools: disabled
		});
		onConfigChange(updated);
	}

	function addPermission() {
		const trimmed = newPermission.trim();
		if (!trimmed || config.grantedPermissions.includes(trimmed)) return;
		const updated = create(SessionConfigSchema, {
			...config,
			grantedPermissions: [...config.grantedPermissions, trimmed]
		});
		onConfigChange(updated);
		newPermission = '';
	}

	function removePermission(perm: string) {
		const updated = create(SessionConfigSchema, {
			...config,
			grantedPermissions: config.grantedPermissions.filter((p) => p !== perm)
		});
		onConfigChange(updated);
	}

	function resetConfig() {
		onConfigChange(create(SessionConfigSchema, { overrideLevel: OverrideLevel.NONE }));
	}

	function handleLoadPreset(name: string) {
		const presetConfig = presetStore.loadPreset(name);
		if (!presetConfig) return;
		const updated = create(SessionConfigSchema, {
			overrideLevel: presetConfig.overrideLevel,
			disabledTools: [...presetConfig.disabledTools],
			grantedPermissions: [...presetConfig.grantedPermissions]
		});
		onConfigChange(updated);
	}

	function handleSavePreset() {
		saveError = '';
		try {
			presetStore.savePreset(newPresetName, {
				overrideLevel: config.overrideLevel,
				disabledTools: [...config.disabledTools],
				grantedPermissions: [...config.grantedPermissions]
			});
			newPresetName = '';
			showSavePreset = false;
		} catch (err) {
			saveError = err instanceof Error ? err.message : 'Failed to save preset';
		}
	}

	function handleDeletePreset(name: string) {
		presetStore.deletePreset(name);
	}
</script>

{#if onClose}
	<Backdrop onClose={onClose} />
{/if}

<aside
	class="flex h-full w-72 flex-col border-l border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900
		fixed inset-y-0 right-0 z-50
		md:relative md:z-auto"
>
	<div class="flex items-center justify-between border-b border-gray-200 dark:border-gray-700 px-4 py-3">
		<div class="flex items-center gap-2">
			<h2 class="text-sm font-semibold text-gray-900 dark:text-gray-100">Session Config</h2>
			{#if isNonDefault}
				<span class="h-2 w-2 rounded-full bg-amber-500" title="Non-default config active"></span>
			{/if}
		</div>
		<div class="flex items-center gap-2">
			<button
				type="button"
				onclick={resetConfig}
				class="text-xs text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300"
			>
				Reset
			</button>
			{#if onClose}
				<button
					type="button"
					onclick={onClose}
					class="flex h-7 w-7 items-center justify-center rounded text-gray-400 dark:text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-gray-600 dark:hover:text-gray-300 md:hidden"
					aria-label="Close config sidebar"
				>
					&#10005;
				</button>
			{/if}
		</div>
	</div>

	<div class="flex-1 overflow-y-auto p-4 space-y-5">
		<!-- Presets -->
		<div>
			<p class="mb-2 text-xs font-medium text-gray-700 dark:text-gray-300">Presets</p>
			<div class="space-y-1">
				{#each presetStore.getAllPresets() as preset (preset.name)}
					<div class="flex items-center gap-1">
						<button
							type="button"
							onclick={() => handleLoadPreset(preset.name)}
							class="flex-1 rounded-lg px-3 py-1.5 text-left text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700"
						>
							{preset.name}
							{#if preset.builtIn}
								<span class="text-[10px] text-gray-400 dark:text-gray-500">built-in</span>
							{/if}
						</button>
						{#if !preset.builtIn}
							<button
								type="button"
								onclick={() => handleDeletePreset(preset.name)}
								class="rounded px-1.5 py-1 text-xs text-gray-400 dark:text-gray-500 hover:text-red-500"
							>
								&#10005;
							</button>
						{/if}
					</div>
				{/each}
			</div>
			{#if showSavePreset}
				<div class="mt-2 flex gap-1">
					<input
						type="text"
						bind:value={newPresetName}
						onkeydown={(e) => { if (e.key === 'Enter') handleSavePreset(); }}
						placeholder="Preset name"
						class="flex-1 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-2 py-1.5 text-xs text-gray-900 dark:text-gray-100 focus:border-blue-500 focus:outline-none"
					/>
					<button
						type="button"
						onclick={handleSavePreset}
						disabled={!newPresetName.trim()}
						class="rounded-lg bg-blue-50 dark:bg-blue-900/40 px-2 py-1.5 text-xs font-medium text-blue-700 dark:text-blue-300 hover:bg-blue-100 dark:hover:bg-blue-900/60 disabled:opacity-50"
					>
						Save
					</button>
					<button
						type="button"
						onclick={() => { showSavePreset = false; saveError = ''; newPresetName = ''; }}
						class="rounded-lg px-1.5 py-1.5 text-xs text-gray-400 dark:text-gray-500 hover:text-gray-600 dark:hover:text-gray-300"
					>
						&#10005;
					</button>
				</div>
				{#if saveError}
					<p class="mt-1 text-xs text-red-500">{saveError}</p>
				{/if}
			{:else}
				<button
					type="button"
					onclick={() => (showSavePreset = true)}
					class="mt-2 w-full rounded-lg border border-dashed border-gray-300 dark:border-gray-600 px-3 py-1.5 text-xs text-gray-500 dark:text-gray-400 hover:border-gray-400 dark:hover:border-gray-500 hover:text-gray-700 dark:hover:text-gray-300"
				>
					Save current as preset
				</button>
			{/if}
		</div>

		<!-- Override Level -->
		<div>
			<p class="mb-2 text-xs font-medium text-gray-700 dark:text-gray-300">Override Level</p>
			<div class="space-y-1">
				{#each overrideLevels as level (level.value)}
					<button
						type="button"
						onclick={() => setOverrideLevel(level.value)}
						class="flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left text-sm
							{config.overrideLevel === level.value
							? 'bg-blue-50 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 ring-1 ring-blue-200 dark:ring-blue-700'
							: 'text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700'}"
					>
						<span class="font-medium">{level.label}</span>
						<span class="text-xs text-gray-500 dark:text-gray-400">&mdash; {level.description}</span>
					</button>
				{/each}
			</div>
		</div>

		<!-- Disabled Tools -->
		<div>
			<p class="mb-2 text-xs font-medium text-gray-700 dark:text-gray-300">Disabled Tools</p>
			<div class="space-y-1">
				{#each toolTypes as tool (tool.value)}
					<label class="flex items-center gap-2 rounded px-2 py-1 text-sm hover:bg-gray-50 dark:hover:bg-gray-700">
						<input
							type="checkbox"
							checked={config.disabledTools.includes(tool.label)}
							onchange={() => toggleTool(tool.label)}
							class="rounded border-gray-300 dark:border-gray-600 text-blue-600"
						/>
						<span class="text-gray-700 dark:text-gray-300">{tool.label}</span>
					</label>
				{/each}
			</div>
		</div>

		<!-- Granted Permissions -->
		<div>
			<p class="mb-2 text-xs font-medium text-gray-700 dark:text-gray-300">Granted Permissions</p>
			<div class="flex gap-1">
				<input
					type="text"
					bind:value={newPermission}
					onkeydown={(e) => { if (e.key === 'Enter') addPermission(); }}
					placeholder="agent_type:tool"
					class="flex-1 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 px-2 py-1.5 text-xs text-gray-900 dark:text-gray-100 focus:border-blue-500 focus:outline-none"
				/>
				<button
					type="button"
					onclick={addPermission}
					class="rounded-lg bg-gray-100 dark:bg-gray-700 px-2 py-1.5 text-xs font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600"
				>
					Add
				</button>
			</div>
			{#if config.grantedPermissions.length > 0}
				<div class="mt-2 space-y-1">
					{#each config.grantedPermissions as perm (perm)}
						<div class="flex items-center justify-between rounded bg-gray-50 dark:bg-gray-800 px-2 py-1">
							<code class="text-xs text-gray-700 dark:text-gray-300">{perm}</code>
							<button
								type="button"
								onclick={() => removePermission(perm)}
								class="text-xs text-gray-400 dark:text-gray-500 hover:text-red-500"
							>
								&#10005;
							</button>
						</div>
					{/each}
				</div>
			{/if}
		</div>
	</div>
</aside>
