<!--
  Settings › Integrations

  Outward-facing hooks: where Tinyforge *sends* events.
    1. URL field (global / fallback) — saved via /api/settings.
    2. Outgoing-webhook panel — secret rotate, disable signing, send test.
  Inbound webhooks are per-project / per-site and live on their respective
  detail pages — this page deliberately does not surface them.
-->
<script lang="ts">
	import { onMount } from 'svelte';
	import { get } from 'svelte/store';
	import {
		updateSettings,
		getSettingsNotificationSecret,
		regenerateSettingsNotificationSecret,
		disableSettingsNotificationSigning,
		testSettingsNotification,
	} from '$lib/api';
	import { settingsCache } from '$lib/stores/caches';
	import FormField from '$lib/components/FormField.svelte';
	import Skeleton from '$lib/components/Skeleton.svelte';
	import OutgoingWebhookPanel from '$lib/components/OutgoingWebhookPanel.svelte';
	import { toasts } from '$lib/stores/toast';
	import { t } from '$lib/i18n';
	import { IconLoader } from '$lib/components/icons';

	let loading = $state(true);
	let saving = $state(false);

	let notificationUrl = $state('');
	// Tracks the last persisted URL so the OutgoingWebhookPanel's hasUrl
	// flag reflects what the backend actually has, not unsaved input.
	let savedNotificationUrl = $state('');
	let errors = $state<Record<string, string>>({});

	function validateUrl(value: string): string {
		if (!value.trim()) return '';
		try { new URL(value.trim()); return ''; } catch { return $t('validation.invalidUrl'); }
	}

	// Seed once from the shared settings cache (warm → no skeleton on revisit);
	// never re-applied during background refresh, so unsaved edits are safe.
	async function load() {
		const cached = get(settingsCache).value;
		if (cached) {
			notificationUrl = cached.notification_url ?? '';
			savedNotificationUrl = notificationUrl;
			loading = false;
		}
		await settingsCache.refresh();
		const fresh = get(settingsCache).value;
		if (fresh && loading) {
			notificationUrl = fresh.notification_url ?? '';
			savedNotificationUrl = notificationUrl;
		}
		loading = false;
		const { error } = get(settingsCache);
		if (error && !cached) toasts.error(error || $t('settingsGeneral.loadFailed'));
	}

	async function handleSave() {
		const urlErr = validateUrl(notificationUrl);
		errors = urlErr ? { notificationUrl: urlErr } : {};
		if (urlErr) return;
		saving = true;
		try {
			await updateSettings({ notification_url: notificationUrl.trim() });
			// PUT returns {status:"updated"}, not Settings — refetch the cache.
			await settingsCache.refresh();
			savedNotificationUrl = notificationUrl.trim();
			toasts.success($t('settingsGeneral.saved'));
		} catch (err) {
			toasts.error(err instanceof Error ? err.message : $t('settingsGeneral.saveFailed'));
		} finally {
			saving = false;
		}
	}

	onMount(load);
</script>

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

<div class="space-y-6">
	{#if loading}
		<div class="space-y-4">
			<Skeleton height="2rem" width="12rem" />
			<Skeleton height="6rem" />
		</div>
	{:else}
		<!-- Outgoing: notification URL -->
		<div class="rounded-xl border border-[var(--border-primary)] bg-[var(--surface-card)] p-6 shadow-[var(--shadow-sm)]">
			<h2 class="mb-1 text-lg font-semibold text-[var(--text-primary)]">{$t('settingsIntegrations.outgoing')}</h2>
			<p class="mb-4 text-sm text-[var(--text-secondary)]">{$t('settingsIntegrations.outgoingDesc')}</p>

			<FormField
				label={$t('settingsGeneral.notificationUrl')}
				name="notificationUrl"
				bind:value={notificationUrl}
				placeholder="https://notify.example.com/webhook"
				error={errors.notificationUrl ?? ''}
				helpText={$t('settingsGeneral.notificationUrlHelp')}
			/>

			<div class="mt-6">
				<button onclick={handleSave} disabled={saving} class="inline-flex items-center gap-2 rounded-lg bg-[var(--color-brand-600)] px-4 py-2.5 text-sm font-medium text-white shadow-sm transition-all duration-150 hover:bg-[var(--color-brand-700)] disabled:opacity-50 active:animate-press">
					{#if saving}<IconLoader size={16} />{/if}
					{saving ? $t('settingsGeneral.saving') : $t('settingsGeneral.saveSettings')}
				</button>
			</div>
		</div>

		<!-- Outgoing: signing secret + send test -->
		<OutgoingWebhookPanel
			title={$t('outgoingWebhook.signingSecret')}
			description={$t('settingsIntegrations.outgoingDesc')}
			hasUrl={!!savedNotificationUrl}
			fetchSecret={getSettingsNotificationSecret}
			regenerateSecret={regenerateSettingsNotificationSecret}
			disableSigning={disableSettingsNotificationSigning}
			sendTest={testSettingsNotification}
		/>

		<!-- Inbound hooks now live per-entity. -->
		<div class="rounded-xl border border-[var(--border-primary)] bg-[var(--surface-card)] p-6 shadow-[var(--shadow-sm)]">
			<h2 class="mb-1 text-lg font-semibold text-[var(--text-primary)]">{$t('settingsIntegrations.incoming')}</h2>
			<p class="text-sm text-[var(--text-secondary)]">{$t('settingsIntegrations.incomingMovedDesc')}</p>
		</div>
	{/if}
</div>
