<script module lang="ts">
	import { z } from 'zod';

	export const loginSchema = z.object({
		email: z.string().email(),
	});

	export const loginPasswordSchema = z.object({
		email: z.string().email(),
		password: z.string({ required_error: 'Password is required' }),
	})

	export const verifySchema = z.object({
		email: z.string().email(),
		code: z.string().length(6)
	});
</script>

<script lang="ts">
	import { Button } from '$lib/components/ui/button';
	import * as Card from '$lib/components/ui/card';
	import { Input } from '$lib/components/ui/input';
	import { superForm, defaults, setError } from 'sveltekit-superforms';
	import { zod } from 'sveltekit-superforms/adapters';
	import * as Form from '$lib/components/ui/form';
	import { createMutation, useQueryClient } from '@tanstack/svelte-query';
	import { goto } from '$app/navigation';
	import ChevronLeftIcon from 'lucide-svelte/icons/chevron-left';
	import { queryHandler } from '$lib/tanstack-query';
	import * as InputOTP from '$lib/components/ui/input-otp/index.js';

	const RESEND_VERIFICATION_CODE_COOLDOWN = 60;

	let queryClient = useQueryClient();
	let step = $state<'login' | 'request' | 'verify'>('request');
	let countdownTimer = $state(RESEND_VERIFICATION_CODE_COOLDOWN);
	let resendVerificationCodeOnCooldown = $derived(
		countdownTimer != RESEND_VERIFICATION_CODE_COOLDOWN
	);

	/* ----------------------------------- Api ---------------------------------- */
	const requestUsernamePasswordLoginMutation = createMutation({
		...queryHandler().iam.requestUsernamePasswordLogin(),
		onSuccess(_data, variables, _context) {
			step = 'verify';
			$verifyForm.email = variables.json.email;
			$verifyForm.
		}
	})

	const requestMutation = createMutation({
		...queryHandler().iam.requestLogin(),
		onSuccess(_data, variables, _context) {
			step = 'verify';
			$verifyForm.email = variables.json.email;
			startResendVerificationCodeTimer();
		},
		onError(error) {
			requestErrors.set({ email: [error.message] });
		}
	});

	const verifyMutation = createMutation({
		...queryHandler().iam.verifyLogin(),
		async onSuccess() {
			await queryClient.invalidateQueries();
			goto('/');
		},
		onError(error) {
			verifyErrors.set({ code: [error.message] });
		}
	});

	/* ------------------------------- Login Form ------------------------------- */
	const sf_login_username_password = superForm(defaults(zod(loginPasswordSchema)), {
		resetForm: false,
		SPA: true,
		validators: zod(loginPasswordSchema),
		async onUpdated(event) {
			if (!event.form.valid) return;
			await $requestUsernamePasswordLogin.mutateAsync({ json: event.form.data });
		}
	})

	const sf_login = superForm(defaults(zod(loginSchema)), {
		resetForm: false,
		SPA: true,
		validators: zod(loginSchema),
		async onUpdated(event) {
			if (!event.form.valid) return;

			await $requestMutation.mutateAsync({
				json: {
					email: event.form.data.email
				}
			});

			if ($requestMutation.error)
				return setError(event.form, 'email', $requestMutation.error.message);

			step = 'verify';
			$verifyForm.email = event.form.data.email;
		}
	});
	const { form: loginPasswordForm, enhance: loginPasswordEnhance, errors: loginPasswordErrors } = sf_login_username_password;

	const { form: loginForm, enhance: loginEnhance, errors: requestErrors } = sf_login;

	/* ------------------------------- Verify Form ------------------------------ */
	const sf_verify = superForm(defaults(zod(verifySchema)), {
		resetForm: false,
		SPA: true,
		validators: zod(verifySchema),
		async onUpdated(event) {
			if (!event.form.valid) return;
			await $verifyMutation.mutateAsync({ json: event.form.data });
		}
	});
	const { form: verifyForm, enhance: verifyEnhance, errors: verifyErrors } = sf_verify;

	/* -------------------------------- Functions ------------------------------- */
	function startResendVerificationCodeTimer() {
		countdownTimer = RESEND_VERIFICATION_CODE_COOLDOWN - 1;
		const interval = setInterval(() => {
			countdownTimer -= 1;
			if (countdownTimer <= 0) {
				countdownTimer = RESEND_VERIFICATION_CODE_COOLDOWN;
				clearInterval(interval);
			}
		}, 1000);
	}

	function resetAuthFlow() {
		step = 'request';
		sf_verify.reset();
		sf_login.reset();
	}

	async function resendVerificationCode() {
		startResendVerificationCodeTimer();
		await $requestMutation.mutateAsync({
			json: { email: $verifyForm.email }
		});
	}
