<script lang="ts">
	import type { PhotoDimensions } from '$lib/cards/types';
	import PhotoCrop from './PhotoCrop.svelte';

	let { photo, onCropUpdated, onRetry, photoDimensions } = $props<{
		photo: {
			name: string;
			url: string;
			status: 'loading' | 'success' | 'error';
			objectUrl?: string;
			retryCount: number;
			cropData?: { x: number; y: number; width: number; height: number };
			faceDetectionStatus?: 'pending' | 'processing' | 'completed' | 'failed' | 'manual';
		};
		onCropUpdated: (detail: any) => void;
		onRetry: () => void;
		photoDimensions: PhotoDimensions;
	}>();

	let showCropper = $state(false);
	let imageDimensions = $state<{ w: number; h: number } | null>(null);
	let imageContainer = $state<HTMLDivElement | undefined>();

	const cropBoxStyle = $derived(() => {
		if (!photo.cropData || !imageDimensions || !imageContainer) {
			return 'display: none;';
		}

		const { w: naturalW, h: naturalH } = imageDimensions;
		const { x, y, width, height } = photo.cropData;
		const { clientWidth: containerW, clientHeight: containerH } = imageContainer;

		const containerAspect = containerW / containerH;
		const naturalAspect = naturalW / naturalH;

		let imgW, imgH;
		if (naturalAspect > containerAspect) {
			// Image is wider than container, so it's letterboxed top/bottom
			imgW = containerW;
			imgH = containerW / naturalAspect;
		} else {
			// Image is taller than container, so it's letterboxed left/right
			imgH = containerH;
			imgW = containerH * naturalAspect;
		}

		const offsetX = (containerW - imgW) / 2;
		const offsetY = (containerH - imgH) / 2;

		const scaleX = imgW / naturalW;
		const scaleY = imgH / naturalH;

		const left = x * scaleX + offsetX;
		const top = y * scaleY + offsetY;
		const boxWidth = width * scaleX;
		const boxHeight = height * scaleY;

		return `
      position: absolute;
      left: ${left}px;
      top: ${top}px;
      width: ${boxWidth}px;
      height: ${boxHeight}px;
      border: 2px solid #3b82f6; /* blue-500 */
      box-shadow: 0 0 0 9999px rgba(229, 231, 235, 0.75); /* gray-200 with opacity */
      transition: all 0.3s;
    `;
	});

	function handleImageLoad(event: Event) {
		const img = event.target as HTMLImageElement;
		imageDimensions = { w: img.naturalWidth, h: img.naturalHeight };
	}

	function handleCropUpdated(detail: any) {
		onCropUpdated(detail);
		showCropper = false;
	}
</script>

{#if photo.status === 'loading'}
	<div class="border border-gray-200 rounded-lg overflow-hidden bg-white shadow-sm">
		<div class="h-48 bg-gray-200 flex items-center justify-center">
			<div class="flex flex-col items-center">
				<div
					class="w-8 h-8 border-2 border-blue-600 border-t-transparent rounded-full animate-spin mb-2"
				></div>
				<span class="text-xs text-gray-600">Loading...</span>
			</div>
		</div>
		<div class="p-3">
			<h4 class="font-medium text-sm text-gray-900 truncate">{photo.name}</h4>
			<span class="text-xs text-blue-600">Processing photo...</span>
		</div>
	</div>
{:else if photo.status === 'success' && photo.objectUrl}
	<div class="border border-gray-200 rounded-lg overflow-hidden bg-white shadow-sm relative">
		<div
			class="h-48 bg-gray-200 flex items-center justify-center relative overflow-hidden"
			bind:this={imageContainer}
		>
			<img
				src={photo.objectUrl}
				alt={`Photo of ${photo.name}`}
				class="max-w-full max-h-full object-contain"
				onload={handleImageLoad}
			/>
			{#if photo.cropData}
				<div style={cropBoxStyle()}></div>
			{/if}
		</div>

		<div class="esnSection p-3 flex items-center justify-between gap-2">
			<div class="min-w-0 flex-1">
				<h4 class="font-medium text-sm text-gray-900 truncate">{photo.name}</h4>
				{#if photo.faceDetectionStatus === 'completed'}
					<span class="text-xs text-green-600">Face detected</span>
				{:else if photo.faceDetectionStatus === 'failed'}
					<span class="text-xs text-orange-600">Face not found</span>
				{:else if photo.faceDetectionStatus === 'processing'}
					<span class="text-xs text-blue-600">Detecting face...</span>
				{:else if photo.faceDetectionStatus === 'manual'}
					<span class="text-xs text-purple-600">Manual crop</span>
				{:else if photo.faceDetectionStatus === 'pending'}
					<span class="text-xs text-gray-500">Queued...</span>
				{/if}
			</div>
			<button
				onclick={() => (showCropper = true)}
				class="p-1 text-gray-500 hover:text-blue-600 shrink-0"
				title="Edit Crop"
				aria-label="Edit Crop"
			>
				<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
					<path
						stroke-linecap="round"
						stroke-linejoin="round"
						stroke-width="2"
						d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.5L16.732 3.732z"
					/>
				</svg>
			</button>
		</div>

		{#if showCropper}
			<PhotoCrop
				imageUrl={photo.objectUrl}
				personName={photo.name}
				initialCropData={photo.cropData}
				{photoDimensions}
				onClose={() => (showCropper = false)}
				onCropUpdated={handleCropUpdated}
			/>
		{/if}
	</div>
{:else if photo.status === 'error'}
	<div class="border border-gray-200 rounded-lg overflow-hidden bg-white shadow-sm">
		<div class="h-48 bg-gray-200 flex items-center justify-center">
			<div class="flex flex-col items-center text-center p-4">
				<svg
					class="w-12 h-12 text-red-400 mb-2"
					fill="none"
					viewBox="0 0 24 24"
					stroke="currentColor"
				>
					<path
						stroke-linecap="round"
						stroke-linejoin="round"
						stroke-width="2"
						d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
					/>
				</svg>
				<span class="text-xs text-red-600 mb-2">Failed to load</span>
				<button
					class="text-xs text-blue-600 hover:text-blue-800 underline"
					onclick={onRetry}
					disabled={photo.retryCount >= 3}
				>
					{photo.retryCount >= 3 ? 'Max retries' : 'Retry'}
				</button>
			</div>
		</div>
		<div class="p-3">
			<h4 class="font-medium text-sm text-gray-900 truncate">{photo.name}</h4>
			<span class="text-xs text-red-600">Failed to load</span>
		</div>
	</div>
{/if}
