<script lang="ts">
	import { createBubbler } from "svelte/legacy";

	const bubble = createBubbler();
	import type { PageData } from "./$types";

	import { isHuggingChat } from "$lib/utils/isHuggingChat";

	import { goto } from "$app/navigation";
	import { base } from "$app/paths";
	import { page } from "$app/state";

	import CarbonAdd from "~icons/carbon/add";
	import CarbonHelpFilled from "~icons/carbon/help-filled";
	import CarbonClose from "~icons/carbon/close";
	import CarbonArrowUpRight from "~icons/carbon/arrow-up-right";
	import CarbonEarthAmerica from "~icons/carbon/earth-americas-filled";
	import CarbonSearch from "~icons/carbon/search";
	import Pagination from "$lib/components/Pagination.svelte";
	import { getHref } from "$lib/utils/getHref";
	import { debounce } from "$lib/utils/debounce";
	import { isDesktop } from "$lib/utils/isDesktop";
	import { SortKey } from "$lib/types/Assistant";
	import ToolLogo from "$lib/components/ToolLogo.svelte";
	import { ReviewStatus } from "$lib/types/Review";
	import { useSettingsStore } from "$lib/stores/settings";
	import { loginModalOpen } from "$lib/stores/loginModal";

	interface Props {
		data: PageData;
	}

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

	const settings = useSettingsStore();

	const SEARCH_DEBOUNCE_DELAY = 400;
	let filterInputEl: HTMLInputElement | undefined = $state();
	let filterValue = $state(data.query);
	let isFilterInPorgress = false;
	let sortValue = $state(data.sort as SortKey);

	let showUnfeatured = $state(data.showUnfeatured);

	const resetFilter = () => {
		filterValue = "";
		isFilterInPorgress = false;
	};

	const filterOnName = debounce(async (value: string) => {
		filterValue = value;

		if (isFilterInPorgress) {
			return;
		}

		isFilterInPorgress = true;
		const newUrl = getHref(page.url, {
			newKeys: { q: value },
			existingKeys: { behaviour: "delete", keys: ["p"] },
		});
		await goto(newUrl);
		if (isDesktop(window)) {
			setTimeout(() => filterInputEl?.focus(), 0);
		}
		isFilterInPorgress = false;

		// there was a new filter query before server returned response
		if (filterValue !== value) {
			filterOnName(filterValue);
		}
	}, SEARCH_DEBOUNCE_DELAY);

	const sortTools = () => {
		const newUrl = getHref(page.url, {
			newKeys: { sort: sortValue },
			existingKeys: { behaviour: "delete", keys: ["p"] },
		});
		goto(newUrl);
	};

	const toggleShowUnfeatured = () => {
		showUnfeatured = !showUnfeatured;
		const newUrl = getHref(page.url, {
			newKeys: { showUnfeatured: showUnfeatured ? "true" : undefined },
			existingKeys: { behaviour: "delete", keys: [] },
		});
		goto(newUrl);
	};

	const goToActiveUrl = () => {
		return getHref(page.url, {
			newKeys: { active: "true" },
			existingKeys: { behaviour: "delete_except", keys: ["active", "sort"] },
		});
	};

	const goToCommunity = () => {
		return getHref(page.url, {
			existingKeys: { behaviour: "delete_except", keys: ["sort", "q"] },
		});
	};
	let activeOnly = $derived(page.url.searchParams.get("active") === "true");
	let tools = $derived(
		data.tools.filter((t) =>
			activeOnly ? data.settings.tools.some((toolId) => toolId === t._id.toString()) : true
		)
	);
	let toolsCreator = $derived(page.url.searchParams.get("user"));
	let createdByMe = $derived(data.user?.username && data.user.username === toolsCreator);
	let currentModelSupportTools = $derived(
		data.models.find((m) => m.id === $settings.activeModel)?.tools ?? false
	);
</script>

