<script lang="ts">
	import { Settings } from '@lucide/svelte';
	import * as Sheet from '$lib/components/ui/sheet';
	import { Switch } from '$lib/components/ui/switch';
	import { McpActiveServersAvatars, SearchInput } from '$lib/components/app';
	import { conversationsStore } from '$lib/stores/conversations.svelte';
	import { mcpStore } from '$lib/stores/mcp.svelte';
	import { HealthCheckStatus } from '$lib/enums';
	import type { MCPServerSettingsEntry } from '$lib/types';

	interface Props {
		class?: string;
		disabled?: boolean;
		onSettingsClick?: () => void;
	}

	let { class: className = '', disabled = false, onSettingsClick }: Props = $props();

	let searchQuery = $state('');
	let mcpServers = $derived(mcpStore.getServersSorted().filter((s) => s.enabled));
	let hasMcpServers = $derived(mcpServers.length > 0);
	let enabledMcpServersForChat = $derived(
		mcpServers.filter((s) => conversationsStore.isMcpServerEnabledForChat(s.id) && s.url.trim())
	);
	let healthyEnabledMcpServers = $derived(
		enabledMcpServersForChat.filter((s) => {
			const healthState = mcpStore.getHealthCheckState(s.id);
			return healthState.status !== HealthCheckStatus.ERROR;
		})
	);
	let hasEnabledMcpServers = $derived(enabledMcpServersForChat.length > 0);
	let mcpFavicons = $derived(
		healthyEnabledMcpServers
			.slice(0, 3)
			.map((s) => ({ id: s.id, url: mcpStore.getServerFavicon(s.id) }))
			.filter((f) => f.url !== null)
	);
	let filteredMcpServers = $derived.by(() => {
		const query = searchQuery.toLowerCase().trim();
		if (query) {
			return mcpServers.filter((s) => {
				const name = getServerLabel(s).toLowerCase();
				const url = s.url.toLowerCase();
				return name.includes(query) || url.includes(query);
			});
		}
		return mcpServers;
	});

	let sheetOpen = $state(false);

	function getServerLabel(server: MCPServerSettingsEntry): string {
		return mcpStore.getServerLabel(server);
	}

	function handleOpenChange(open: boolean) {
		if (open) {
			sheetOpen = true;
			searchQuery = '';
			mcpStore.runHealthChecksForServers(mcpServers);
		} else {
			sheetOpen = false;
			searchQuery = '';
		}
	}

	function handleSheetOpenChange(open: boolean) {
		if (!open) {
			handleOpenChange(false);
		}
	}

	export function open() {
		handleOpenChange(true);
	}

	function isServerEnabledForChat(serverId: string): boolean {
		return conversationsStore.isMcpServerEnabledForChat(serverId);
	}

	async function toggleServerForChat(serverId: string) {
		await conversationsStore.toggleMcpServerForChat(serverId);
	}
</script>

{#if hasMcpServers}
	<button
		type="button"
		class="inline-flex cursor-pointer items-center gap-1.5 rounded-sm py-1 disabled:cursor-not-allowed disabled:opacity-60"
		{disabled}
		aria-label="MCP Servers"
		onclick={() => handleOpenChange(true)}
	>
		{#if hasEnabledMcpServers && mcpFavicons.length > 0}
			<McpActiveServersAvatars class={className} />
		{/if}
	</button>

	<Sheet.Root bind:open={sheetOpen} onOpenChange={handleSheetOpenChange}>
		<Sheet.Content side="bottom" class="max-h-[85vh] gap-1">
			<Sheet.Header>
				<Sheet.Title>MCP Servers</Sheet.Title>

				<Sheet.Description class="sr-only">
					Toggle MCP servers for the current conversation
				</Sheet.Description>
			</Sheet.Header>

			<div class="flex flex-col gap-1 pb-4">
				<div class="mb-3 px-4">
					<SearchInput placeholder="Search servers..." bind:value={searchQuery} />
				</div>

				<div class="max-h-[60vh] overflow-y-auto px-2">
					{#if filteredMcpServers.length === 0}
						<p class="px-3 py-3 text-center text-sm text-muted-foreground">No servers found.</p>
					{/if}

					{#each filteredMcpServers as server (server.id)}
						{@const healthState = mcpStore.getHealthCheckState(server.id)}
						{@const hasError = healthState.status === HealthCheckStatus.ERROR}
						{@const isEnabledForChat = isServerEnabledForChat(server.id)}

						<button
							type="button"
							class="flex w-full items-center justify-between gap-2 rounded-md px-3 py-2.5 text-left transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50"
							onclick={() => !hasError && toggleServerForChat(server.id)}
							disabled={hasError}
						>
							<div class="flex min-w-0 flex-1 items-center gap-2">
								{#if mcpStore.getServerFavicon(server.id)}
									<img
										src={mcpStore.getServerFavicon(server.id)}
										alt=""
										class="h-4 w-4 shrink-0 rounded-sm"
										onerror={(e) => {
											(e.currentTarget as HTMLImageElement).style.display = 'none';
										}}
									/>
								{/if}

								<span class="truncate text-sm">{getServerLabel(server)}</span>

								{#if hasError}
									<span
										class="shrink-0 rounded bg-destructive/15 px-1.5 py-0.5 text-xs text-destructive"
									>
										Error
									</span>
								{/if}
							</div>

							<Switch
								checked={isEnabledForChat}
								disabled={hasError}
								onclick={(e: MouseEvent) => e.stopPropagation()}
								onCheckedChange={() => toggleServerForChat(server.id)}
							/>
						</button>
					{/each}
				</div>

				<div class="mt-2 border-t px-2 pt-2">
					<button
						type="button"
						class="flex w-full cursor-pointer items-center gap-2 rounded-md px-3 py-2.5 text-sm transition-colors hover:bg-accent"
						onclick={() => {
							handleOpenChange(false);
							onSettingsClick?.();
						}}
					>
						<Settings class="h-4 w-4" />
						<span>Manage MCP Servers</span>
					</button>
				</div>
			</div>
		</Sheet.Content>
	</Sheet.Root>
{/if}
