<script lang="ts">
	import { useConvexClient } from 'convex-svelte';
	import {
		ExternalLink,
		FileText,
		File as FileIcon,
		Upload,
		Trash2,
		Eye,
		RefreshCw
	} from 'lucide-svelte';

	interface Props {
		label: string;
		helpUrl?: string;
		value?: string; // storageId
		disabled?: boolean;
		required?: boolean;
		onUpload: (file: globalThis.File) => Promise<void>;
		onRemove: () => Promise<void>;
	}

	let {
		label,
		helpUrl,
		value = $bindable(),
		disabled = false,
		required = false,
		onUpload,
		onRemove
	}: Props = $props();

	const client = useConvexClient() as unknown as {
		storage: {
			getUrl: (id: string) => Promise<string | null>;
		};
	};

	let fileInput: HTMLInputElement | null = null;
	let uploading = $state(false);
	let error = $state<string | null>(null);
	let fileName = $state<string>('');
	let fileType = $state<string>('');
	let previewUrl = $state<string | null>(null);
	let fileUrl = $state<string | null>(null);

	const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
	const ALLOWED_TYPES = ['application/pdf', 'image/jpeg', 'image/jpg', 'image/png'];

	// Buscar URL do arquivo quando houver um storageId
	$effect(() => {
		if (value && !fileName) {
			// Tem storageId mas não é um upload recente
			void loadExistingFile(value);
		}

		let cancelled = false;
		const storageId = value;

		if (!storageId) {
			return;
		}

		(async () => {
			try {
				const url = await client.storage.getUrl(storageId);
				if (!url || cancelled) {
					return;
				}

				fileUrl = url;

				const path = url.split('?')[0] ?? '';
				const nameFromUrl = path.split('/').pop() ?? 'arquivo';
				fileName = decodeURIComponent(nameFromUrl);

				const extension = fileName.toLowerCase().split('.').pop();
				const isPdf =
					extension === 'pdf' || url.includes('.pdf') || url.includes('application/pdf');

				if (isPdf) {
					fileType = 'application/pdf';
					previewUrl = null;
				} else {
					fileType = 'image/jpeg';
					previewUrl = url;
				}
			} catch (err) {
				if (!cancelled) {
					console.error('Erro ao carregar arquivo existente:', err);
				}
			}
		})();

		return () => {
			cancelled = true;
		};
	});

	async function loadExistingFile(storageId: string) {
		try {
			const url = await client.storage.getUrl(storageId);
			if (url) {
				fileUrl = url;

				// Detectar tipo pelo URL ou assumir PDF
				if (url.includes('.pdf') || url.includes('application/pdf')) {
					fileType = 'application/pdf';
				} else {
					fileType = 'image/jpeg';
					// Para imagens, a URL serve como preview
					previewUrl = url;
				}
			}
		} catch (err) {
			console.error('Erro ao carregar arquivo existente:', err);
		}
	}

	async function handleFileSelect(event: Event) {
		const target = event.target as HTMLInputElement;
		const file = target.files?.[0];

		if (!file) {
			return;
		}

		error = null;

		// Validate file size
		if (file.size > MAX_FILE_SIZE) {
			error = 'Arquivo muito grande. Tamanho máximo: 10MB';
			target.value = '';
			return;
		}

		// Validate file type
		if (!ALLOWED_TYPES.includes(file.type)) {
			error = 'Tipo de arquivo não permitido. Use PDF ou imagens (JPG, PNG)';
			target.value = '';
			return;
		}

		try {
			uploading = true;
			fileName = file.name;
			fileType = file.type;

			// Create preview for images
			if (file.type.startsWith('image/')) {
				const reader = new FileReader();
				reader.onload = (e) => {
					const result = e.target?.result;
					if (typeof result === 'string') {
						previewUrl = result;
					}
				};
				reader.readAsDataURL(file);
			} else {
				previewUrl = null;
			}

			await onUpload(file);
		} catch (err: unknown) {
			if (err instanceof Error) {
				error = err.message || 'Erro ao fazer upload do arquivo';
			} else {
				error = 'Erro ao fazer upload do arquivo';
			}
			previewUrl = null;
		} finally {
			uploading = false;
			target.value = '';
		}
	}

	async function handleRemove() {
		if (!confirm('Tem certeza que deseja remover este arquivo?')) {
			return;
		}

		try {
			uploading = true;
			await onRemove();
			fileName = '';
			fileType = '';
			previewUrl = null;
			fileUrl = null;
			error = null;
		} catch (err: unknown) {
			if (err instanceof Error) {
				error = err.message || 'Erro ao remover arquivo';
			} else {
				error = 'Erro ao remover arquivo';
			}
		} finally {
			uploading = false;
		}
	}

	function handleView() {
		if (fileUrl) {
			window.open(fileUrl, '_blank');
		}
	}

	function openFileDialog() {
		fileInput?.click();
	}

	function setFileInput(node: HTMLInputElement) {
		fileInput = node;
		return {
			destroy() {
				if (fileInput === node) {
					fileInput = null;
				}
			}
		};
	}
