<script lang="ts">
	import { cn } from '$lib/components/ui/utils';
	import { mcpStore } from '$lib/stores/mcp.svelte';
	import { mcpResources, mcpResourcesLoading } from '$lib/stores/mcp-resources.svelte';
	import type { MCPServerResources, MCPResourceInfo, MCPResourceTemplateInfo } from '$lib/types';
	import { SvelteMap, SvelteSet } from 'svelte/reactivity';
	import { parseResourcePath } from '$lib/utils';
	import McpResourceBrowserHeader from './McpResourceBrowserHeader.svelte';
	import McpResourceBrowserEmptyState from './McpResourceBrowserEmptyState.svelte';
	import McpResourceBrowserServerItem from './McpResourceBrowserServerItem.svelte';

	interface Props {
		onSelect?: (resource: MCPResourceInfo, shiftKey?: boolean) => void;
		onToggle?: (resource: MCPResourceInfo, checked: boolean) => void;
		onTemplateSelect?: (template: MCPResourceTemplateInfo) => void;
		selectedUris?: Set<string>;
		selectedTemplateUri?: string | null;
		expandToUri?: string;
		class?: string;
	}

	let {
		onSelect,
		onToggle,
		onTemplateSelect,
		selectedUris = new Set(),
		selectedTemplateUri,
		expandToUri,
		class: className
	}: Props = $props();

	let expandedServers = new SvelteSet<string>();
	let expandedFolders = new SvelteSet<string>();
	let searchQuery = $state('');

	const resources = $derived(mcpResources());
	const isLoading = $derived(mcpResourcesLoading());

	const filteredResources = $derived.by(() => {
		if (!searchQuery.trim()) {
			return resources;
		}

		const query = searchQuery.toLowerCase();
		const filtered = new SvelteMap();

		for (const [serverName, serverRes] of resources.entries()) {
			const filteredResources = serverRes.resources.filter((r) => {
				return (
					r.title?.toLowerCase().includes(query) ||
					r.uri.toLowerCase().includes(query) ||
					serverName.toLowerCase().includes(query)
				);
			});

			const filteredTemplates = serverRes.templates.filter((t) => {
				return (
					t.name?.toLowerCase().includes(query) ||
					t.title?.toLowerCase().includes(query) ||
					t.uriTemplate.toLowerCase().includes(query) ||
					serverName.toLowerCase().includes(query)
				);
			});

			if (filteredResources.length > 0 || filteredTemplates.length > 0 || query.trim()) {
				filtered.set(serverName, {
					...serverRes,
					resources: filteredResources,
					templates: filteredTemplates
				});
			}
		}

		return filtered;
	});

	$effect(() => {
		if (expandToUri && resources.size > 0) {
			autoExpandToResource(expandToUri);
		}
	});

	function autoExpandToResource(uri: string) {
		for (const [serverName, serverRes] of resources.entries()) {
			const resource = serverRes.resources.find((r) => r.uri === uri);
			if (resource) {
				expandedServers.add(serverName);

				const pathParts = parseResourcePath(uri);
				if (pathParts.length > 1) {
					let currentPath = '';
					for (let i = 0; i < pathParts.length - 1; i++) {
						currentPath = `${currentPath}/${pathParts[i]}`;
						const folderId = `${serverName}:${currentPath}`;
						expandedFolders.add(folderId);
					}
				}
				break;
			}
		}
	}

	function toggleServer(serverName: string) {
		if (expandedServers.has(serverName)) {
			expandedServers.delete(serverName);
		} else {
			expandedServers.add(serverName);
		}
	}

	function toggleFolder(folderId: string) {
		if (expandedFolders.has(folderId)) {
			expandedFolders.delete(folderId);
		} else {
			expandedFolders.add(folderId);
		}
	}

	function handleRefresh() {
		mcpStore.fetchAllResources();
	}
</script>

<div class={cn('flex flex-col gap-2', className)}>
	<McpResourceBrowserHeader
		{isLoading}
		onRefresh={handleRefresh}
		onSearch={(q) => (searchQuery = q)}
		{searchQuery}
	/>

	<div class="flex flex-col gap-1">
		{#if filteredResources.size === 0}
			<McpResourceBrowserEmptyState {isLoading} />
		{:else}
			{#each [...filteredResources.entries()] as [serverName, serverRes] (serverName)}
				<McpResourceBrowserServerItem
					serverName={serverName as string}
					serverRes={serverRes as MCPServerResources}
					isExpanded={expandedServers.has(serverName as string)}
					{selectedUris}
					{selectedTemplateUri}
					{expandedFolders}
					onToggleServer={() => toggleServer(serverName as string)}
					onToggleFolder={toggleFolder}
					{onSelect}
					{onToggle}
					{onTemplateSelect}
					{searchQuery}
				/>
			{/each}
		{/if}
	</div>
</div>