<script lang="ts">
	import { page } from '$app/stores';
	import type { ProgressEvent } from '$lib/server/extraction';
	import UrlInputSection from './components/UrlInputSection.svelte';
	import ProgressIndicator from './components/ProgressIndicator.svelte';
	import ExtractedTextViewer from './components/ExtractedTextViewer.svelte';
	import RecipeCard from './components/RecipeCard.svelte';
	import ErrorState from './components/ErrorState.svelte';
	import LogViewer from './components/LogViewer.svelte';
	import LlmHealthIndicator from './components/LlmHealthIndicator.svelte';
	import ThumbnailPreview from './components/ThumbnailPreview.svelte';

	let status = $state('idle');
	let logs = $state<string[]>([]);
	let recipe = $state<any>(null);
	let bodyText = $state<string>('');
	let tandoorEnabled = $state(false);
	let tandoorImporting = $state(false);
	let tandoorError = $state<string | null>(null);
	let currentMethod = $state<string>('');
	let thumbnail = $state<string | null>(null);
	let thumbnailStatus = $state<'idle' | 'extracting' | 'success' | 'error'>('idle');

	// URL param parsing for Share Target
	// Instagram typically shares text that contains the URL, so we might need to parse it out
	let sharedText = $derived($page.url.searchParams.get('text') || '');
	let sharedUrl = $derived($page.url.searchParams.get('url') || '');

	function extractUrl(text: string) {
		const match = text.match(/(https?:\/\/[^\s]+)/);
		return match ? match[0] : null;
	}

	let targetUrl = $derived(sharedUrl || extractUrl(sharedText));

	$effect.pre(() => {
		loadTandoorConfig();
	});

	// Load Tandoor config on mount
	async function loadTandoorConfig() {
		try {
			const res = await fetch('/api/tandoor-config');
			const config = await res.json();
			tandoorEnabled = config.enabled;
			logs = [...logs, `Tandoor integration ${config.enabled ? 'enabled' : 'disabled'}`];
		} catch (e) {
			logs = [...logs, 'Failed to load Tandoor config'];
		}
	}

	// Map method names to icons
	function getMethodIcon(method?: string): string {
		const icons: Record<string, string> = {
			'embedded-json': '📦',
			'dom-selector': '🎯',
			'graphql-api': '🔌',
			legacy: '📄'
		};
		return method ? icons[method] || '⚙️' : '⚙️';
	}

	async function process() {
		if (!targetUrl) return;
		status = 'extracting';
		thumbnailStatus = 'extracting';
		logs = [...logs, '🚀 Starting extraction from: ' + targetUrl];
		currentMethod = '';

		try {
			const response = await fetch('/api/extract-stream', {
				method: 'POST',
				body: JSON.stringify({ url: targetUrl }),
				headers: { 'Content-Type': 'application/json' }
			});

			if (!response.body) {
				throw new Error('No response body');
			}

			const reader = response.body.getReader();
			const decoder = new TextDecoder();
			let buffer = '';

			while (true) {
				const { done, value } = await reader.read();

				if (done) break;

				buffer += decoder.decode(value, { stream: true });
				const lines = buffer.split('\n\n');
				buffer = lines.pop() || '';

				for (const line of lines) {
					if (!line.trim()) continue;

					const eventMatch = line.match(/^event: (\w+)\ndata: (.+)$/s);
					if (!eventMatch) continue;

					const [, eventType, eventData] = eventMatch;
					const event: ProgressEvent = JSON.parse(eventData);

					// Update UI based on event type
					if (event.type === 'method') {
						currentMethod = event.method || '';
						logs = [...logs, `${getMethodIcon(event.method)} ${event.message}`];
					} else if (event.type === 'status') {
						logs = [...logs, `ℹ️ ${event.message}`];
					} else if (event.type === 'retry') {
						logs = [...logs, `🔄 ${event.message}`];
					} else if (event.type === 'error') {
						logs = [...logs, `❌ ${event.message}`];
					} else if (event.type === 'thumbnail') {
						thumbnail = event.data?.thumbnail || null;
						thumbnailStatus = thumbnail ? 'success' : 'error';
						logs = [...logs, `🎨 ${event.message}`];
					} else if (eventType === 'complete' && event.data) {
						recipe = event.data.recipe;
						bodyText = event.data.recipe?.bodyText || '';
						status = 'done';
						logs = [...logs, `✅ ${event.message}`];
						currentMethod = '';
					}
				}
			}

			if (status !== 'done') {
				status = 'error';
				if (thumbnailStatus === 'extracting') {
					thumbnailStatus = 'error';
				}
			}
		} catch (e) {
			logs = [...logs, '❌ Network Error: ' + (e instanceof Error ? e.message : 'Unknown')];
			status = 'error';
			thumbnailStatus = 'error';
		}
	}

	async function retry() {
		recipe = null;
		bodyText = '';
		status = 'idle';
		logs = [...logs, 'Retrying extraction...'];
		await process();
	}

	async function importToTandoor() {
		if (!recipe) return;

		tandoorImporting = true;
		tandoorError = null;
		logs = [...logs, 'Importing recipe to Tandoor...'];

		try {
			const res = await fetch('/api/tandoor', {
				method: 'POST',
				body: JSON.stringify({ recipe }),
				headers: { 'Content-Type': 'application/json' }
			});

			const data = await res.json();

			if (data.success) {
				logs = [...logs, `✓ Recipe imported successfully (ID: ${data.recipeId})`];
				tandoorError = null;
			} else {
				logs = [...logs, `✗ Import failed: ${data.error}`];
				tandoorError = data.error;
			}
		} catch (e) {
			const errorMsg = e instanceof Error ? e.message : 'Unknown error';
			logs = [...logs, `✗ Network error: ${errorMsg}`];
			tandoorError = errorMsg;
		} finally {
			tandoorImporting = false;
		}
	}
</script>

<div class="p-8 max-w-lg mx-auto space-y-4">
	<div class="flex items-center justify-between">
		<h1 class="text-2xl font-bold">InstaChef PWA</h1>
		<LlmHealthIndicator />
	</div>

	<UrlInputSection {targetUrl} {sharedText} {sharedUrl} {status} onProcess={process} />
	<ProgressIndicator {status} />
	<ThumbnailPreview {thumbnail} status={thumbnailStatus} />
	<ExtractedTextViewer {bodyText} />
	<RecipeCard
		{recipe}
		{tandoorEnabled}
		{tandoorImporting}
		{tandoorError}
		onRetry={retry}
		onImportToTandoor={importToTandoor}
	/>
	<ErrorState {status} {bodyText} onRetry={retry} />
	<LogViewer {logs} {currentMethod} {status} />
</div>