<script module lang="ts">
	import { tv, type VariantProps } from "tailwind-variants";

	export const welcomeCard = tv({
		slots: {
			root: "overflow-hidden rounded-sm border border-border-default bg-background-default shadow-xs",
			header: "overflow-x-auto border-b border-border-default px-6 py-5",
			// grid so the outgoing and incoming panes share one cell and cross-fade in
			// place; overflow-hidden is what keeps the swipe inside the card
			body: "grid overflow-hidden p-6",
			pane: "col-start-1 row-start-1 min-w-0",
			footer: "flex items-center justify-between gap-4 border-t border-border-default px-6 py-4"
		}
	});

	export type WelcomeCardVariants = VariantProps<typeof welcomeCard>;
</script>

<script lang="ts">
	import type { Snippet } from "svelte";
	import { untrack } from "svelte";
	import { cubicIn, cubicOut } from "svelte/easing";
	import { prefersReducedMotion } from "svelte/motion";
	import { fly } from "svelte/transition";
	import ArrowLeft from "$icon/arrow-left";
	import ArrowRight from "$icon/arrow-right";
	import Check from "$icon/check";
	import Button from "$lib/components/ui/Button.svelte";
	import Steps from "./Steps.svelte";
	import { WELCOME_STEPS, LAST_STEP } from "./steps";

	interface Props {
		step: number;
		/** +1 when advancing, -1 when going back — decides which way the pane slides */
		direction: number;
		/** the appview greens Next once the step has something worth saving */
		nextReady?: boolean;
		onBack: () => void;
		onNext: () => void;
		/** rendered per step index, frozen at pane creation so the outgoing pane keeps its own content */
		children: Snippet<[number]>;
	}

	let { step, direction, nextReady = false, onBack, onNext, children }: Props = $props();

	const slot = welcomeCard();

	const DISTANCE = 40;
	const enter = $derived(
		prefersReducedMotion.current
			? { duration: 0 }
			: { x: direction * DISTANCE, duration: 240, delay: 90, easing: cubicOut }
	);
	const leave = $derived(
		prefersReducedMotion.current
			? { duration: 0 }
			: { x: direction * -DISTANCE, duration: 150, easing: cubicIn }
	);

	const isLast = $derived(step === LAST_STEP);
</script>

<div class={slot.root()}>
	<div class={slot.header()}>
		<Steps items={WELCOME_STEPS} current={step} />
	</div>

	<div class={slot.body()}>
		{#key step}
			<!-- untrack freezes the index at creation: `children` is a live snippet, so
			     without this the leaving pane would re-render with the new step's content
			     halfway through its own exit transition -->
			{@const frozen = untrack(() => step)}
			<div class={slot.pane()} in:fly={enter} out:fly={leave}>
				{@render children(frozen)}
			</div>
		{/key}
	</div>

	<div class={slot.footer()}>
		{#if step > 0}
			<Button variant="ghost" icon={ArrowLeft} onclick={onBack}>Back</Button>
		{:else}
			<span></span>
		{/if}

		<Button
			variant={nextReady ? "primary" : "default"}
			icon={isLast ? Check : ArrowRight}
			iconSide={isLast ? "left" : "right"}
			onclick={onNext}
		>
			{isLast ? "Finish" : "Next"}
		</Button>
	</div>
</div>
