<script lang="ts">
	import { onMount } from 'svelte';
	import { slide } from 'svelte/transition';
	import { api , errMsg} from '$lib/api';
	import { t } from '$lib/i18n';
	import { actionsCache, providersCache, capabilitiesCache } from '$lib/stores/caches.svelte';
	import PageHeader from '$lib/components/PageHeader.svelte';
	import Card from '$lib/components/Card.svelte';
	import Loading from '$lib/components/Loading.svelte';
	import IconPicker from '$lib/components/IconPicker.svelte';
	import MdiIcon from '$lib/components/MdiIcon.svelte';
	import EmptyState from '$lib/components/EmptyState.svelte';
	import ConfirmModal from '$lib/components/ConfirmModal.svelte';
	import IconButton from '$lib/components/IconButton.svelte';
	import EntitySelect from '$lib/components/EntitySelect.svelte';
	import CrossLink from '$lib/components/CrossLink.svelte';
	import { snackSuccess, snackError } from '$lib/stores/snackbar.svelte';
	import { highlightFromUrl } from '$lib/highlight';
	import { globalProviderFilter } from '$lib/stores/provider-filter.svelte';
	import { providerDefaultIcon } from '$lib/grid-items';
	import RuleEditor from './RuleEditor.svelte';
	import ExecutionHistory from './ExecutionHistory.svelte';
	import ErrorBanner from '$lib/components/ErrorBanner.svelte';
	import Button from '$lib/components/Button.svelte';
	import MetaStrip, { type MetaTile } from '$lib/components/MetaStrip.svelte';
	import type { Action, ActionRule } from '$lib/types';

	let allActions = $derived(actionsCache.items);
	let providers = $derived(providersCache.items);
	let filterText = $state('');
	let actions = $derived(allActions.filter((a: Action) =>
		(!filterText || a.name.toLowerCase().includes(filterText.toLowerCase()) || a.action_type.toLowerCase().includes(filterText.toLowerCase())) &&
		(!globalProviderFilter.id || a.provider_id === globalProviderFilter.id)
	));

	let showForm = $state(false);
	let editing = $state<number | null>(null);
	let form = $state({
		name: '', provider_id: 0, action_type: 'auto_organize', icon: '',
		config: {} as Record<string, any>,
		schedule_type: 'interval', schedule_interval: 3600, schedule_cron: '',
		enabled: false,
	});
	let nameManuallyEdited = $state(false);
	let error = $state('');

	function actionTypeLabel(at: string): string {
		return at.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
	}
	$effect(() => {
		if (showForm && !nameManuallyEdited && !editing) {
			const provider = providers.find((p: any) => p.id === form.provider_id);
			const at = actionTypeLabel(form.action_type || '');
			form.name = provider ? `${provider.name} ${at}`.trim() : at || 'Action';
		}
	});
	let loadError = $state('');
	let submitting = $state(false);
	let loaded = $state(false);
	let confirmDelete = $state<Action | null>(null);
	let executing = $state<Record<number, boolean>>({});
	let historyActionId = $state<number | null>(null);

	// Providers that support actions
	let actionProviders = $derived(providers.filter((p: any) => {
		const caps = capabilitiesCache.items[p.type];
		return caps && caps.action_types && caps.action_types.length > 0;
	}));

	let providerItems = $derived(actionProviders
		.filter((p: any) => !globalProviderFilter.providerType || p.type === globalProviderFilter.providerType)
		.map((p: any) => ({
			value: p.id, label: p.name, icon: providerDefaultIcon(p), desc: p.type,
		})));

	// Action types for selected provider
	let selectedProviderType = $derived(providers.find((p: any) => p.id === form.provider_id)?.type || '');
	let actionTypes = $derived((() => {
		const caps = capabilitiesCache.items[selectedProviderType];
		return caps?.action_types || [];
	})());

	onMount(load);

	const headerPills = $derived.by(() => {
		const pills: Array<{ label: string; tone: 'mint' | 'citrus' }> = [];
		const enabled = actions.filter((a: Action) => a.enabled).length;
		const disabled = actions.length - enabled;
		if (enabled > 0) pills.push({ label: `${enabled} ${t('notificationTracker.armed')}`, tone: 'mint' });
		if (disabled > 0) pills.push({ label: `${disabled} ${t('notificationTracker.paused')}`, tone: 'citrus' });
		return pills;
	});

	async function load() {
		try {
			await Promise.all([
				actionsCache.fetch(true),
				providersCache.fetch(),
				capabilitiesCache.fetch(),
			]);
			loadError = '';
		} catch (err: unknown) {
			loadError = errMsg(err, t('actions.loadError'));
		} finally { loaded = true; highlightFromUrl(); }
	}

	function openNew() {
		const defaultProvider = actionProviders[0]?.id || 0;
		form = {
			name: '', provider_id: defaultProvider, action_type: 'auto_organize', icon: '',
			config: {}, schedule_type: 'interval', schedule_interval: 3600, schedule_cron: '',
			enabled: false,
		};
		nameManuallyEdited = false;
		editing = null; showForm = true;
	}

	function edit(action: Action) {
		form = {
			name: action.name, provider_id: action.provider_id,
			action_type: action.action_type, icon: action.icon || '',
			config: { ...action.config }, schedule_type: action.schedule_type,
			schedule_interval: action.schedule_interval,
			schedule_cron: action.schedule_cron, enabled: action.enabled,
		};
		nameManuallyEdited = true;
		editing = action.id; showForm = true;
	}

	async function save(e: SubmitEvent) {
		e.preventDefault(); error = ''; submitting = true;
		try {
			const payload = { ...form };
			if (editing) {
				await api(`/actions/${editing}`, { method: 'PUT', body: JSON.stringify(payload) });
			} else {
				await api('/actions', { method: 'POST', body: JSON.stringify(payload) });
			}
			showForm = false; editing = null; actionsCache.invalidate(); await load();
			snackSuccess(t('actions.saved'));
		} catch (err: unknown) { const __m = errMsg(err); error = __m; snackError(__m); }
		submitting = false;
	}

	function startDelete(action: Action) { confirmDelete = action; }
	async function doDelete() {
		if (!confirmDelete) return;
		const id = confirmDelete.id;
		confirmDelete = null;
		try {
			await api(`/actions/${id}`, { method: 'DELETE' });
			actionsCache.invalidate(); await load();
			snackSuccess(t('actions.deleted'));
		} catch (err: unknown) { snackError(errMsg(err)); }
	}

	async function executeAction(id: number, dryRun = false) {
		executing = { ...executing, [id]: true };
		try {
			const endpoint = dryRun ? `/actions/${id}/dry-run` : `/actions/${id}/execute`;
			const result = await api<any>(endpoint, { method: 'POST' });
			const affected = result.total_items_affected || 0;
			const msg = dryRun
				? `${t('actions.dryRun')}: ${affected} ${t('actions.affected')}`
				: `${t('actions.execute')}: ${affected} ${t('actions.affected')}`;
			snackSuccess(msg);
			actionsCache.invalidate(); await load();
		} catch (err: unknown) { snackError(errMsg(err)); }
		executing = { ...executing, [id]: false };
	}

	function getProvider(providerId: number) {
		return providers.find((p: any) => p.id === providerId);
	}

	function getProviderName(providerId: number): string {
		return getProvider(providerId)?.name || '?';
	}

	function formatSchedule(action: Action): string {
		if (action.schedule_type === 'cron' && action.schedule_cron) {
			return `cron: ${action.schedule_cron}`;
		}
		const h = Math.floor(action.schedule_interval / 3600);
		const m = Math.floor((action.schedule_interval % 3600) / 60);
		if (h > 0 && m > 0) return `${h}h ${m}m`;
		if (h > 0) return `${h}h`;
		return `${action.schedule_interval}s`;
	}

	function statusColor(status: string): string {
		if (status === 'success') return 'var(--color-success-fg)';
		if (status === 'partial') return 'var(--color-warning-fg)';
		if (status === 'failed') return 'var(--color-error-fg)';
		return 'var(--color-muted-foreground)';
	}

	function statusTone(status: string | undefined): MetaTile['tone'] {
		if (status === 'success') return 'mint';
		if (status === 'partial') return 'citrus';
		if (status === 'failed') return 'coral';
		return 'default';
	}

	function actionTiles(action: Action): MetaTile[] {
		const tiles: MetaTile[] = [];
		tiles.push(action.enabled
			? { icon: 'mdiCheckCircle', label: t('commandTracker.enabled'), tone: 'mint' }
			: { icon: 'mdiPauseCircleOutline', label: t('commandTracker.disabled'), tone: 'default' });
		tiles.push({
			icon: 'mdiServer',
			label: getProviderName(action.provider_id),
			tone: 'lavender',
		});
		tiles.push({
			icon: 'mdiTagOutline',
			label: action.action_type,
			tone: 'sky',
			mono: true,
		});
		tiles.push({
			icon: action.schedule_type === 'cron' ? 'mdiClockOutline' : 'mdiTimerOutline',
			label: formatSchedule(action),
			tone: 'orchid',
			mono: true,
		});
		tiles.push({
			icon: 'mdiFormatListBulleted',
			value: String(action.rules?.length || 0),
			label: t('actions.rules'),
			tone: (action.rules?.length || 0) > 0 ? 'sky' : 'default',
		});
		if (action.last_run_status) {
			tiles.push({
				icon: 'mdiHistory',
				label: action.last_run_status,
				tone: statusTone(action.last_run_status),
			});
		}
		return tiles;
	}
