<script lang="ts">
	import { t } from '$lib/i18n';
	import MdiIcon from '$lib/components/MdiIcon.svelte';
	import Hint from '$lib/components/Hint.svelte';
	import IconGridSelect from '$lib/components/IconGridSelect.svelte';
	import { logLevelItems, logFormatItems } from '$lib/grid-items';

	type Level = 'DEBUG' | 'INFO' | 'WARNING' | 'ERROR';

	interface Override {
		module: string;
		level: Level;
	}

	interface Props {
		logLevel: string;
		logFormat: string;
		logLevels: string;
	}

	let {
		logLevel = $bindable(),
		logFormat = $bindable(),
		logLevels = $bindable(),
	}: Props = $props();

	const LEVELS: Level[] = ['DEBUG', 'INFO', 'WARNING', 'ERROR'];
	const LEVEL_TONE: Record<Level, string> = {
		DEBUG: 'sky',
		INFO: 'mint',
		WARNING: 'citrus',
		ERROR: 'coral',
	};

	let rawMode = $state(false);

	// Parse the comma-separated `module=LEVEL,...` string into structured rows.
	function parse(csv: string): Override[] {
		if (!csv) return [];
		const out: Override[] = [];
		const seen = new Set<string>();
		for (const raw of csv.split(',')) {
			const piece = raw.trim();
			if (!piece) continue;
			const eq = piece.indexOf('=');
			if (eq < 0) continue;
			const module = piece.slice(0, eq).trim();
			const lvlRaw = piece.slice(eq + 1).trim().toUpperCase();
			if (!module || seen.has(module)) continue;
			const level = (LEVELS.includes(lvlRaw as Level) ? lvlRaw : 'INFO') as Level;
			seen.add(module);
			out.push({ module, level });
		}
		return out;
	}

	function serialize(rows: Override[]): string {
		return rows
			.filter(r => r.module.trim().length > 0)
			.map(r => `${r.module.trim()}=${r.level}`)
			.join(',');
	}

	let rows = $state<Override[]>(parse(logLevels));
	let lastEmitted = $state(logLevels);

	// Re-parse when the upstream string changes from outside (e.g. fetch / reset).
	$effect(() => {
		if (logLevels !== lastEmitted) {
			rows = parse(logLevels);
			lastEmitted = logLevels;
		}
	});

	function commit(next: Override[]): void {
		rows = next;
		const serialized = serialize(next);
		lastEmitted = serialized;
		logLevels = serialized;
	}

	function addRow(): void {
		commit([...rows, { module: '', level: 'INFO' }]);
	}

	function removeRow(i: number): void {
		commit(rows.filter((_, idx) => idx !== i));
	}

	function updateModule(i: number, value: string): void {
		const next = rows.map((r, idx) => (idx === i ? { ...r, module: value } : r));
		commit(next);
	}

	function updateLevel(i: number, level: Level): void {
		const next = rows.map((r, idx) => (idx === i ? { ...r, level } : r));
		commit(next);
	}

	const previewLine = $derived.by(() => {
		const root = (logLevel || 'INFO').toUpperCase();
		if (rows.length === 0) return `root=${root}`;
		return `root=${root}, ${rows.map(r => `${r.module || '?'}=${r.level}`).join(', ')}`;
	});
</script>

