<script lang="ts">
	import { onMount } from 'svelte';
	import { goto } from '$app/navigation';
	import * as api from '$lib/api';
	import type { SharedSecretInput } from '$lib/api';
	import type { EntityPickerItem, App } from '$lib/types';
	import ForgeHero from '$lib/components/ForgeHero.svelte';
	import ToggleSwitch from '$lib/components/ToggleSwitch.svelte';
	import EntityPicker from '$lib/components/EntityPicker.svelte';
	import { IconX } from '$lib/components/icons';
	import { t } from '$lib/i18n';

	let name = $state('');
	// The secret value lives only in this in-memory field — never logged
	// and never persisted client-side beyond the form lifetime.
	let value = $state('');
	let encrypted = $state(true);
	let scope = $state<'global' | 'app'>('global');
	let appID = $state('');
	let description = $state('');
	let enabled = $state(true);

	let submitting = $state(false);
	let error = $state('');

	// App picker state. Loaded once on mount so the modal is instant.
	// Failure to load is non-fatal — surfaced in the page-level alert.
	let apps = $state<App[]>([]);
	let pickerOpen = $state(false);

	// Map each app grouping to a picker item.
	const pickerItems = $derived<EntityPickerItem[]>(
		apps.map((a) => ({
			value: a.id,
			label: a.name,
			description: a.description
		}))
	);

	const selectedApp = $derived(apps.find((a) => a.id === appID));

	// CREATE requires: name + scope; for app scope, an app_id too.
	const canSubmit = $derived(
		name.trim() !== '' && (scope === 'global' || appID.trim() !== '')
	);

	onMount(async () => {
		try {
			apps = await api.listApps();
		} catch (e) {
			error = e instanceof Error ? e.message : 'Failed to load apps';
		}
	});

	function pickApp(value: string): void {
		appID = value;
		pickerOpen = false;
	}

	function clearApp(): void {
		appID = '';
	}

	// Switching back to global drops any selected app so we never send a
	// stale app_id with a global secret.
	function onScopeChange(): void {
		if (scope === 'global') appID = '';
	}

	async function submit(e: Event): Promise<void> {
		e.preventDefault();
		if (submitting || !canSubmit) return;
		error = '';
		submitting = true;
		try {
			const body: SharedSecretInput = {
				name: name.trim(),
				encrypted,
				scope,
				app_id: scope === 'app' ? appID.trim() : '',
				description: description.trim(),
				enabled
			};
			// Only send a value if the operator typed one. An empty secret
			// is technically allowed; omitting the field keeps the body lean.
			if (value !== '') body.value = value;
			const created = await api.createSharedSecret(body);
			goto(`/shared-secrets/${created.id}`);
		} catch (e) {
			error = conflictMessage(e);
		} finally {
			submitting = false;
		}
	}

	// A duplicate (scope, app_id, name) returns 409 — surface a friendly
	// message instead of the raw backend error.
	function conflictMessage(e: unknown): string {
		const msg = e instanceof Error ? e.message : 'Create failed';
		if (/\b409\b/.test(msg) || /conflict/i.test(msg) || /already exists/i.test(msg)) {
			return $t('sharedsecrets.form.conflict');
		}
		return msg;
	}
</script>

<svelte:head>
	<title>{$t('sharedsecrets.titleNew')} · Tinyforge</title>
</svelte:head>