</script>

<div class="form-control w-full">
	<label class="label" for="file-upload-input">
		<span class="label-text flex items-center gap-2 font-medium">
			{label}
			{#if required}
				<span class="text-error">*</span>
			{/if}
			{#if helpUrl}
				<div class="tooltip tooltip-right" data-tip="Clique para acessar o link">
					<a
						href={helpUrl ?? '/'}
						target="_blank"
						rel="noopener noreferrer"
						class="text-primary hover:text-primary-focus transition-colors"
						aria-label="Acessar link"
					>
						<ExternalLink class="h-4 w-4" strokeWidth={2} />
					</a>
				</div>
			{/if}
		</span>
	</label>

	<input
		id="file-upload-input"
		type="file"
		use:setFileInput
		onchange={handleFileSelect}
		accept=".pdf,.jpg,.jpeg,.png"
		class="hidden"
		{disabled}
	/>

	{#if value || fileName}
		<div class="border-base-300 bg-base-100 flex items-center gap-2 rounded-lg border p-3">
			<!-- Preview -->
			<div class="shrink-0">
				{#if previewUrl}
					<img src={previewUrl} alt="Preview" class="h-12 w-12 rounded object-cover" />
				{:else if fileType === 'application/pdf' || fileName.endsWith('.pdf')}
					<div class="bg-error/10 flex h-12 w-12 items-center justify-center rounded">
						<FileText class="text-error h-6 w-6" strokeWidth={2} />
					</div>
				{:else}
					<div class="bg-success/10 flex h-12 w-12 items-center justify-center rounded">
						<FileIcon class="text-success h-6 w-6" strokeWidth={2} />
					</div>
				{/if}
			</div>

			<!-- File info -->
			<div class="min-w-0 flex-1">
				<p class="truncate text-sm font-medium">
					{fileName || 'Arquivo anexado'}
				</p>
				<p class="text-base-content/60 text-xs">
					{#if uploading}
						Carregando...
					{:else}
						Enviado com sucesso
					{/if}
				</p>
			</div>

			<!-- Actions -->
			<div class="flex gap-2">
				{#if fileUrl}
					<button
						type="button"
						onclick={handleView}
						class="btn btn-sm btn-ghost text-info"
						disabled={uploading || disabled}
						title="Visualizar arquivo"
					>
						<Eye class="h-4 w-4" strokeWidth={2} />
					</button>
				{/if}
				<button
					type="button"
					onclick={openFileDialog}
					class="btn btn-sm btn-ghost"
					disabled={uploading || disabled}
					title="Substituir arquivo"
				>
					<RefreshCw class="h-4 w-4" strokeWidth={2} />
				</button>
				<button
					type="button"
					onclick={handleRemove}
					class="btn btn-sm btn-ghost text-error"
					disabled={uploading || disabled}
					title="Remover arquivo"
				>
					<Trash2 class="h-4 w-4" strokeWidth={2} />
				</button>
			</div>
		</div>
	{:else}
		<button
			type="button"
			onclick={openFileDialog}
			class="btn btn-outline btn-block justify-start gap-2"
			disabled={uploading || disabled}
		>
			{#if uploading}
				<span class="loading loading-spinner loading-sm"></span>
				Carregando...
			{:else}
				<Upload class="h-5 w-5" strokeWidth={2} />
				Selecionar arquivo (PDF ou imagem, máx. 10MB)
			{/if}
		</button>
	{/if}

	{#if error}
		<div class="label">
			<span class="label-text-alt text-error">{error}</span>
		</div>
	{/if}
</div>
