<script lang="ts">
	/**
	 * WorkloadNotificationsPanel
	 *
	 * Per-workload outbound notification routes. Multi-destination
	 * fan-out: each row is one Slack channel / Discord webhook /
	 * generic receiver, optionally filtered to a comma-separated
	 * allow-list of event types. When zero rows exist the dispatcher
	 * falls back to the legacy single notification URL on the workload.
	 *
	 * Secret is write-only: the API returns secret_set so the UI shows
	 * "secret configured" / "no secret" without ever round-tripping the
	 * ciphertext. To rotate, submit a new plaintext value.
	 */
	import * as api from '$lib/api';
	import { t } from '$lib/i18n';
	import ToggleSwitch from './ToggleSwitch.svelte';
	import ConfirmDialog from './ConfirmDialog.svelte';
	import { IconPlus, IconTrash, IconEdit } from './icons';

	interface Props {
		workloadId: string;
	}
	let { workloadId }: Props = $props();

	let rows = $state<api.WorkloadNotification[]>([]);
	let loading = $state(true);
	let error = $state('');
	let saving = $state(false);
	let confirmDeleteId = $state<string | null>(null);

	// Edit form. editingId === '' means we're creating, otherwise it's
	// the row being edited. Form fields are kept flat (string) so the
	// API payload assembly stays trivial.
	let editingId = $state<string | null>(null);
	let formName = $state('');
	let formURL = $state('');
	let formSecret = $state('');
	let formEventTypes = $state('');
	let formEnabled = $state(true);

	const formValid = $derived(formURL.trim().length > 0);

	async function load(): Promise<void> {
		loading = true;
		error = '';
		try {
			rows = await api.listWorkloadNotifications(workloadId);
		} catch (e) {
			error = e instanceof Error ? e.message : String(e);
		} finally {
			loading = false;
		}
	}

	// Reload whenever the workloadId prop changes — the parent (/apps/[id])
	// reuses this component instance across /apps/A → /apps/B navigation, so
	// onMount(load) alone would keep showing the previous workload's rows.
	$effect(() => {
		const _ = workloadId; // explicit dependency
		load();
	});

	function startAdd(): void {
		editingId = '';
		formName = '';
		formURL = '';
		formSecret = '';
		formEventTypes = '';
		formEnabled = true;
	}

	function startEdit(row: api.WorkloadNotification): void {
		editingId = row.id;
		formName = row.name;
		formURL = row.url;
		formSecret = ''; // write-only; empty means "leave unchanged"
		formEventTypes = row.event_types;
		formEnabled = row.enabled;
	}

	function cancelEdit(): void {
		editingId = null;
	}

	async function save(): Promise<void> {
		if (!formValid || saving) return;
		saving = true;
		try {
			const body: api.WorkloadNotificationInput = {
				name: formName.trim(),
				url: formURL.trim(),
				event_types: formEventTypes.trim(),
				enabled: formEnabled
			};
			if (formSecret.trim()) body.secret = formSecret.trim();
			if (editingId === '') {
				await api.createWorkloadNotification(workloadId, body);
			} else if (editingId) {
				await api.updateWorkloadNotification(workloadId, editingId, body);
			}
			editingId = null;
			await load();
		} catch (e) {
			error = e instanceof Error ? e.message : String(e);
		} finally {
			saving = false;
		}
	}

	async function doDelete(id: string): Promise<void> {
		saving = true;
		try {
			await api.deleteWorkloadNotification(workloadId, id);
			confirmDeleteId = null;
			await load();
		} catch (e) {
			error = e instanceof Error ? e.message : String(e);
		} finally {
			saving = false;
		}
	}
</script>

