<script lang="ts">
	import { apiMutate } from '$lib/api/client.js';
	import type {
		BgpCommunity,
		DohProfile,
		DohResolverPolicy,
		ModulePatch,
		ModuleRow
	} from '$lib/api/types.js';
	import { dohPolicyRu } from '$lib/ui-labels.js';
	import {
		communityLabel,
		communityOptionLabel,
		fromNullableSelect,
		moduleDohProfileIds,
		NONE_OPTION,
		nullableSelectValue
	} from '$lib/components/modules/module-helpers.js';
	import { Button } from '@evobgp/ui/components/button/index.js';
	import { Input } from '@evobgp/ui/components/input/index.js';
	import { Label } from '@evobgp/ui/components/label/index.js';
	import { Checkbox } from '@evobgp/ui/components/checkbox/index.js';
	import {
		Dialog,
		DialogContent,
		DialogHeader,
		DialogTitle,
		DialogFooter
	} from '@evobgp/ui/components/dialog/index.js';
	import {
		Select,
		SelectContent,
		SelectItem,
		SelectTrigger
	} from '@evobgp/ui/components/select/index.js';
	import { Switch } from '@evobgp/ui/components/switch/index.js';
	import { notify, notifyApiError } from '$lib/ui/app/toast.js';

	const dohPolicyOptions: { value: DohResolverPolicy; label: string; hint: string }[] = [
		{
			value: 'primary_only',
			label: 'Только первый',
			hint: 'Используется первый выбранный DoH-профиль.'
		},
		{
			value: 'failover',
			label: 'Резервирование',
			hint: 'Профили по порядку до первого успешного ответа.'
		},
		{
			value: 'union',
			label: 'Объединение',
			hint: 'Все A/AAAA со всех профилей (geo-split DNS).'
		}
	];

	type Props = {
		open: boolean;
		mod: ModuleRow;
		moduleId: string;
		communities: BgpCommunity[];
		dohProfiles: DohProfile[];
		onSaved: () => void | Promise<void>;
		onClose: () => void;
	};

	let {
		open = $bindable(),
		mod,
		moduleId,
		communities,
		dohProfiles,
		onSaved,
		onClose
	}: Props = $props();

	let editForm = $state<ModulePatch>({});
	let editSaving = $state(false);
	let initKey = $state('');

	function resetEditForm() {
		editForm = {
			name: mod.name,
			enabled: mod.enabled,
			priority: mod.priority,
			refresh_interval_sec: mod.refresh_interval_sec,
			cron_expr: mod.cron_expr,
			default_community_id: mod.default_community_id,
			doh_profile_ids: moduleDohProfileIds(mod),
			doh_resolver_policy: mod.doh_resolver_policy ?? 'primary_only'
		};
	}

	$effect(() => {
		if (!open) {
			initKey = '';
			return;
		}
		const nextKey = mod.id;
		if (nextKey !== initKey) {
			initKey = nextKey;
			resetEditForm();
		}
	});

	function toggleEditDohProfile(id: string, checked: boolean) {
		let ids = [...(editForm.doh_profile_ids ?? [])];
		if (checked) {
			if (!ids.includes(id)) ids.push(id);
		} else {
			ids = ids.filter((x) => x !== id);
		}
		editForm = { ...editForm, doh_profile_ids: ids };
	}

	function isEditDohProfileSelected(id: string): boolean {
		return (editForm.doh_profile_ids ?? []).includes(id);
	}

	async function saveMod() {
		editSaving = true;
		try {
			const cron =
				typeof editForm.cron_expr === 'string' ? editForm.cron_expr.trim() : editForm.cron_expr;
			const intervalRaw = editForm.refresh_interval_sec;
			const interval =
				intervalRaw === null || intervalRaw === undefined ? null : Number(intervalRaw);
			const payload: ModulePatch = {
				...editForm,
				cron_expr: cron ? cron : null,
				refresh_interval_sec: Number.isFinite(interval) ? interval : null,
				default_community_id: fromNullableSelect(
					nullableSelectValue(editForm.default_community_id)
				),
				doh_profile_ids: editForm.doh_profile_ids ?? [],
				doh_resolver_policy: editForm.doh_resolver_policy ?? 'primary_only'
			};
			await apiMutate<ModuleRow>(`/v1/modules/${moduleId}`, 'PATCH', payload);
			notify.success('Модуль обновлён');
			open = false;
			await onSaved();
		} catch (e) {
			notifyApiError(e);
		} finally {
			editSaving = false;
		}
	}

	function handleOpenChange(next: boolean) {
		open = next;
		if (!next) onClose();
	}
</script>

