<script lang="ts">
	import { inspectImage, quickDeploy, listRegistries, listRegistryImages, deployInstance } from '$lib/api';
	import type { InspectResult, EntityPickerItem, Project } from '$lib/types';
	import FormField from '$lib/components/FormField.svelte';
	import EntityPicker from '$lib/components/EntityPicker.svelte';
	import ConfirmDialog from '$lib/components/ConfirmDialog.svelte';
	import { toasts } from '$lib/stores/toast';
	import { t } from '$lib/i18n';
	import { goto } from '$app/navigation';
	import { IconSearch, IconDeploy, IconLoader, IconCheck } from '$lib/components/icons';

	let imageUrl = $state('');
	let inspecting = $state(false);
	let deploying = $state(false);
	let inspected = $state(false);
	let inspectResult: InspectResult | null = $state(null);

	let projectName = $state('');
	let port = $state('');
	let stage = $state('dev');
	let subdomain = $state('');
	let envVars = $state('');

	let errors = $state<Record<string, string>>({});

	// Duplicate detection state
	let conflictProjects = $state<Project[]>([]);
	let showConflictDialog = $state(false);

	// Image picker state
	let showImagePicker = $state(false);
	let imagePickerItems = $state<EntityPickerItem[]>([]);
	let imagePickerLoading = $state(false);

	async function handleBrowseImages() {
		showImagePicker = true;
		if (imagePickerItems.length > 0) return;

		imagePickerLoading = true;
		try {
			const registries = await listRegistries();
			const items: EntityPickerItem[] = [];
			for (const reg of registries) {
				if (!reg.owner) continue;
				try {
					const images = await listRegistryImages(reg.id);
					for (const img of images) {
						items.push({
							value: img.full_ref + ':latest',
							label: img.full_ref,
							description: reg.name,
							group: reg.name
						});
					}
				} catch {
					// Skip registries that fail.
				}
			}
			imagePickerItems = items;
		} catch {
			toasts.error($t('quickDeploy.imageLoadFailed'));
		} finally {
			imagePickerLoading = false;
		}
	}

	function selectPickedImage(value: string) {
		imageUrl = value;
		showImagePicker = false;
	}

	function validateImageUrl(url: string): string {
		if (!url.trim()) return $t('validation.required', { field: 'Image URL' });
		if (!/^[a-zA-Z0-9._\-/]+:[a-zA-Z0-9._\-]+$/.test(url.trim())) {
			return $t('validation.invalidUrl');
		}
		return '';
	}

	function validatePort(value: string | number): string {
		const s = String(value ?? '');
		if (!s.trim()) return $t('validation.required', { field: 'Port' });
		const num = parseInt(s, 10);
		if (isNaN(num) || num < 1 || num > 65535) return $t('validation.invalidPort');
		return '';
	}

	function validateProjectName(value: string): string {
		if (!value.trim()) return $t('validation.required', { field: 'Project name' });
		if (value.trim().length > 1 && !/^[a-z0-9][a-z0-9\-]*[a-z0-9]$/.test(value.trim())) {
			return $t('validation.invalidProjectName');
		}
		return '';
	}

	function validateAll(): boolean {
		const newErrors: Record<string, string> = {};
		const nameErr = validateProjectName(projectName);
		if (nameErr) newErrors.projectName = nameErr;
		const portErr = validatePort(port);
		if (portErr) newErrors.port = portErr;
		errors = newErrors;
		return Object.keys(newErrors).length === 0;
	}

	function deriveProjectName(image: string): string {
		const withoutTag = image.split(':')[0] ?? image;
		const segments = withoutTag.split('/');
		return (segments[segments.length - 1] ?? 'unknown').toLowerCase().replace(/[^a-z0-9\-]/g, '-');
	}

	async function handleInspect() {
		const urlError = validateImageUrl(imageUrl);
		if (urlError) {
			errors = { imageUrl: urlError };
			return;
		}
		errors = {};
		inspecting = true;
		try {
			const result = await inspectImage(imageUrl.trim());
			inspectResult = result;
			projectName = deriveProjectName(result.image);
			port = result.port?.toString() ?? '';
			// Healthcheck auto-detected but not shown — user can configure later on project page.
			stage = 'dev';
			subdomain = '';
			envVars = '';
			inspected = true;
			toasts.success($t('quickDeploy.inspectedSuccess'));
		} catch (err) {
			const message = err instanceof Error ? err.message : $t('quickDeploy.inspectFailed');
			toasts.error(message);
		} finally {
			inspecting = false;
		}
	}

	async function handleDeploy(force = false) {
		if (!validateAll()) return;
		deploying = true;
		try {
			const result = await quickDeploy({ image: imageUrl.trim(), name: projectName.trim(), port: parseInt(port, 10), force });
			toasts.success($t('quickDeploy.deployedSuccess', { name: projectName }));
			// Redirect to the new project page.
			if (result.project?.id) {
				goto(`/projects/${result.project.id}`);
			} else {
				imageUrl = '';
				inspected = false;
				inspectResult = null;
				projectName = '';
				port = '';
					stage = 'dev';
				subdomain = '';
				envVars = '';
			}
		} catch (err: unknown) {
			// Handle 409 Conflict — existing project with same image.
			if (err instanceof Error && 'status' in err && (err as any).status === 409) {
				try {
					// The error message contains the JSON response from the server.
					// Re-fetch existing projects for this image.
					const res = await fetch(`/api/deploy/quick`, {
						method: 'POST',
						headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('auth_token')}` },
						body: JSON.stringify({ image: imageUrl.trim(), name: projectName.trim(), port: parseInt(port, 10) })
					});
					if (res.status === 409) {
						const envelope = await res.json();
						if (envelope.data?.existing_projects) {
							conflictProjects = envelope.data.existing_projects;
							showConflictDialog = true;
							return;
						}
					}
				} catch { /* fall through */ }
				toasts.error($t('quickDeploy.imageAlreadyExists'));
			} else {
				const message = err instanceof Error ? err.message : $t('quickDeploy.deployFailed');
				toasts.error(message);
			}
		} finally {
			deploying = false;
		}
	}

	async function handleDeployToExisting(project: Project) {
		showConflictDialog = false;
		conflictProjects = [];
		goto(`/projects/${project.id}`);
	}

	async function handleForceNewProject() {
		showConflictDialog = false;
		conflictProjects = [];
		await handleDeploy(true);
	}
</script>

<svelte:head>
	<title>{$t('quickDeploy.title')} - {$t('app.name')}</title>
</svelte:head>

<div class="mx-auto max-w-2xl space-y-6">
	<div>
		<h1 class="text-2xl font-bold text-[var(--text-primary)]">{$t('quickDeploy.title')}</h1>
		<p class="mt-1 text-sm text-[var(--text-secondary)]">{$t('quickDeploy.description')}</p>
	</div>

	<!-- Step 1 -->
	<div class="rounded-xl border border-[var(--border-primary)] bg-[var(--surface-card)] p-6 shadow-[var(--shadow-sm)]">
		<h2 class="mb-4 text-base font-semibold text-[var(--text-primary)]">{$t('quickDeploy.step1')}</h2>
		<div class="flex gap-3">
			<div class="flex-1">
				<FormField
					label={$t('quickDeploy.imageUrl')}
					name="imageUrl"
					bind:value={imageUrl}
					placeholder="registry.example.com/org/app:tag"
					required
					error={errors.imageUrl ?? ''}
					helpText={$t('quickDeploy.imageUrlHelp')}
					disabled={inspecting}
				/>
			</div>
			<div class="flex items-start gap-2 pt-[26px]">
				<button
					type="button"
					onclick={handleBrowseImages}
					title={$t('quickDeploy.browseImages')}
					aria-label={$t('quickDeploy.browseImages')}
					class="rounded-lg border border-[var(--border-primary)] p-2 text-[var(--text-secondary)] hover:bg-[var(--surface-card-hover)] hover:text-[var(--text-primary)] transition-colors"
				>
					{#if imagePickerLoading}
						<IconLoader size={16} />
					{:else}
						<IconSearch size={16} />
					{/if}
				</button>
				<button
					onclick={handleInspect}
					disabled={inspecting || !imageUrl.trim()}
					class="inline-flex items-center gap-2 rounded-lg bg-[var(--color-info)] px-4 py-2 text-sm font-medium text-white transition-all duration-150 hover:bg-[var(--color-info-dark)] disabled:cursor-not-allowed disabled:opacity-50 active:animate-press"
				>
					{#if inspecting}
						<IconLoader size={16} />
						{$t('quickDeploy.inspecting')}
					{:else}
						<IconSearch size={16} />
						{$t('quickDeploy.inspect')}
					{/if}
				</button>
			</div>
		</div>
		<EntityPicker
			bind:open={showImagePicker}
			items={imagePickerItems}
			current={imageUrl}
			title={$t('quickDeploy.selectImage')}
			placeholder={$t('entityPicker.search')}
			onselect={selectPickedImage}
			onclose={() => { showImagePicker = false; }}
		/>
	</div>

	<!-- Step 2 -->
	{#if inspected}
		<div class="rounded-xl border border-[var(--border-primary)] bg-[var(--surface-card)] p-6 shadow-[var(--shadow-sm)] animate-scale-in">
			<h2 class="mb-1 text-base font-semibold text-[var(--text-primary)]">{$t('quickDeploy.step2')}</h2>
			<p class="mb-4 text-sm text-[var(--text-secondary)]">{$t('quickDeploy.reviewDesc')}</p>

			<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
				<FormField label={$t('quickDeploy.projectName')} name="projectName" bind:value={projectName} placeholder="my-app" required error={errors.projectName ?? ''} helpText={$t('quickDeploy.lowercaseHint')} />
				<FormField label={$t('quickDeploy.port')} name="port" type="number" bind:value={port} placeholder="3000" required error={errors.port ?? ''} helpText={$t('quickDeploy.portHelp')} />
				<div class="flex flex-col gap-1.5">
					<label for="stage" class="text-sm font-medium text-[var(--text-primary)]">{$t('quickDeploy.stage')}</label>
					<select id="stage" bind:value={stage} class="rounded-lg border border-[var(--border-input)] bg-[var(--surface-input)] px-3 py-2 text-sm text-[var(--text-primary)] focus:border-[var(--color-brand-500)] focus:ring-2 focus:ring-[var(--color-brand-500)] focus:outline-none">
						<option value="dev">{$t('quickDeploy.development')}</option>
						<option value="rel">{$t('quickDeploy.release')}</option>
						<option value="prod">{$t('quickDeploy.production')}</option>
					</select>
					<p class="text-xs text-[var(--text-tertiary)]">{$t('quickDeploy.stageHelp')}</p>
				</div>
				<FormField label={$t('quickDeploy.subdomainOverride')} name="subdomain" bind:value={subdomain} placeholder="auto-generated" helpText={$t('quickDeploy.subdomainHelp')} />
			</div>

			<div class="mt-4">
				<FormField label={$t('quickDeploy.envVars')} name="envVars" type="textarea" bind:value={envVars} placeholder={"KEY=value\nANOTHER_KEY=another_value"} helpText={$t('quickDeploy.envVarsHelp')} />
			</div>
		</div>

		<!-- Step 3 -->
		<div class="rounded-xl border border-[var(--border-primary)] bg-[var(--surface-card)] p-6 shadow-[var(--shadow-sm)] animate-scale-in">
			<h2 class="mb-1 text-base font-semibold text-[var(--text-primary)]">{$t('quickDeploy.step3')}</h2>
			<p class="mb-4 text-sm text-[var(--text-secondary)]">{$t('quickDeploy.deployDesc')}</p>
			<div class="flex gap-3">
				<button
					onclick={() => handleDeploy()}
					disabled={deploying}
					class="inline-flex items-center gap-2 rounded-lg bg-[var(--color-success)] px-6 py-2.5 text-sm font-medium text-white shadow-sm transition-all duration-150 hover:bg-[var(--color-success-dark)] disabled:cursor-not-allowed disabled:opacity-50 active:animate-press"
				>
					{#if deploying}
						<IconLoader size={16} />
						{$t('projectDetail.deploying')}
					{:else}
						<IconDeploy size={16} />
						{$t('quickDeploy.deployBtn')}
					{/if}
				</button>
				<button
					onclick={() => { inspected = false; inspectResult = null; }}
					disabled={deploying}
					class="rounded-lg border border-[var(--border-primary)] px-4 py-2.5 text-sm font-medium text-[var(--text-secondary)] hover:bg-[var(--surface-card-hover)] transition-colors disabled:opacity-50"
				>
					{$t('common.cancel')}
				</button>
			</div>
		</div>
	{/if}
</div>

<!-- Conflict dialog: image already deployed -->
{#if showConflictDialog}
	<div class="fixed inset-0 z-40 bg-[var(--surface-overlay)] animate-fade-in" role="presentation" onclick={() => { showConflictDialog = false; }}></div>
	<div class="fixed inset-0 z-50 flex items-center justify-center p-4">
		<!-- svelte-ignore a11y_no_static_element_interactions -->
		<div
			role="dialog"
			aria-modal="true"
			aria-labelledby="conflict-dialog-title"
			tabindex="-1"
			onkeydown={(e) => { if (e.key === 'Escape') showConflictDialog = false; }}
			onclick={(e) => e.stopPropagation()}
			class="w-full max-w-lg rounded-2xl bg-[var(--surface-card)] p-6 shadow-xl animate-scale-in"
		>
			<h3 id="conflict-dialog-title" class="text-lg font-semibold text-[var(--text-primary)]">
				{$t('quickDeploy.imageAlreadyExists')}
			</h3>
			<p class="mt-2 text-sm text-[var(--text-secondary)]">
				{$t('quickDeploy.conflictDescription')}
			</p>

			<div class="mt-4 space-y-2">
				{#each conflictProjects as project (project.id)}
					<button
						type="button"
						onclick={() => handleDeployToExisting(project)}
						class="flex w-full items-center justify-between rounded-lg border border-[var(--border-primary)] bg-[var(--surface-card-hover)] p-3 text-left hover:border-[var(--color-brand-500)] transition-colors"
					>
						<div>
							<span class="text-sm font-medium text-[var(--text-primary)]">{project.name}</span>
							<span class="ml-2 text-xs text-[var(--text-tertiary)]">{project.image}</span>
						</div>
						<span class="text-xs text-[var(--text-tertiary)]">{$t('quickDeploy.openProject')}</span>
					</button>
				{/each}
			</div>

			<div class="mt-6 flex justify-end gap-3">
				<button
					type="button"
					class="rounded-lg px-4 py-2 text-sm font-medium text-[var(--text-secondary)] hover:bg-[var(--surface-card-hover)] transition-colors"
					onclick={() => { showConflictDialog = false; }}
				>
					{$t('common.cancel')}
				</button>
				<button
					type="button"
					class="rounded-lg bg-[var(--color-brand-600)] px-4 py-2 text-sm font-medium text-white hover:bg-[var(--color-brand-700)] transition-colors"
					onclick={handleForceNewProject}
				>
					{$t('quickDeploy.createNewAnyway')}
				</button>
			</div>
		</div>
	</div>
{/if}