<section class="panel notif-panel" aria-labelledby="notif-heading">
	<span class="reg reg-tl" aria-hidden="true"></span>
	<span class="reg reg-tr" aria-hidden="true"></span>
	<span class="reg reg-bl" aria-hidden="true"></span>
	<span class="reg reg-br" aria-hidden="true"></span>

	<header class="panel-head">
		<h2 class="panel-title" id="notif-heading">
			{$t('apps.detail.notifications.title')}<span class="title-accent">.</span>
		</h2>
		<span class="panel-sub">{$t('apps.detail.notifications.sub')}</span>
	</header>

	{#if error}
		<div class="alert inline-alert" role="alert">
			<span class="alert-tag">ERR</span><span>{error}</span>
		</div>
	{/if}

	{#if loading}
		<p class="hint">{$t('apps.detail.notifications.loading')}</p>
	{:else if rows.length === 0 && editingId === null}
		<p class="hint">{$t('apps.detail.notifications.empty')}</p>
		<button class="forge-btn" onclick={startAdd}>
			<IconPlus size={13} />
			<span>{$t('apps.detail.notifications.addFirst')}</span>
		</button>
	{:else}
		{#if rows.length > 0}
			<ul class="notif-list">
				{#each rows as row (row.id)}
					<li class="notif-row" class:disabled={!row.enabled}>
						<div class="notif-main">
							<span class="notif-name">{row.name || '(unnamed)'}</span>
							<span class="notif-url mono">{row.url}</span>
							<span class="notif-meta">
								{#if row.event_types}
									<span class="notif-tag">{row.event_types}</span>
								{:else}
									<span class="notif-tag muted">{$t('apps.detail.notifications.allEvents')}</span>
								{/if}
								{#if row.secret_set}
									<span class="notif-tag secret">{$t('apps.detail.notifications.signed')}</span>
								{/if}
								{#if !row.enabled}
									<span class="notif-tag muted">{$t('apps.detail.notifications.disabled')}</span>
								{/if}
							</span>
						</div>
						<div class="notif-actions">
							<button
								class="forge-btn-ghost"
								onclick={() => startEdit(row)}
								aria-label={$t('apps.detail.notifications.edit')}
							>
								<IconEdit size={13} />
							</button>
							<button
								class="forge-btn-ghost danger"
								onclick={() => (confirmDeleteId = row.id)}
								aria-label={$t('apps.detail.notifications.delete')}
							>
								<IconTrash size={13} />
							</button>
						</div>
					</li>
				{/each}
			</ul>
		{/if}

		{#if editingId === null}
			<button class="forge-btn-ghost notif-add" onclick={startAdd}>
				<IconPlus size={13} />
				<span>{$t('apps.detail.notifications.add')}</span>
			</button>
		{/if}
	{/if}

	{#if editingId !== null}
		<div class="notif-form">
			<label class="sub">
				<span class="sub-label">{$t('apps.detail.notifications.name')}</span>
				<input
					type="text"
					class="input"
					bind:value={formName}
					placeholder={$t('apps.detail.notifications.namePlaceholder')}
					autocomplete="off"
				/>
			</label>
			<label class="sub">
				<span class="sub-label">{$t('apps.detail.notifications.url')}</span>
				<input
					type="url"
					class="input mono"
					bind:value={formURL}
					placeholder="https://hooks.slack.com/services/..."
					autocomplete="off"
				/>
			</label>
			<label class="sub">
				<span class="sub-label">{$t('apps.detail.notifications.secret')}</span>
				<input
					type="password"
					class="input mono"
					bind:value={formSecret}
					placeholder={editingId
						? $t('apps.detail.notifications.secretEditPlaceholder')
						: $t('apps.detail.notifications.secretPlaceholder')}
					autocomplete="new-password"
				/>
				<span class="hint">{$t('apps.detail.notifications.secretHint')}</span>
			</label>
			<label class="sub">
				<span class="sub-label">{$t('apps.detail.notifications.eventTypes')}</span>
				<input
					type="text"
					class="input mono"
					bind:value={formEventTypes}
					placeholder={$t('apps.detail.notifications.eventTypesPlaceholder')}
					autocomplete="off"
					spellcheck="false"
				/>
				<span class="hint">{$t('apps.detail.notifications.eventTypesHint')}</span>
			</label>
			<div class="sub toggle-row">
				<span class="sub-label">{$t('apps.detail.notifications.enabled')}</span>
				<ToggleSwitch bind:checked={formEnabled} ariaLabel={$t('apps.detail.notifications.enabled')} />
			</div>
			<div class="notif-form-actions">
				<button class="forge-btn-ghost" onclick={cancelEdit} disabled={saving}>
					{$t('apps.detail.notifications.cancel')}
				</button>
				<button class="forge-btn" onclick={save} disabled={!formValid || saving}>
					{saving ? $t('apps.detail.notifications.saving') : $t('apps.detail.notifications.save')}
				</button>
			</div>
		</div>
	{/if}
</section>

{#if confirmDeleteId}
	<ConfirmDialog
		open={true}
		title={$t('apps.detail.notifications.confirmDeleteTitle')}
		message={$t('apps.detail.notifications.confirmDeleteMessage')}
		confirmLabel={$t('apps.detail.notifications.delete')}
		confirmVariant="danger"
		onconfirm={() => confirmDeleteId && doDelete(confirmDeleteId)}
		oncancel={() => (confirmDeleteId = null)}
	/>
{/if}

<style>
	.notif-panel {
		margin-top: 1rem;
	}
	.notif-list {
		list-style: none;
		margin: 0.7rem 0 0;
		padding: 0;
		display: flex;
		flex-direction: column;
		gap: 0.5rem;
	}
	.notif-row {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: 0.85rem;
		padding: 0.65rem 0.85rem;
		background: var(--surface-card-hover);
		border: 1px solid var(--border-primary);
		border-radius: 4px;
	}
	.notif-row.disabled {
		opacity: 0.55;
	}
	.notif-main {
		display: flex;
		flex-direction: column;
		gap: 0.2rem;
		min-width: 0;
		flex: 1;
	}
	.notif-name {
		font-weight: 600;
		font-size: 0.85rem;
	}
	.notif-url {
		font-size: 0.75rem;
		color: var(--text-secondary);
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}
	.notif-meta {
		display: flex;
		flex-wrap: wrap;
		gap: 0.35rem;
		margin-top: 0.15rem;
	}
	.notif-tag {
		font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
		font-size: 0.68rem;
		padding: 0.1rem 0.45rem;
		border: 1px solid var(--border-primary);
		border-radius: 3px;
		letter-spacing: 0.04em;
	}
	.notif-tag.secret {
		border-color: var(--accent-warm, #c08458);
	}
	.notif-tag.muted {
		color: var(--text-tertiary);
	}
	.notif-actions {
		display: flex;
		gap: 0.35rem;
	}
	.notif-add {
		margin-top: 0.85rem;
		font-size: 0.7rem;
		letter-spacing: 0.12em;
		text-transform: uppercase;
	}
	.notif-form {
		margin-top: 1rem;
		padding-top: 0.95rem;
		border-top: 1px dashed var(--border-primary);
		display: flex;
		flex-direction: column;
		gap: 0.7rem;
	}
	.notif-form .sub {
		display: flex;
		flex-direction: column;
		gap: 0.25rem;
	}
	.notif-form .sub-label {
		font-size: 0.7rem;
		letter-spacing: 0.1em;
		text-transform: uppercase;
		color: var(--text-secondary);
	}
	.notif-form .toggle-row {
		flex-direction: row;
		align-items: center;
		gap: 0.65rem;
	}
	.notif-form-actions {
		display: flex;
		gap: 0.5rem;
		justify-content: flex-end;
	}
	.hint {
		font-size: 0.72rem;
		color: var(--text-tertiary);
	}
</style>
