<script lang="ts">
	import { CodeXml, ExternalLink } from '@lucide/svelte';

	import { Button } from '$lib/components/ui/button';
	import * as Dialog from '$lib/components/ui/sheet/index.js';
	import Code from '$lib/components/chat/markdown/Code.svelte';
	import { useSvelteFlow } from '@xyflow/svelte';
	import { breakpointsState } from '$lib/state/breakpoints.svelte';
	import { modelsState } from '$lib/state/models.svelte';

	type Instruction = {
		library: string;
		doc_link: string;
		install: string;
		code: string;
	};

	type Language = {
		language: string;
		instructions: Instruction[];
	};

	const { getNodes } = useSvelteFlow();
	let firstModelSelection = $derived(
		(getNodes()?.[0]?.data as { selectedModels?: string[] })?.selectedModels?.[0] ??
			(modelsState.models[0]?.id as string) ??
			''
	);

	const instructions: Language[] = $derived([
		{
			language: 'Javascript',
			instructions: [
				{
					library: 'openai',
					doc_link: 'https://platform.openai.com/docs/libraries',
					install: 'npm install --save openai',
					code: `import { OpenAI } from "openai";";

const client = new OpenAI({
	baseURL: "https://router.huggingface.co/v1",
	apiKey: process.env.HF_TOKEN,
});

const stream = await client.chat.completions.create({
    model: "${firstModelSelection}",
    messages: [
		{ role: "user", content: "What is the capital of France?" }
    ],
    stream: true,
});

for await (const chunk of stream) {
    process.stdout.write(chunk.choices[0]?.delta?.content || "");
}`
				},
				{
					library: 'huggingface.js',
					doc_link: 'https://huggingface.co/docs/huggingface.js/inference/README',
					install: 'npm install --save @huggingface/inference',
					code: `import { InferenceClient } from "@huggingface/inference";

const client = new InferenceClient(process.env.HF_TOKEN);

let out = "";

const stream = client.chatCompletionStream({
    model: "${firstModelSelection}",
    messages: [
		{ role: "user", content: "What is the capital of France?" }
    ],
});

for await (const chunk of stream) {
	if (chunk.choices && chunk.choices.length > 0) {
		const newContent = chunk.choices[0].delta.content;
		out += newContent;
		console.log(newContent);
	}
}`
				}
			]
		},
		{
			language: 'Python',
			instructions: [
				{
					library: 'openai',
					doc_link: 'https://platform.openai.com/docs/libraries',
					install: 'pip install --upgrade openai',
					code: `import os
from openai import OpenAI

client = OpenAI(
    base_url="https://router.huggingface.co/v1",
    api_key=os.environ.get("HF_TOKEN"),
)

stream = client.chat.completions.create(
    model="${firstModelSelection}",
    messages=[{"role": "user", "content": "What is the capital of France?"}],
    stream=True,
)
for chunk in stream:
    print(chunk.choices[0].delta.content, end="")`
				},
				{
					library: 'huggingface_hub',
					doc_link: 'https://huggingface.co/docs/huggingface_hub/guides/inference',
					install: 'pip install --upgrade huggingface_hub',
					code: `import os
from huggingface_hub import InferenceClient

client = InferenceClient(
    api_key=os.environ["HF_TOKEN"],
)

stream = client.chat.completions.create(
    model="${firstModelSelection}",
    messages=[{"role": "user", "content": "What is the capital of France?"}],
    stream=True,
)

for chunk in stream:
    print(chunk.choices[0].delta.content, end="")`
				},
				{
					library: 'requests',
					doc_link: 'https://requests.readthedocs.io/en/latest/',
					install: 'pip install requests',
					code: `import os
import json
import requests

API_URL = "https://router.huggingface.co/v1/chat/completions"
headers = {"Authorization": f"Bearer {os.environ['HF_TOKEN']}"}

def query(payload):
    response = requests.post(API_URL, headers=headers, json=payload, stream=True)
    for line in response.iter_lines():
        if not line.startswith(b"data:"):
            continue
        if line.strip() == b"data: [DONE]":
            return
        yield json.loads(line.decode("utf-8").lstrip("data:"))

chunks = query({
    "messages": [{"role": "user", "content": "What is the capital of France?"}],
    "model": "${firstModelSelection}",
    "stream": True,
})
for chunk in chunks:
    print(chunk["choices"][0]["delta"]["content"], end="")`
				}
			]
		},
		{
			language: 'cURL',
			instructions: [
				{
					library: 'curl',
					doc_link: 'https://huggingface.co/docs/api-inference/getting-started',
					install: '',
					code: `curl https://router.huggingface.co/v1/chat/completions \\
  -H "Authorization: Bearer $HF_TOKEN" \\
  -H "Content-Type: application/json" \\
  -d '{
    "model": "${firstModelSelection}",
    "messages": [
      { "role": "user", "content": "What is the capital of France?" }
    ],
    "stream": true
  }'`
				}
			]
		}
	]);

	let open = $state(false);
	let selectedLanguage = $state<string>('Javascript');
	let selectedLibrary = $state<string>('openai');

	let languageData = $derived(instructions.find((i) => i.language === selectedLanguage));
	let libraryData = $derived(languageData?.instructions.find((i) => i.library === selectedLibrary));
	let showLibraryTabs = $derived((languageData?.instructions.length ?? 0) > 1);

	function selectLanguage(lang: string) {
		selectedLanguage = lang;
		const langData = instructions.find((i) => i.language === lang);
		if (langData) selectedLibrary = langData.instructions[0].library;
	}
