<script lang="ts">
	import type { PageData } from './$types';
	import type { Repository } from '$lib/types';
	import RepositoryCard from '$lib/components/RepositoryCard.svelte';
	import AddRepositoryModal from '$lib/components/AddRepositoryModal.svelte';
	import ConfirmDialog from '$lib/components/ConfirmDialog.svelte';
	import IndexingProgress from '$lib/components/IndexingProgress.svelte';

	let { data }: { data: PageData } = $props();

	// Local mutable copy; refreshRepositories() keeps it up to date after mutations.
	// Intentionally captures initial value from server load — mutations happen via fetch.
	let repositories = $state<Repository[]>(data.repositories ?? []); // svelte-disable state_referenced_locally
	let showAddModal = $state(false);
	let confirmDeleteId = $state<string | null>(null);
	let activeJobIds = $state<Record<string, string>>({});
	let errorMessage = $state<string | null>(null);

	const confirmDeleteRepo = $derived(
		confirmDeleteId ? repositories.find((r) => r.id === confirmDeleteId) : null
	);

	async function refreshRepositories() {
		try {
			const res = await fetch('/api/v1/libs');
			const fetched = await res.json();
			repositories = fetched.libraries ?? [];
		} catch {
			// keep existing list on network error
		}
	}

	async function handleReindex(id: string) {
		errorMessage = null;
		try {
			const res = await fetch(`/api/v1/libs/${encodeURIComponent(id)}/index`, {
				method: 'POST'
			});
			if (!res.ok) {
				const fetched = await res.json();
				throw new Error(fetched.error ?? 'Failed to trigger re-indexing');
			}
			const fetched = await res.json();
			if (fetched.job?.id) {
				activeJobIds = { ...activeJobIds, [id]: fetched.job.id };
			}
			await refreshRepositories();
		} catch (e) {
			errorMessage = (e as Error).message;
		}
	}

	function handleDeleteRequest(id: string) {
		confirmDeleteId = id;
	}

	async function handleDeleteConfirm() {
		if (!confirmDeleteId) return;
		const id = confirmDeleteId;
		confirmDeleteId = null;
		errorMessage = null;
		try {
			const res = await fetch(`/api/v1/libs/${encodeURIComponent(id)}`, {
				method: 'DELETE'
			});
			if (!res.ok && res.status !== 204) {
				const fetched = await res.json();
				throw new Error(fetched.error ?? 'Failed to delete repository');
			}
			repositories = repositories.filter((r) => r.id !== id);
			const updated = { ...activeJobIds };
			delete updated[id];
			activeJobIds = updated;
		} catch (e) {
			errorMessage = (e as Error).message;
		}
	}

	function handleDeleteCancel() {
		confirmDeleteId = null;
	}

	async function handleRepoAdded() {
		await refreshRepositories();
	}
</script>

<svelte:head>
	<title>Repositories — TrueRef</title>
</svelte:head>

<div class="flex items-center justify-between">
	<div>
		<h1 class="text-xl font-semibold text-gray-900">Repositories</h1>
		<p class="mt-0.5 text-sm text-gray-500">
			{repositories.length}
			{repositories.length === 1 ? 'repository' : 'repositories'} indexed
		</p>
	</div>
	<button
		onclick={() => (showAddModal = true)}
		class="flex items-center gap-1.5 rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-700"
	>
		<svg class="h-4 w-4" viewBox="0 0 20 20" fill="currentColor">
			<path
				d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z"
			/>
		</svg>
		Add Repository
	</button>
</div>

{#if errorMessage}
	<div class="mt-4 rounded-lg bg-red-50 px-4 py-3">
		<p class="text-sm text-red-700">{errorMessage}</p>
	</div>
{/if}

{#if repositories.length === 0}
	<div class="mt-16 flex flex-col items-center text-center">
		<svg
			class="h-16 w-16 text-gray-300"
			viewBox="0 0 24 24"
			fill="none"
			stroke="currentColor"
			stroke-width="1.5"
		>
			<path
				stroke-linecap="round"
				stroke-linejoin="round"
				d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"
			/>
		</svg>
		<h2 class="mt-4 text-lg font-medium text-gray-700">No repositories yet</h2>
		<p class="mt-2 max-w-sm text-sm text-gray-500">
			Add your first GitHub or local repository to start indexing documentation for AI-powered
			retrieval.
		</p>
		<button
			onclick={() => (showAddModal = true)}
			class="mt-6 flex items-center gap-1.5 rounded-lg bg-blue-600 px-5 py-2.5 text-sm font-medium text-white hover:bg-blue-700"
		>
			<svg class="h-4 w-4" viewBox="0 0 20 20" fill="currentColor">
				<path
					d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z"
				/>
			</svg>
			Add Repository
		</button>
	</div>
{:else}
	<div class="mt-6 grid gap-4 sm:grid-cols-1 lg:grid-cols-2">
		{#each repositories as repo (repo.id)}
			<div>
				<RepositoryCard {repo} onReindex={handleReindex} onDelete={handleDeleteRequest} />
				{#if activeJobIds[repo.id]}
					<div class="px-5">
						<IndexingProgress jobId={activeJobIds[repo.id]} />
					</div>
				{/if}
			</div>
		{/each}
	</div>
{/if}

{#if showAddModal}
	<AddRepositoryModal onClose={() => (showAddModal = false)} onAdded={handleRepoAdded} />
{/if}

{#if confirmDeleteId && confirmDeleteRepo}
	<ConfirmDialog
		title="Delete Repository"
		message="Are you sure you want to delete {confirmDeleteRepo.title}? This will remove all indexed data and cannot be undone."
		confirmLabel="Delete"
		danger={true}
		onConfirm={handleDeleteConfirm}
		onCancel={handleDeleteCancel}
	/>
{/if}