<div class="forge">
	{#snippet lede()}
		{$t('sharedsecrets.ledeNew')}
	{/snippet}

	<ForgeHero
		backHref="/shared-secrets"
		backLabel={$t('sharedsecrets.toolbar.backToList')}
		eyebrowSuffix={$t('sharedsecrets.toolbar.newButton').toUpperCase()}
		title={$t('sharedsecrets.titleNew')}
		size="lg"
		lede_html={lede}
	/>

	<form onsubmit={submit} class="form" aria-busy={submitting}>
		{#if error}
			<div class="alert" role="alert">
				<span class="alert-tag">ERR</span><span>{error}</span>
			</div>
		{/if}

		<div class="field">
			<label for="s-name" class="field-label">
				<span class="num" aria-hidden="true">01</span>
				<span class="lbl">{$t('sharedsecrets.form.name')}</span>
				<span class="req">{$t('sharedsecrets.form.required')}</span>
			</label>
			<input
				id="s-name"
				type="text"
				class="input mono"
				bind:value={name}
				required
				autocomplete="off"
				placeholder={$t('sharedsecrets.form.namePlaceholder')}
			/>
			<p class="hint">{$t('sharedsecrets.form.nameHint')}</p>
		</div>

		<div class="field group">
			<div class="field-label">
				<span class="num" aria-hidden="true">02</span>
				<span class="lbl">{$t('sharedsecrets.form.value')}</span>
				<span class="opt">{$t('sharedsecrets.form.optional')}</span>
			</div>
			<input
				id="s-value"
				type="password"
				class="input mono"
				bind:value
				autocomplete="new-password"
				placeholder={$t('sharedsecrets.form.valuePlaceholder')}
			/>
			<p class="hint">{$t('sharedsecrets.form.valueHintNew')}</p>
			<div class="row-toggle inline">
				<div class="toggle-copy">
					<span class="lbl small" aria-hidden="true">{$t('sharedsecrets.form.encrypted')}</span>
					<p class="hint">{$t('sharedsecrets.form.encryptedHint')}</p>
				</div>
				<ToggleSwitch bind:checked={encrypted} label={$t('sharedsecrets.form.encrypted')} />
			</div>
		</div>

		<div class="field">
			<label for="s-scope" class="field-label">
				<span class="num" aria-hidden="true">03</span>
				<span class="lbl">{$t('sharedsecrets.form.scope')}</span>
				<span class="req">{$t('sharedsecrets.form.required')}</span>
			</label>
			<select id="s-scope" class="input" bind:value={scope} onchange={onScopeChange}>
				<option value="global">{$t('sharedsecrets.form.scopeGlobalOption')}</option>
				<option value="app">{$t('sharedsecrets.form.scopeAppOption')}</option>
			</select>
			{#if scope === 'app'}
				<div class="scope-picker">
					{#if appID === ''}
						<div class="scope-state global">
							<span class="scope-icon" aria-hidden="true">●</span>
							<span class="scope-text muted">{$t('sharedsecrets.form.scopeAppEmpty')}</span>
							<button
								type="button"
								class="forge-btn-ghost xs"
								onclick={() => (pickerOpen = true)}
							>
								{$t('sharedsecrets.form.scopePick')}
							</button>
						</div>
					{:else}
						<div class="scope-state app">
							<span class="scope-tag">{$t('sharedsecrets.form.scopeSelected')}</span>
							{#if selectedApp}
								<span class="scope-text">{selectedApp.name}</span>
								{#if selectedApp.description}
									<code class="scope-meta">{selectedApp.description}</code>
								{/if}
							{:else}
								<span class="scope-text muted">{$t('sharedsecrets.form.scopeUnknown')}</span>
								<code class="scope-meta">{appID}</code>
							{/if}
							<button
								type="button"
								class="forge-btn-ghost xs"
								onclick={() => (pickerOpen = true)}
							>
								{$t('observability.edit')}
							</button>
							<button
								type="button"
								class="scope-clear"
								onclick={clearApp}
								aria-label={$t('sharedsecrets.form.scopeClear')}
								title={$t('sharedsecrets.form.scopeClear')}
							>
								<IconX size={14} />
							</button>
						</div>
					{/if}
				</div>
			{/if}
			<p class="hint">{$t('sharedsecrets.form.scopeHint')}</p>
		</div>

		<div class="field">
			<label for="s-description" class="field-label">
				<span class="num" aria-hidden="true">04</span>
				<span class="lbl">{$t('sharedsecrets.form.description')}</span>
				<span class="opt">{$t('sharedsecrets.form.optional')}</span>
			</label>
			<input
				id="s-description"
				type="text"
				class="input"
				bind:value={description}
				placeholder={$t('sharedsecrets.form.descriptionPlaceholder')}
			/>
		</div>

		<div class="field row-toggle">
			<div class="toggle-copy">
				<span class="lbl small" aria-hidden="true">{$t('sharedsecrets.form.enabled')}</span>
				<p class="hint">{$t('sharedsecrets.form.enabledHint')}</p>
			</div>
			<ToggleSwitch bind:checked={enabled} label={$t('sharedsecrets.form.enabled')} />
		</div>

		<div class="actions">
			<a href="/shared-secrets" class="forge-btn-ghost">{$t('observability.cancel')}</a>
			<button
				type="submit"
				class="forge-btn"
				disabled={submitting || !canSubmit}
				aria-busy={submitting}
			>
				{submitting ? $t('sharedsecrets.form.submitting') : $t('sharedsecrets.form.submit')}
			</button>
		</div>
	</form>

	<EntityPicker
		bind:open={pickerOpen}
		items={pickerItems}
		current={appID}
		title={$t('sharedsecrets.form.scopePickTitle')}
		onselect={pickApp}
		onclose={() => (pickerOpen = false)}
	/>
</div>

<style>
	.forge {
		display: flex;
		flex-direction: column;
		gap: 1rem;
		max-width: 820px;
		margin: 0 auto;
	}
	.form {
		display: flex;
		flex-direction: column;
		gap: 1.5rem;
		background: var(--surface-card);
		border: 1px solid var(--border-primary);
		border-radius: var(--radius-2xl);
		padding: 1.75rem;
	}
	@media (max-width: 600px) {
		.form {
			padding: 1.1rem;
			gap: 1.25rem;
		}
	}

	/* ── Alert ─────────────────────────────────────── */
	.alert {
		display: flex;
		gap: 0.7rem;
		align-items: center;
		padding: 0.7rem 0.9rem;
		background: var(--color-danger-light);
		color: var(--color-danger-dark);
		border: 1px solid var(--color-danger);
		border-left-width: 4px;
		border-radius: var(--radius-lg);
		font-size: 0.875rem;
	}
	.alert-tag {
		font-family: var(--forge-mono);
		font-weight: 700;
		font-size: 0.65rem;
		letter-spacing: 0.16em;
		padding: 0.15rem 0.4rem;
		background: var(--color-danger);
		color: var(--surface-card);
		border-radius: var(--radius-sm);
	}
	:global([data-theme='dark']) .alert {
		background: color-mix(in srgb, var(--color-danger) 14%, transparent);
		color: color-mix(in srgb, var(--color-danger) 60%, var(--text-primary));
	}

	/* ── Field structure ────────────────────────────── */
	.field {
		display: flex;
		flex-direction: column;
		gap: 0.55rem;
		margin: 0;
		padding: 0;
		border: 0;
	}
	.field.group {
		gap: 0.75rem;
	}
	.field-label {
		display: flex;
		align-items: center;
		flex-wrap: wrap;
		gap: 0.55rem;
	}
	.num {
		display: inline-flex;
		width: 26px;
		height: 26px;
		justify-content: center;
		align-items: center;
		background: var(--text-primary);
		color: var(--surface-card);
		border-radius: var(--radius-sm);
		font-family: var(--forge-mono);
		font-size: 0.7rem;
		font-weight: 700;
		flex: 0 0 auto;
	}
	.lbl {
		font-weight: 600;
		font-size: 1.1rem;
		letter-spacing: -0.01em;
		color: var(--text-primary);
	}
	.lbl.small {
		font-size: 0.95rem;
	}
	.req,
	.opt {
		font-family: var(--forge-mono);
		font-size: 0.58rem;
		font-weight: 600;
		text-transform: uppercase;
		letter-spacing: 0.14em;
	}
	.req {
		color: var(--color-danger);
	}
	.opt {
		color: var(--text-tertiary);
	}

	/* ── Inputs ─────────────────────────────────────── */
	.input {
		width: 100%;
		background: var(--surface-input);
		border: 1px solid var(--border-input);
		border-radius: var(--radius-lg);
		padding: 0.55rem 0.75rem;
		font-size: 0.9rem;
		color: var(--text-primary);
		font-family: inherit;
		outline: none;
		transition: border-color 120ms ease, box-shadow 120ms ease;
	}
	.input.mono {
		font-family: var(--forge-mono);
	}
	.input:focus {
		border-color: var(--border-focus);
		box-shadow: 0 0 0 3px var(--forge-accent-soft);
	}

	/* ── Hints ──────────────────────────────────────── */
	.hint {
		font-size: 0.78rem;
		color: var(--text-tertiary);
		line-height: 1.5;
		margin: 0;
	}

	/* ── Toggle row ─────────────────────────────────── */
	.row-toggle {
		display: flex;
		flex-direction: row;
		align-items: flex-start;
		justify-content: space-between;
		gap: 1rem;
		padding-top: 0.6rem;
		border-top: 1px dashed var(--border-primary);
	}
	.row-toggle.inline {
		padding-top: 0;
		border-top: 0;
	}
	.toggle-copy {
		flex: 1;
		display: flex;
		flex-direction: column;
		gap: 0.25rem;
	}

	/* ── Action footer ──────────────────────────────── */
	.actions {
		display: flex;
		justify-content: flex-end;
		gap: 0.55rem;
		flex-wrap: wrap;
	}
	@media (max-width: 480px) {
		.actions {
			flex-direction: column-reverse;
			align-items: stretch;
		}
		.actions :global(.forge-btn),
		.actions :global(.forge-btn-ghost) {
			justify-content: center;
		}
	}

	/* ── Scope picker chip ────────────────────────────────────
	   Renders the selected app as a single state row: either
	   "● [Pick app…]" or "App · <name> <desc> [Edit] [×]".
	   Visual style mirrors the metric-alert scope chip. */
	.scope-picker {
		display: flex;
		flex-direction: column;
		gap: 0.4rem;
	}
	.scope-state {
		display: flex;
		flex-wrap: wrap;
		align-items: center;
		gap: 0.55rem;
		padding: 0.55rem 0.75rem;
		background: var(--surface-card-hover);
		border: 1px solid var(--border-primary);
		border-radius: var(--radius-lg);
	}
	.scope-state.global {
		border-style: dashed;
	}
	.scope-state.app {
		background: color-mix(in srgb, var(--color-brand-500) 8%, var(--surface-card-hover));
		border-color: color-mix(in srgb, var(--color-brand-500) 35%, var(--border-primary));
	}
	.scope-icon {
		font-size: 0.7rem;
		color: var(--text-tertiary);
	}
	.scope-text {
		font-weight: 600;
		font-size: 0.92rem;
		color: var(--text-primary);
	}
	.scope-text.muted {
		color: var(--text-tertiary);
		font-style: italic;
	}
	.scope-tag {
		font-family: var(--forge-mono);
		font-size: 0.6rem;
		font-weight: 700;
		letter-spacing: 0.14em;
		text-transform: uppercase;
		padding: 0.12rem 0.4rem;
		background: var(--color-brand-500);
		color: var(--surface-card);
		border-radius: var(--radius-sm);
	}
	.scope-meta {
		font-family: var(--forge-mono);
		font-size: 0.72rem;
		color: var(--text-secondary);
		padding: 0.1rem 0.35rem;
		background: var(--surface-card);
		border: 1px solid var(--border-primary);
		border-radius: var(--radius-sm);
	}
	.scope-state .forge-btn-ghost {
		margin-left: auto;
	}
	.scope-state.app .forge-btn-ghost {
		margin-left: auto;
		margin-right: 0;
	}
	.scope-clear {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		width: 26px;
		height: 26px;
		background: transparent;
		border: 1px solid var(--border-primary);
		border-radius: var(--radius-md);
		color: var(--text-tertiary);
		cursor: pointer;
		transition: color 120ms ease, border-color 120ms ease;
	}
	.scope-clear:hover {
		color: var(--color-danger);
		border-color: var(--color-danger);
	}
	:global(.forge-btn-ghost.xs) {
		padding: 0.2rem 0.55rem;
		font-size: 0.62rem;
	}
</style>