</script>

<Dialog.Root bind:open>
	<Dialog.Trigger class="">
		<Button variant="outline" size={breakpointsState.isMobile ? 'icon-sm' : 'default'}>
			<CodeXml />
			{#if !breakpointsState.isMobile}
				How to use the API
			{/if}
		</Button>
	</Dialog.Trigger>

	<Dialog.Content class="max-w-xl! gap-0! p-0!">
		<Dialog.Header class="mb-0 gap-1! rounded-none border-b p-5">
			<Dialog.Title>Use the API</Dialog.Title>
			<Dialog.Description>How to use the API in your application.</Dialog.Description>
		</Dialog.Header>

		<div class="space-y-4 p-5">
			<div class="flex items-center gap-1.5">
				{#each instructions as lang}
					<Button
						variant={selectedLanguage === lang.language ? 'default' : 'outline'}
						size="default"
						onclick={() => selectLanguage(lang.language)}
					>
						{lang.language}
					</Button>
				{/each}
			</div>

			{#if showLibraryTabs && languageData}
				<div class="flex items-center gap-1.5">
					{#each languageData.instructions as instr}
						<Button
							variant={selectedLibrary === instr.library ? 'outline-blue' : 'outline'}
							size="xs"
							class="rounded-full!"
							onclick={() => (selectedLibrary = instr.library)}
						>
							{instr.library}
						</Button>
					{/each}
				</div>
			{/if}

			{#if libraryData}
				{#if libraryData.install}
					<div class="overflow-hidden rounded-lg border border-border">
						<div class="flex items-center justify-between border-b border-border px-3.5 py-2.5">
							<p class="text-xs font-semibold text-primary">Install</p>
						</div>
						<Code text={libraryData.install} className="" />
					</div>
				{/if}

				<div class="overflow-hidden rounded-lg border border-border">
					<div class="flex items-center justify-between border-b border-border px-3.5 py-2.5">
						<p class="text-xs font-semibold text-primary">Streaming API</p>
						<div class="flex items-center gap-1.5">
							<a href={libraryData.doc_link} target="_blank" rel="noopener noreferrer">
								<Button variant="outline" size="2xs">
									<ExternalLink class="size-3.5" />
									View documentation
								</Button>
							</a>
						</div>
					</div>
					<Code text={libraryData.code} className="" />
				</div>
			{/if}
		</div>
	</Dialog.Content>
</Dialog.Root>