</script>

{#if step === 'login'}
	{@render loginCard()}
{/if}
{#if step === 'request'}
	{@render requestsCard()}
{/if}
{#if step === 'verify'}
	{@render verifyCard()}
{/if}

{#snippet loginCard()}
	<Card.Root class="mx-auto w-full max-w-sm">
		<Card.Header>
			<Card.Title class="text-2xl">Login</Card.Title>
			<Card.Description>Enter your email below to login to your account</Card.Description>
		</Card.Header>
		<Card.Content>
			<form use:loginEnhance method="POST" class="grid gap-4">
				<Form.Field form={sf_login_username_password} name="email">
					<Form.Control>
						{#snippet children({ props })}
							<Form.Label>Email</Form.Label>
							<Input {...props} bind:value={$loginPasswordForm.email} />
						{/snippet}
					</Form.Control>
					<Form.Description />
					<Form.FieldErrors />
				</Form.Field>
				<Form.Field form={sf_login_username_password} name="password">
					<Form.Control>
						{#snippet children({ props })}
							<Form.Label>Password</Form.Label>
							<Input type="password" {...props} bind:value={$loginPasswordForm.password} />
						{/snippet}
					</Form.Control>
					<Form.Description />
					<Form.FieldErrors />
				</Form.Field>
				<Button type="submit" class="w-full">Continue with Email</Button>
			</form>
		</Card.Content>
	</Card.Root>
{/snippet}

{#snippet requestsCard()}
	<Card.Root class="mx-auto w-full max-w-sm">
		<Card.Header>
			<Card.Title class="text-2xl">Login</Card.Title>
			<Card.Description>Enter your email below to login to your account</Card.Description>
		</Card.Header>
		<Card.Content>
			<form use:loginEnhance method="POST" class="grid gap-4">
				<Form.Field form={sf_login} name="email">
					<Form.Control>
						{#snippet children({ props })}
							<Form.Label>Email</Form.Label>
							<Input {...props} bind:value={$loginForm.email} />
						{/snippet}
					</Form.Control>
					<Form.Description />
					<Form.FieldErrors />
				</Form.Field>
				<Button type="submit" class="w-full">Continue with Email</Button>
			</form>
		</Card.Content>
	</Card.Root>
{/snippet}

{#snippet verifyCard()}
	<Card.Root class="mx-auto w-full max-w-sm">
		<Card.Header>
			<Button onclick={resetAuthFlow} class="h-8 w-8" variant="secondary"
				><ChevronLeftIcon /></Button
			>
			<Card.Title class="text-2xl">Enter Code</Card.Title>
			<Card.Description
				>Please enter the 6 digit code we sent to {$verifyForm.email}</Card.Description
			>
		</Card.Header>
		<Card.Content>
			<form use:verifyEnhance method="POST" class="grid gap-4">
				<input value={$verifyForm.email} id="email" hidden />
				<Form.Field form={sf_verify} name="code">
					<Form.Control>
						{#snippet children({ props })}
							<InputOTP.Root maxlength={6} {...props} bind:value={$verifyForm.code}>
								{#snippet children({ cells })}
									<InputOTP.Group>
										{#each cells as cell}
											<InputOTP.Slot {cell} />
										{/each}
									</InputOTP.Group>
								{/snippet}
							</InputOTP.Root>
						{/snippet}
					</Form.Control>
					<Form.Description />
					<Form.FieldErrors />
				</Form.Field>
				<Button type="submit" class="w-full">Verify</Button>
			</form>
			<div class="mt-4 text-sm">
				{#if resendVerificationCodeOnCooldown}
					<p>Resend code in {countdownTimer}s</p>
				{:else}
					<Button onclick={resendVerificationCode} variant="ghost" size="sm">Resend Code</Button>
				{/if}
			</div>
		</Card.Content>
	</Card.Root>
{/snippet}