<div class="scrollbar-custom h-full overflow-y-auto py-12 max-sm:pt-8 md:py-24">
	<div class="pt-42 mx-auto flex flex-col px-5 xl:w-[60rem] 2xl:w-[64rem]">
		<div class="flex items-center">
			<h1 class="text-2xl font-bold">Tools</h1>
			{#if isHuggingChat}
				<div class="5 ml-1.5 rounded-lg text-xxs uppercase text-gray-500 dark:text-gray-500">
					beta
				</div>
				<a
					href="https://huggingface.co/spaces/huggingchat/chat-ui/discussions/357"
					class="ml-auto dark:text-gray-400 dark:hover:text-gray-300"
					target="_blank"
					aria-label="Hub discussion about tools"
				>
					<CarbonHelpFilled />
				</a>
			{/if}
		</div>
		<h2 class="text-gray-500">Popular tools made by the community</h2>
		<h3 class="mt-2 w-fit text-purple-700 dark:text-purple-300">
			This feature is <span
				class="rounded-lg bg-purple-100 px-2 py-1 font-semibold dark:bg-purple-800/50"
				>experimental</span
			>. Consider
			<a
				class="underline hover:text-purple-500"
				href="https://huggingface.co/spaces/huggingchat/chat-ui/discussions/569"
				target="_blank">sharing your feedback with us!</a
			>
		</h3>
		<div class="ml-auto mt-6 flex justify-between gap-2 max-sm:flex-col sm:items-center">
			{#if data.user?.isAdmin}
				<label class="mr-auto flex items-center gap-1 text-red-500" title="Admin only feature">
					<input type="checkbox" checked={showUnfeatured} onchange={toggleShowUnfeatured} />
					Show unfeatured tools
				</label>
			{/if}
			{#if page.data.loginRequired && !data.user}
				<button
					onclick={() => {
						$loginModalOpen = true;
					}}
					class="flex items-center gap-1 whitespace-nowrap rounded-lg border bg-white py-1 pl-1.5 pr-2.5 shadow-sm hover:bg-gray-50 hover:shadow-none dark:border-gray-600 dark:bg-gray-700 dark:hover:bg-gray-700"
				>
					<CarbonAdd />Create new tool
				</button>
			{:else}
				<a
					href={`${base}/tools/new`}
					class="flex items-center gap-1 whitespace-nowrap rounded-lg border bg-white py-1 pl-1.5 pr-2.5 shadow-sm hover:bg-gray-50 hover:shadow-none dark:border-gray-600 dark:bg-gray-700 dark:hover:bg-gray-700"
				>
					<CarbonAdd />Create new tool
				</a>
			{/if}
		</div>

		<div class="mb-4 mt-7 flex flex-wrap items-center gap-x-2 gap-y-3 text-sm">
			{#if toolsCreator && !createdByMe}
				<div
					class="flex items-center gap-1.5 rounded-full border border-gray-300 bg-gray-50 px-3 py-1 dark:border-gray-600 dark:bg-gray-700 dark:text-white"
				>
					{toolsCreator}'s tools
					<a
						href={getHref(page.url, {
							existingKeys: { behaviour: "delete", keys: ["user", "modelId", "p", "q"] },
						})}
						onclick={resetFilter}
						class="group"
						><CarbonClose
							class="text-xs group-hover:text-gray-800 dark:group-hover:text-gray-300"
						/></a
					>
				</div>
				{#if isHuggingChat}
					<a
						href="https://hf.co/{toolsCreator}"
						target="_blank"
						class="ml-auto flex items-center text-xs text-gray-500 underline hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-300"
						><CarbonArrowUpRight class="mr-1 flex-none text-[0.58rem]" target="_blank" />View {toolsCreator}
						on HF</a
					>
				{/if}
			{:else}
				<a
					href={goToActiveUrl()}
					class="flex items-center gap-1.5 rounded-full border px-3 py-1 {activeOnly
						? 'border-gray-300 bg-gray-50  dark:border-gray-600 dark:bg-gray-700 dark:text-white'
						: 'border-transparent text-gray-400 hover:text-gray-800 dark:hover:text-gray-300'}"
				>
					<CarbonEarthAmerica class="text-xs" />
					Active ({page.data.settings?.tools?.length})
				</a>
				<a
					href={goToCommunity()}
					class="flex items-center gap-1.5 rounded-full border px-3 py-1 {!activeOnly &&
					!toolsCreator
						? 'border-gray-300 bg-gray-50  dark:border-gray-600 dark:bg-gray-700 dark:text-white'
						: 'border-transparent text-gray-400 hover:text-gray-800 dark:hover:text-gray-300'}"
				>
					<CarbonEarthAmerica class="text-xs" />
					Community
				</a>
				{#if data.user?.username}
					<a
						href={getHref(page.url, {
							newKeys: { user: data.user.username },
							existingKeys: { behaviour: "delete", keys: ["modelId", "p", "q", "active"] },
						})}
						onclick={resetFilter}
						class="flex items-center gap-1.5 truncate rounded-full border px-3 py-1 {toolsCreator &&
						createdByMe
							? 'border-gray-300 bg-gray-50  dark:border-gray-600 dark:bg-gray-700 dark:text-white'
							: 'border-transparent text-gray-400 hover:text-gray-800 dark:hover:text-gray-300'}"
						>{data.user.username}
					</a>
				{/if}
			{/if}
			<div
				class="relative ml-auto flex h-[30px] w-40 items-center rounded-full border px-2 has-[:focus]:border-gray-400 dark:border-gray-600 sm:w-64"
			>
				<CarbonSearch class="pointer-events-none absolute left-2 text-xs text-gray-400" />
				<input
					class="h-[30px] w-full bg-transparent pl-5 focus:outline-none"
					placeholder="Filter by name"
					value={filterValue}
					oninput={(e) => filterOnName(e.currentTarget.value)}
					bind:this={filterInputEl}
					maxlength="150"
					type="search"
					aria-label="Filter tools by name"
				/>
			</div>
			<select
				bind:value={sortValue}
				onchange={sortTools}
				class="rounded-lg border border-gray-300 bg-gray-50 px-2 py-1 text-sm text-gray-900 focus:border-blue-700 focus:ring-blue-700 dark:border-gray-600 dark:bg-gray-700 dark:text-white dark:placeholder-gray-400"
				aria-label="Sort tools"
			>
				<option value={SortKey.TRENDING}>{SortKey.TRENDING}</option>
				<option value={SortKey.POPULAR}>{SortKey.POPULAR}</option>
			</select>
		</div>

		{#if !currentModelSupportTools}
			<div class="mx-auto text-center text-sm text-purple-700 dark:text-purple-300">
				You are currently not using a model that supports tools. Activate one
				<a href="{base}/models" class="underline">here</a>.
			</div>
		{/if}

		<div class="mt-4 grid grid-cols-1 gap-3 sm:gap-5 lg:grid-cols-2">
			{#each tools as tool}
				{@const isActive = (page.data.settings?.tools ?? []).includes(tool._id.toString())}
				{@const isOfficial = !tool.createdByName}
				<div
					onclick={() => goto(`${base}/tools/${tool._id.toString()}`)}
					onkeydown={(e) => e.key === "Enter" && goto(`${base}/tools/${tool._id.toString()}`)}
					role="button"
					tabindex="0"
					class="relative flex flex-row items-center gap-4 overflow-hidden text-balance rounded-xl border bg-gray-50/50 px-4 text-center shadow hover:bg-gray-50 hover:shadow-inner dark:bg-gray-950/20 dark:hover:bg-gray-950/40 max-sm:px-4 sm:h-24 {!(
						tool.review === ReviewStatus.APPROVED
					) && !isOfficial
						? ' border-red-500/30'
						: 'dark:border-gray-800/70'}"
					class:!border-blue-600={isActive}
				>
					{#key tool.color + tool.icon}
						<ToolLogo color={tool.color} icon={tool.icon} />
					{/key}
					<div class="flex h-full w-full flex-col items-start py-2 text-left">
						<span class="font-bold">
							<span class="w-full overflow-clip">
								{tool.displayName}
							</span>
							{#if isActive}
								<span
									class="mx-1.5 inline-flex items-center rounded-full bg-blue-600 px-2 py-0.5 text-xs font-semibold text-white"
									>Active</span
								>
							{/if}
						</span>
						<span class="line-clamp-1 font-mono text-xs text-gray-400">
							{tool.baseUrl ?? "Internal tool"}
						</span>

						<p class=" line-clamp-1 w-full text-sm text-gray-600 dark:text-gray-300">
							{tool.description}
						</p>

						{#if !isOfficial}
							<p class="mt-auto text-xs text-gray-400 dark:text-gray-500">
								Added by <a
									class="hover:underline"
									href="{base}/tools?user={tool.createdByName}"
									onclick={(e) => {
										e.stopPropagation();
										bubble("click");
									}}
								>
									{tool.createdByName}
								</a>
								<span class="text-gray-300">•</span>
								{#if tool.useCount === 1}
									1 run
								{:else}
									{tool.useCount} runs
								{/if}
							</p>
						{:else}
							<p class="mt-auto text-xs text-purple-700 dark:text-purple-400">
								HuggingChat official tool
							</p>
						{/if}
					</div>
				</div>
			{:else}
				{#if activeOnly}
					You don't have any active tools.
				{:else}
					No tools found
				{/if}
			{/each}
		</div>

		<Pagination
			classNames="w-full flex justify-center mt-14 mb-4"
			numItemsPerPage={data.numItemsPerPage}
			numTotalItems={data.numTotalItems}
		/>
	</div>
</div>
