<!-- src/lib/components/ItemDisplay.svelte -->
<script lang="ts">
	import { createEventDispatcher, onMount } from 'svelte';
	import { apiClient, ApiClientError } from '$lib/apiClient';
	import type { ItemPublic, ItemUpdate } from '$lib/schemas/item';
	import { putItemToDb, deleteItemFromDb, addSyncAction } from '$lib/db';
	import { processSyncQueue } from '$lib/syncService';
	import { browser } from '$app/environment';
	import { authStore } from '$lib/stores/authStore';
	import { get } from 'svelte/store';

	export let item: ItemPublic;

	const dispatch = createEventDispatcher<{
		itemUpdated: ItemPublic;
		itemDeleted: number;
		updateError: string;
	}>();

	// --- Component State ---
	let isEditing = false;
	let isToggling = false;
	let isDeleting = false;
	let isSavingEdit = false;
	let isSavingPrice = false;

	// State for edit form
	let editName = '';
	let editQuantity = '';
	let editPrice = '';

	// Initialize editPrice when item prop changes
	$: if (item) {
		editPrice = item.price?.toString() ?? '';
		if (!isEditing) {
			editName = item.name;
			editQuantity = item.quantity ?? '';
		}
	}

	// --- Edit Mode ---
	function startEdit() {
		if (isEditing) return;
		editName = item.name;
		editQuantity = item.quantity ?? '';
		isEditing = true;
		dispatch('updateError', '');
	}

	function cancelEdit() {
		isEditing = false;
		editPrice = item.price?.toString() ?? '';
		dispatch('updateError', '');
	}

	// --- API Interactions ---
	async function handleToggleComplete() {
		if (isToggling || isEditing) return;
		isToggling = true;
		dispatch('updateError', '');

		const newStatus = !item.is_complete;
		const updateData: ItemUpdate = { is_complete: newStatus };
		const currentUserId = get(authStore).user?.id;

		// Optimistic DB/UI Update
		const optimisticItem = {
			...item,
			is_complete: newStatus,
			completed_by_id: newStatus ? (currentUserId ?? item.completed_by_id ?? null) : null,
			updated_at: new Date().toISOString()
		};

		try {
			await putItemToDb(optimisticItem);
			dispatch('itemUpdated', optimisticItem);
		} catch (dbError) {
			isToggling = false;
			return;
		}

		// Queue or Send API Call
		console.log(`Toggling item ${item.id} to ${newStatus}`);
		try {
			if (browser && !navigator.onLine) {
				console.log(`Offline: Queuing update for item ${item.id}`);
				await addSyncAction({
					type: 'update_item',
					payload: { id: item.id, data: updateData },
					timestamp: Date.now()
				});
			} else {
				const updatedItemFromServer = await apiClient.put<ItemPublic>(
					`/v1/items/${item.id}`,
					updateData
				);
				await putItemToDb(updatedItemFromServer);
				dispatch('itemUpdated', updatedItemFromServer);
			}
			if (browser && navigator.onLine) processSyncQueue();
		} catch (err) {
			// Handle error
		} finally {
			isToggling = false;
		}
	}

	async function handleSaveEdit() {
		if (isSavingEdit) return;
		isSavingEdit = true;
		dispatch('updateError', '');

		const updateData: ItemUpdate = {
			name: editName.trim(),
			quantity: editQuantity.trim() || undefined
		};

		// Optimistic DB/UI Update
		const optimisticItem = {
			...item,
			...updateData,
			updated_at: new Date().toISOString()
		};

		try {
			await putItemToDb(optimisticItem as any);
			dispatch('itemUpdated', optimisticItem as any);
		} catch (dbError) {
			isSavingEdit = false;
			return;
		}

		// Queue or Send API Call
		console.log(`Saving edits for item ${item.id}`, updateData);
		try {
			if (browser && !navigator.onLine) {
				await addSyncAction({
					type: 'update_item',
					payload: { id: item.id, data: updateData },
					timestamp: Date.now()
				});
			} else {
				const updatedItemFromServer = await apiClient.put<ItemPublic>(
					`/v1/items/${item.id}`,
					updateData
				);
				await putItemToDb(updatedItemFromServer);
				dispatch('itemUpdated', updatedItemFromServer);
			}
			if (browser && navigator.onLine) processSyncQueue();
			isEditing = false;
		} catch (err) {
			// Handle error
		} finally {
			isSavingEdit = false;
		}
	}

	// --- Save Price Logic ---
	async function handleSavePrice() {
		if (isSavingPrice || isEditing || !item.is_complete) return;
		isSavingPrice = true;
		dispatch('updateError', '');

		let newPrice: number | null = null;
		try {
			const trimmedPrice = editPrice.trim();
			if (trimmedPrice === '') {
				newPrice = null;
			} else {
				const parsed = parseFloat(trimmedPrice);
				if (isNaN(parsed) || parsed < 0) {
					throw new Error('Invalid price: Must be a non-negative number.');
				}
				newPrice = parseFloat(parsed.toFixed(2));
			}
		} catch (parseError: any) {
			dispatch('updateError', parseError.message || 'Invalid price format.');
			isSavingPrice = false;
			return;
		}

		if (newPrice === (item.price ?? null)) {
			console.log('Price unchanged, skipping save.');
			isSavingPrice = false;
			return;
		}

		const updateData: ItemUpdate = { price: newPrice };

		// Optimistic DB/UI Update
		const optimisticItem = {
			...item,
			price: newPrice,
			updated_at: new Date().toISOString()
		};

		try {
			await putItemToDb(optimisticItem);
			dispatch('itemUpdated', optimisticItem);
		} catch (dbError) {
			isSavingPrice = false;
			return;
		}

		// Queue or Send API Call
		console.log(`Saving price for item ${item.id}: ${newPrice}`);
		try {
			if (browser && !navigator.onLine) {
				console.log(`Offline: Queuing price update for item ${item.id}`);
				await addSyncAction({
					type: 'update_item',
					payload: { id: item.id, data: updateData },
					timestamp: Date.now()
				});
			} else {
				const updatedItemFromServer = await apiClient.put<ItemPublic>(
					`/v1/items/${item.id}`,
					updateData
				);
				await putItemToDb(updatedItemFromServer);
				dispatch('itemUpdated', updatedItemFromServer);
				editPrice = updatedItemFromServer.price?.toString() ?? '';
			}
			if (browser && navigator.onLine) processSyncQueue();
		} catch (err) {
			console.error(`Save price for item ${item.id} failed:`, err);
			const errorMsg =
				err instanceof ApiClientError
					? `Error (${err.status}): ${err.message}`
					: 'Save price failed';
			dispatch('updateError', errorMsg);
		} finally {
			isSavingPrice = false;
		}
	}

	async function handleDelete() {
		// Existing delete logic
	}