<section class="logging glass">
	<header class="log-head">
		<div class="log-eyebrow">
			<MdiIcon name="mdiTextBoxOutline" size={12} />
			<span>{t('settings.logging')}</span>
		</div>
		<h3 class="log-title">{t('settings.loggingHeadline')}</h3>
	</header>

	<!-- Level + format -->
	<div class="log-row">
		<div class="log-cell">
			<span class="log-label">
				{t('settings.logLevel')}
				<Hint text={t('settings.logLevelHint')} />
			</span>
			<IconGridSelect items={logLevelItems()} bind:value={logLevel} columns={2} />
		</div>
		<div class="log-cell">
			<span class="log-label">
				{t('settings.logFormat')}
				<Hint text={t('settings.logFormatHint')} />
			</span>
			<IconGridSelect items={logFormatItems()} bind:value={logFormat} columns={2} />
		</div>
	</div>

	<!-- Per-module overrides -->
	<div class="overrides">
		<div class="overrides-head">
			<span class="log-label">
				{t('settings.logLevels')}
				<Hint text={t('settings.logLevelsHint')} />
			</span>
			<button
				type="button"
				class="mode-toggle"
				onclick={() => (rawMode = !rawMode)}
				title={rawMode ? t('settings.editAsChips') : t('settings.editAsText')}
			>
				<MdiIcon name={rawMode ? 'mdiViewList' : 'mdiCodeBraces'} size={12} />
				<span>{rawMode ? t('settings.editAsChips') : t('settings.editAsText')}</span>
			</button>
		</div>

		{#if rawMode}
			<input
				bind:value={logLevels}
				placeholder="sqlalchemy.engine=WARNING,notify_bridge_core.notifications.telegram.client=DEBUG"
				class="raw-input"
			/>
		{:else}
			<div class="chip-stack">
				{#each rows as row, i (i)}
					{@const tone = LEVEL_TONE[row.level]}
					<div class="chip" data-tone={tone}>
						<span class="chip-edge" aria-hidden="true"></span>
						<input
							value={row.module}
							oninput={(e) => updateModule(i, (e.currentTarget as HTMLInputElement).value)}
							placeholder={t('settings.logModulePlaceholder')}
							class="chip-input"
							autocomplete="off"
							spellcheck="false"
						/>
						<span class="chip-sep" aria-hidden="true">=</span>
						<select
							value={row.level}
							onchange={(e) => updateLevel(i, (e.currentTarget as HTMLSelectElement).value as Level)}
							class="chip-level"
							aria-label={t('settings.logLevel')}
						>
							{#each LEVELS as lvl}
								<option value={lvl}>{lvl}</option>
							{/each}
						</select>
						<button
							type="button"
							class="chip-remove"
							onclick={() => removeRow(i)}
							aria-label={t('settings.removeOverride')}
							title={t('settings.removeOverride')}
						>
							<MdiIcon name="mdiClose" size={13} />
						</button>
					</div>
				{/each}

				<button type="button" class="chip-add" onclick={addRow}>
					<MdiIcon name="mdiPlus" size={13} />
					<span>{t('settings.addOverride')}</span>
				</button>
			</div>
		{/if}

		<!-- Live preview -->
		<div class="preview" role="status">
			<span class="preview-eyebrow">{t('settings.logPreviewLabel')}</span>
			<code class="preview-text">{previewLine}</code>
		</div>
	</div>
</section>

<style>
	.logging {
		padding: 1.5rem 1.6rem 1.4rem;
		display: flex;
		flex-direction: column;
		gap: 1.15rem;
	}
	.log-head {
		position: relative;
		z-index: 1;
	}
	.log-eyebrow {
		display: inline-flex;
		align-items: center;
		gap: 0.35rem;
		font-family: var(--font-mono);
		font-size: 0.62rem;
		text-transform: uppercase;
		letter-spacing: 0.18em;
		color: var(--color-muted-foreground);
		margin-bottom: 0.45rem;
	}
	.log-title {
		margin: 0;
		font-family: var(--font-display);
		font-style: italic;
		font-weight: 400;
		font-size: 1.15rem;
		line-height: 1.35;
		letter-spacing: -0.015em;
		color: var(--color-foreground);
		max-width: 38ch;
	}

	.log-row {
		position: relative;
		z-index: 1;
		display: grid;
		grid-template-columns: 1fr;
		gap: 0.85rem;
	}
	@media (min-width: 720px) {
		.log-row { grid-template-columns: 1fr 1fr; gap: 1.4rem; }
	}
	.log-cell {
		display: flex;
		flex-direction: column;
		gap: 0.4rem;
	}
	.log-label {
		font-size: 0.75rem;
		font-weight: 500;
		color: var(--color-foreground);
		display: inline-flex;
		align-items: center;
	}

	/* --- Overrides editor --- */
	.overrides {
		position: relative;
		z-index: 1;
		display: flex;
		flex-direction: column;
		gap: 0.55rem;
		padding-top: 0.5rem;
		border-top: 1px solid var(--color-border);
	}
	.overrides-head {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: 0.5rem;
		flex-wrap: wrap;
	}
	.mode-toggle {
		display: inline-flex;
		align-items: center;
		gap: 0.3rem;
		padding: 0.25rem 0.55rem;
		border-radius: 999px;
		background: transparent;
		border: 1px solid var(--color-border);
		color: var(--color-muted-foreground);
		font-family: var(--font-mono);
		font-size: 0.6rem;
		text-transform: uppercase;
		letter-spacing: 0.12em;
		cursor: pointer;
		transition: background 0.15s, color 0.15s, border-color 0.15s;
	}
	.mode-toggle:hover {
		background: var(--color-glass-strong);
		color: var(--color-foreground);
		border-color: var(--color-rule-strong);
	}

	.raw-input {
		width: 100%;
		font-family: var(--font-mono);
		font-size: 0.78rem;
		padding: 0.6rem 0.85rem;
	}

	.chip-stack {
		display: flex;
		flex-direction: column;
		gap: 0.4rem;
	}
	.chip {
		position: relative;
		display: grid;
		grid-template-columns: 1fr auto auto auto;
		align-items: center;
		gap: 0.3rem;
		padding: 0.35rem 0.4rem 0.35rem 0.95rem;
		border-radius: 12px;
		border: 1px solid var(--color-border);
		background: var(--color-glass-strong);
		overflow: hidden;
		transition: border-color 0.18s, background 0.18s;
	}
	.chip:hover {
		border-color: var(--color-rule-strong);
		background: var(--color-glass-elev);
	}
	.chip-edge {
		position: absolute;
		left: 0; top: 0; bottom: 0;
		width: 3px;
		opacity: 0.85;
	}
	.chip[data-tone="sky"] .chip-edge    { background: var(--color-sky); }
	.chip[data-tone="mint"] .chip-edge   { background: var(--color-mint); }
	.chip[data-tone="citrus"] .chip-edge { background: var(--color-citrus); }
	.chip[data-tone="coral"] .chip-edge  { background: var(--color-coral); }

	.chip-input {
		width: 100%;
		background: transparent;
		border: 0;
		outline: 0;
		padding: 0.35rem 0;
		font-family: var(--font-mono);
		font-size: 0.78rem;
		color: var(--color-foreground);
		min-width: 0;
	}
	.chip-input::placeholder { color: var(--color-muted-foreground); opacity: 0.7; }

	.chip-sep {
		font-family: var(--font-mono);
		color: var(--color-muted-foreground);
		opacity: 0.5;
		padding: 0 0.15rem;
	}

	.chip-level {
		font-family: var(--font-mono);
		font-size: 0.7rem;
		font-weight: 500;
		padding: 0.3rem 1.6rem 0.3rem 0.6rem;
		border-radius: 8px;
		border: 1px solid var(--color-border);
		background: var(--color-glass);
		color: var(--color-foreground);
		min-width: 7.2rem;
		letter-spacing: 0.08em;
		text-transform: uppercase;
	}
	.chip[data-tone="sky"]    .chip-level { color: var(--color-sky); border-color: color-mix(in srgb, var(--color-sky) 35%, var(--color-border)); }
	.chip[data-tone="mint"]   .chip-level { color: var(--color-mint); border-color: color-mix(in srgb, var(--color-mint) 35%, var(--color-border)); }
	.chip[data-tone="citrus"] .chip-level { color: var(--color-citrus); border-color: color-mix(in srgb, var(--color-citrus) 35%, var(--color-border)); }
	.chip[data-tone="coral"]  .chip-level { color: var(--color-coral); border-color: color-mix(in srgb, var(--color-coral) 35%, var(--color-border)); }

	.chip-remove {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		width: 26px; height: 26px;
		border-radius: 8px;
		background: transparent;
		border: 0;
		color: var(--color-muted-foreground);
		cursor: pointer;
		transition: background 0.15s, color 0.15s;
	}
	.chip-remove:hover {
		background: color-mix(in srgb, var(--color-error-fg) 12%, var(--color-glass-strong));
		color: var(--color-error-fg);
	}

	.chip-add {
		display: inline-flex;
		align-items: center;
		gap: 0.35rem;
		align-self: flex-start;
		padding: 0.35rem 0.85rem;
		border-radius: 999px;
		border: 1px dashed var(--color-rule-strong);
		background: transparent;
		color: var(--color-muted-foreground);
		font-family: inherit;
		font-size: 0.72rem;
		cursor: pointer;
		transition: background 0.15s, color 0.15s, border-color 0.15s;
	}
	.chip-add:hover {
		background: color-mix(in srgb, var(--color-primary) 8%, transparent);
		color: var(--color-primary);
		border-style: solid;
		border-color: color-mix(in srgb, var(--color-primary) 45%, var(--color-rule-strong));
	}

	/* --- Live preview --- */
	.preview {
		display: flex;
		flex-direction: column;
		gap: 0.3rem;
		padding: 0.65rem 0.85rem;
		border-radius: 12px;
		background: color-mix(in srgb, var(--color-background-deep, #02030a) 30%, var(--color-glass-strong));
		border: 1px solid var(--color-border);
		overflow: hidden;
	}
	.preview-eyebrow {
		font-family: var(--font-mono);
		font-size: 0.55rem;
		text-transform: uppercase;
		letter-spacing: 0.18em;
		color: var(--color-muted-foreground);
	}
	.preview-text {
		font-family: var(--font-mono);
		font-size: 0.72rem;
		color: var(--color-foreground);
		word-break: break-all;
		line-height: 1.45;
	}
</style>