<Dialog bind:open onOpenChange={handleOpenChange}>
	<DialogContent class="sm:max-w-md">
		<DialogHeader>
			<DialogTitle>Редактировать модуль</DialogTitle>
		</DialogHeader>
		<div class="space-y-4 py-2">
			<div class="space-y-1.5">
				<Label for="e-name">Название</Label>
				<Input id="e-name" bind:value={editForm.name} />
			</div>
			<div class="grid grid-cols-2 gap-4">
				<div class="space-y-1.5">
					<Label for="e-priority">Приоритет</Label>
					<Input id="e-priority" type="number" bind:value={editForm.priority} />
				</div>
				<div class="space-y-1.5">
					<Label for="e-interval">Интервал (сек)</Label>
					<Input id="e-interval" type="number" bind:value={editForm.refresh_interval_sec} />
				</div>
			</div>
			<div class="space-y-1.5">
				<Label for="e-cron">Cron-выражение</Label>
				<Input id="e-cron" placeholder="0 */6 * * *" bind:value={editForm.cron_expr} />
			</div>
			<div class="space-y-1.5">
				<Label for="e-comm">Community по умолчанию</Label>
				<Select
					type="single"
					value={nullableSelectValue(editForm.default_community_id)}
					onValueChange={(v) => {
						editForm.default_community_id = fromNullableSelect(v);
					}}
				>
					<SelectTrigger id="e-comm" class="w-full">
						{editForm.default_community_id
							? communityLabel(editForm.default_community_id, communities)
							: 'Не выбрано'}
					</SelectTrigger>
					<SelectContent>
						<SelectItem value={NONE_OPTION}>Не выбрано</SelectItem>
						{#each communities as c (c.id)}
							<SelectItem value={c.id}>{communityOptionLabel(c)}</SelectItem>
						{/each}
					</SelectContent>
				</Select>
				<Button
					type="button"
					variant="ghost"
					size="sm"
					class="h-7 px-2"
					onclick={() => {
						editForm.default_community_id = null;
					}}
				>
					Сбросить
				</Button>
			</div>
			{#if mod.type === 'DOMAINS'}
				<div class="space-y-1.5">
					<Label for="e-doh-policy">Политика DoH</Label>
					<Select
						type="single"
						value={editForm.doh_resolver_policy ?? 'primary_only'}
						onValueChange={(v) => {
							if (v) editForm.doh_resolver_policy = v as DohResolverPolicy;
						}}
					>
						<SelectTrigger id="e-doh-policy" class="w-full">
							{dohPolicyRu(editForm.doh_resolver_policy)}
						</SelectTrigger>
						<SelectContent>
							{#each dohPolicyOptions as opt (opt.value)}
								<SelectItem value={opt.value}>{opt.label}</SelectItem>
							{/each}
						</SelectContent>
					</Select>
					<p class="text-xs text-muted-foreground">
						{dohPolicyOptions.find(
							(o) => o.value === (editForm.doh_resolver_policy ?? 'primary_only')
						)?.hint}
					</p>
				</div>
				<div class="space-y-2">
					<Label>DoH-профили</Label>
					<p class="text-xs text-muted-foreground">
						Порядок выбора = порядок в списке (сверху вниз).
					</p>
					<div class="max-h-40 space-y-2 overflow-y-auto rounded-md border p-3">
						{#each dohProfiles as d (d.id)}
							<label class="flex items-start gap-2 text-sm">
								<Checkbox
									checked={isEditDohProfileSelected(d.id)}
									onCheckedChange={(v) => toggleEditDohProfile(d.id, v === true)}
								/>
								<span class="min-w-0 break-all">
									<span class="font-medium">{d.name?.trim() ? d.name : d.url}</span>
									{#if d.name?.trim()}
										<span class="block font-mono text-xs text-muted-foreground">{d.url}</span>
									{/if}
								</span>
							</label>
						{:else}
							<p class="text-xs text-muted-foreground">Нет профилей — создайте в справочниках.</p>
						{/each}
					</div>
					<Button
						type="button"
						variant="ghost"
						size="sm"
						class="h-7 px-2"
						onclick={() => {
							editForm = { ...editForm, doh_profile_ids: [] };
						}}
					>
						Сбросить профили
					</Button>
				</div>
			{/if}
			<div
				class="flex flex-row items-center justify-between gap-4 rounded-lg border border-border bg-muted/30 p-3"
			>
				<div class="grid min-w-0 flex-1 gap-1 pr-2">
					<Label for="e-enabled" class="leading-snug text-foreground">Включён</Label>
					<p class="text-xs leading-snug text-muted-foreground">
						Отключённые модули не участвуют в обновлении конфигурации.
					</p>
				</div>
				<Switch
					id="e-enabled"
					class="shrink-0"
					checked={editForm.enabled !== false}
					onCheckedChange={(v) => {
						editForm = { ...editForm, enabled: v };
					}}
				/>
			</div>
		</div>
		<DialogFooter>
			<Button variant="outline" onclick={() => handleOpenChange(false)}>Отмена</Button>
			<Button onclick={saveMod} disabled={editSaving}>
				{editSaving ? 'Сохранение…' : 'Сохранить'}
			</Button>
		</DialogFooter>
	</DialogContent>
</Dialog>