</script>

<li
	class="flex flex-col gap-2 rounded border p-3 transition duration-150 ease-in-out hover:bg-gray-50 sm:flex-row sm:items-center sm:justify-between"
	class:border-gray-200={!isEditing}
	class:border-blue-400={isEditing}
	class:opacity-60={item.is_complete && !isEditing}
>
	{#if isEditing}
		<!-- Edit Mode Form -->
		<form
			on:submit|preventDefault={handleSaveEdit}
			class="flex w-full flex-grow items-center gap-2"
		>
			<!-- Name/Qty inputs, Save/Cancel buttons -->
		</form>
	{:else}
		<!-- Display Mode -->
		<div class="flex flex-grow items-center gap-3 overflow-hidden">
			<input
				type="checkbox"
				checked={item.is_complete}
				disabled={isToggling || isDeleting}
				on:change={handleToggleComplete}
				aria-label="Mark {item.name} as {item.is_complete ? 'incomplete' : 'complete'}"
				class="h-5 w-5 flex-shrink-0 rounded border-gray-300 text-blue-600 focus:ring-blue-500 disabled:cursor-not-allowed disabled:opacity-50"
			/>
			<div class="flex-grow overflow-hidden">
				<span
					class="block truncate font-medium text-gray-800"
					class:line-through={item.is_complete}
					class:text-gray-500={item.is_complete}
					title={item.name}
				>
					{item.name}
				</span>
				{#if item.quantity}
					<span
						class="block truncate text-sm text-gray-500"
						class:line-through={item.is_complete}
						title={item.quantity}
					>
						Qty: {item.quantity}
					</span>
				{/if}
				{#if item.is_complete && item.price != null}
					<span class="mt-1 block text-xs font-semibold text-green-700">
						${item.price.toFixed(2)}
					</span>
				{/if}
			</div>
		</div>

		<!-- Action Buttons & Price Input Area -->
		<div class="flex flex-shrink-0 items-center space-x-2">
			{#if item.is_complete}
				<div class="flex items-center space-x-1">
					<label for="price-{item.id}" class="text-sm text-gray-600">$</label>
					<input
						type="number"
						id="price-{item.id}"
						step="0.01"
						min="0"
						placeholder="Price"
						bind:value={editPrice}
						on:blur={handleSavePrice}
						on:keydown={(e) => {
							if (e.key === 'Enter') handleSavePrice();
						}}
						class="w-24 rounded border border-gray-300 px-2 py-1 text-sm shadow-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
						disabled={isSavingPrice}
						aria-label="Item price"
					/>
					{#if isSavingPrice}
						<span class="animate-pulse text-xs text-gray-500">...</span>
					{/if}
				</div>
			{/if}

			<button
				on:click={startEdit}
				class="..."
				title="Edit Item"
				disabled={isToggling || isDeleting}
			>
				✏️
			</button>
			<button
				on:click={handleDelete}
				class="..."
				title="Delete Item"
				disabled={isToggling || isDeleting}
			>
				{#if isDeleting}⏳{:else}🗑️{/if}
			</button>
		</div>
	{/if}
</li>