</script>

<PageHeader
	title={t('actions.title')}
	emphasis={t('actions.titleEmphasis')}
	description={t('actions.description')}
	crumb={t('crumbs.routingAutomation')}
	count={actions.length}
	countLabel={t('actions.countLabel')}
	pills={headerPills}
>
	<Button size="sm" onclick={() => { showForm ? (showForm = false, editing = null) : openNew(); }}>
		{showForm ? t('common.cancel') : t('actions.addAction')}
	</Button>
</PageHeader>

{#if !loaded}
	<Loading />
{:else}

{#if loadError}
	<Card class="mb-6">
		<div class="flex items-center gap-2 text-sm" style="color: var(--color-error-fg);">
			<MdiIcon name="mdiAlertCircle" size={18} />
			{loadError}
		</div>
	</Card>
{/if}

{#if showForm}
	<div in:slide={{ duration: 200 }}>
	<Card class="mb-6">
		{#if error}<ErrorBanner message={error} />{/if}
		<form onsubmit={save} class="space-y-3">
			<div>
				<div class="block text-sm font-medium mb-1">{t('actions.provider')}</div>
				<EntitySelect items={providerItems} bind:value={form.provider_id}
					placeholder={t('actions.selectProvider')} disabled={!!editing} />
			</div>

			{#if actionTypes.length > 0}
			<div>
				<div class="block text-sm font-medium mb-1">{t('actions.actionType')}</div>
				{#if !editing}
					<div class="space-y-1">
						{#each actionTypes as at}
							<label class="flex items-center gap-2 p-2 rounded border cursor-pointer
								{form.action_type === at.key ? 'border-[var(--color-primary)] bg-[var(--color-primary)]/5' : 'border-[var(--color-border)]'}">
								<input type="radio" name="action_type" value={at.key} bind:group={form.action_type} class="accent-[var(--color-primary)]" />
								<div>
									<span class="text-sm font-medium">{at.name}</span>
									<p class="text-xs text-[var(--color-muted-foreground)]">{at.description}</p>
								</div>
							</label>
						{/each}
					</div>
				{:else}
					<p class="text-sm text-[var(--color-muted-foreground)]">{form.action_type}</p>
				{/if}
			</div>
			{/if}

			<div>
				<label for="act-name" class="block text-sm font-medium mb-1">{t('actions.name')}</label>
				<div class="flex gap-2">
					<IconPicker value={form.icon} onselect={(v: string) => form.icon = v} />
					<input id="act-name" bind:value={form.name} oninput={() => nameManuallyEdited = true} required
						class="flex-1 px-3 py-2 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]" />
				</div>
			</div>

			<div>
				<div class="block text-sm font-medium mb-1">{t('actions.schedule')}</div>
				<div class="flex gap-2 items-center mb-2">
					<label class="flex items-center gap-1 text-sm">
						<input type="radio" name="schedule_type" value="interval" bind:group={form.schedule_type} class="accent-[var(--color-primary)]" />
						{t('actions.interval')}
					</label>
					<label class="flex items-center gap-1 text-sm">
						<input type="radio" name="schedule_type" value="cron" bind:group={form.schedule_type} class="accent-[var(--color-primary)]" />
						{t('actions.cronMode')}
					</label>
				</div>
				{#if form.schedule_type === 'interval'}
					<div class="flex items-center gap-2">
						<input type="number" bind:value={form.schedule_interval} min="60" step="60"
							class="w-28 px-3 py-2 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]" />
						<span class="text-sm text-[var(--color-muted-foreground)]">{t('actions.seconds')}</span>
					</div>
				{:else}
					<input bind:value={form.schedule_cron} placeholder="0 3 * * *"
						class="w-full px-3 py-2 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)] font-mono" />
					<p class="text-xs text-[var(--color-muted-foreground)] mt-1">{t('actions.cronHint')}</p>
				{/if}
			</div>

			<div class="flex items-center gap-2">
				<input type="checkbox" id="act-enabled" bind:checked={form.enabled} class="accent-[var(--color-primary)]" />
				<label for="act-enabled" class="text-sm">{t('actions.enabled')}</label>
			</div>

			<Button type="submit" disabled={submitting}>
				{submitting ? t('common.loading') : (editing ? t('common.save') : t('actions.addAction'))}
			</Button>
		</form>

		{#if editing}
			<hr class="my-4 border-[var(--color-border)]" />
			<RuleEditor actionId={editing} actionType={form.action_type} providerId={form.provider_id} />
		{/if}
	</Card>
	</div>
{/if}

{#if !showForm && allActions.length > 0}
<div class="flex items-center gap-2 mb-3">
	<input type="text" bind:value={filterText} placeholder={t('common.filterByName')}
		class="flex-1 px-3 py-1.5 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]" />
</div>
{/if}

{#if allActions.length === 0 && !showForm}
	<Card>
		<EmptyState icon="mdiPlayCircleOutline" message={t('actions.noActions')} />
	</Card>
{:else if actions.length === 0 && !showForm}
	<Card>
		<EmptyState icon="mdiFilterOff" message={t('common.noFilterResults')} />
	</Card>
{:else if !showForm}
	<div class="list-stack stagger-children">
		{#each actions as action}
			<Card hover entityId={action.id}>
				<div class="list-row">
					<div class="list-row__identity">
						<div class="flex items-center gap-3 min-w-0">
							<div class="w-2.5 h-2.5 rounded-full flex-shrink-0"
								style="background: {action.enabled ? '#059669' : 'var(--color-muted-foreground)'}"></div>
							<span style="color: var(--color-primary);" class="shrink-0"><MdiIcon name={action.icon || 'mdiPlayCircleOutline'} size={20} /></span>
							<div class="min-w-0">
								<div class="flex items-center gap-2 min-w-0">
									<p class="font-medium truncate">{action.name}</p>
									<span class="text-xs px-1.5 py-0.5 rounded bg-[var(--color-muted)] text-[var(--color-muted-foreground)] shrink-0">{action.action_type}</span>
								</div>
								<div class="flex items-center gap-3 text-xs text-[var(--color-muted-foreground)] list-row__secondary">
									<CrossLink href="/providers" icon={providerDefaultIcon(getProvider(action.provider_id) || {})} label={getProviderName(action.provider_id)} entityId={action.provider_id} />
									<span>{formatSchedule(action)}</span>
									<span>{action.rules?.length || 0} {t('actions.rules')}</span>
									{#if action.last_run_status}
										<span style="color: {statusColor(action.last_run_status)}">
											{action.last_run_status}
										</span>
									{/if}
								</div>
							</div>
						</div>
					</div>
					<MetaStrip tiles={actionTiles(action)} />
					<div class="list-row__actions">
						<IconButton icon="mdiPlay" title={t('actions.execute')}
							onclick={() => executeAction(action.id)}
							disabled={executing[action.id]} />
						<IconButton icon="mdiEyeOutline" title={t('actions.dryRun')}
							onclick={() => executeAction(action.id, true)}
							disabled={executing[action.id]} />
						<IconButton icon="mdiHistory" title={t('actions.history')}
							onclick={() => historyActionId = historyActionId === action.id ? null : action.id} />
						<IconButton icon="mdiPencil" title={t('common.edit')} onclick={() => edit(action)} />
						<IconButton icon="mdiDelete" title={t('common.delete')} onclick={() => startDelete(action)} variant="danger" />
					</div>
				</div>
				{#if historyActionId === action.id}
					<div class="mt-3 pt-3 border-t border-[var(--color-border)]" in:slide={{ duration: 200 }}>
						<ExecutionHistory actionId={action.id} />
					</div>
				{/if}
			</Card>
		{/each}
	</div>
{/if}

{/if}

<ConfirmModal open={!!confirmDelete} message={t('actions.confirmDelete')}
	onconfirm={doDelete} oncancel={() => confirmDelete = null} />
