<script lang="ts">
	import { Button } from '$lib/components/ui/button/index.js';
	import { Input } from '$lib/components/ui/input/index.js';
	import { EmailInput } from '$lib/components/ui/email-input/index.js';
	import { PhoneInput } from '$lib/components/ui/phone-input/index.js';
	import { Label } from '$lib/components/ui/label/index.js';
	import { Separator } from '$lib/components/ui/separator/index.js';
	import { Checkbox } from '$lib/components/ui/checkbox/index.js';
	import RequiredLabel from '$lib/components/layout/RequiredLabel.svelte';
	import { isValidUKPhone, toE164UK } from '$lib/utils/phone';
	import { SvelteDate } from 'svelte/reactivity';

	// zxcvbn-ts imports
	import { zxcvbn, zxcvbnOptions } from '@zxcvbn-ts/core';
	import * as languageCommon from '@zxcvbn-ts/language-common';
	import * as languageEn from '@zxcvbn-ts/language-en';
	import { toast } from 'svelte-sonner';
	import { sanitizeText } from '$lib/utils/toast-safe';

	// set up options so that feedback, dictionary etc. are included
	zxcvbnOptions.setOptions({
		translations: languageEn.translations,
		graphs: languageCommon.adjacencyGraphs,
		dictionary: {
			...languageCommon.dictionary,
			...languageEn.dictionary
		}
	});

	let isLogin = $state(true);
	let agreedToPolicy = $state(false);

	let formData = $state({
		email: '',
		password: '',
		firstName: '',
		lastName: '',
		confirmPassword: '',
		phone: '',
		dateOfBirth: '',
		referralCode: ''
	});

	// Validation state
	let validationErrors = $state({
		email: '',
		phone: '',
		dateOfBirth: ''
	});

	function toggleMode() {
		isLogin = !isLogin;
		agreedToPolicy = false;
		formData = {
			email: '',
			password: '',
			firstName: '',
			lastName: '',
			confirmPassword: '',
			phone: '',
			dateOfBirth: '',
			referralCode: ''
		};
		validationErrors = {
			email: '',
			phone: '',
			dateOfBirth: ''
		};
	}

	function validatePhone(phone: string): boolean {
		const valid = isValidUKPhone(phone);
		validationErrors.phone = valid ? '' : 'Please enter a valid UK phone number';
		return valid;
	}

	// Age validation (must be 16+)
	function validateAge(dateStr: string): boolean {
		if (!dateStr) {
			validationErrors.dateOfBirth = '';
			return true;
		}

		const dob = new SvelteDate(dateStr);
		const today = new SvelteDate();
		const sixteenYearsAgo = new SvelteDate(
			today.getFullYear() - 16,
			today.getMonth(),
			today.getDate()
		);

		const isValid = dob <= sixteenYearsAgo;
		validationErrors.dateOfBirth = isValid
			? ''
			: "You must be at least 16 years old to register, but you can call for an appointment by clicking 'Contact' at the top of the page.";
		return isValid;
	}

	/**
	 * Formats referral code input into 3 blocks of 4 characters (xxxx-xxxx-xxxx).
	 * Handles paste, backspace, and partial inputs gracefully.
	 */
	function handleReferralInput(e: Event) {
		const target = e.target as HTMLInputElement;

		// 1. Clean the input: keep only alphanumeric characters
		let raw = target.value.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();

		// 2. Limit to 12 characters
		if (raw.length > 12) {
			raw = raw.slice(0, 12);
		}

		// 3. Reconstruct with dashes
		let formatted = '';
		if (raw.length > 0) {
			formatted += raw.slice(0, 4);
		}
		if (raw.length > 4) {
			formatted += '-' + raw.slice(4, 8);
		}
		if (raw.length > 8) {
			formatted += '-' + raw.slice(8, 12);
		}

		// 4. Update state
		formData.referralCode = formatted;
	}

	// Normalize data before sending
	function normalizeFormData() {
		return {
			firstName: formData.firstName.trim(),
			lastName: formData.lastName.trim(),
			email: formData.email.trim().toLowerCase(),
			password: formData.password,
			phone: toE164UK(formData.phone) ?? formData.phone,
			dateOfBirth: formData.dateOfBirth.trim(),
			// Strip dashes to send raw 12 characters
			referralCode: formData.referralCode.replace(/-/g, '').trim() || undefined,
			agreedToPolicy: agreedToPolicy
		};
	}

	async function handleSubmit() {
		if (isLogin) {
			// Login flow with loading toast
			const loadingToast = toast.loading('Signing in...');

			try {
				const response = await fetch('/api/login', {
					method: 'POST',
					headers: { 'Content-Type': 'application/json' },
					body: JSON.stringify({
						email: formData.email.trim().toLowerCase(),
						password: formData.password
					})
				});

				if (response.ok) {
					const data = await response.json();
					localStorage.setItem('authToken', data.token);

					// Decode token to check role for redirect
					let redirectTo = '/';
					try {
						const payload = JSON.parse(atob(data.token.split('.')[1]));
						if (payload.role === 'admin') {
							redirectTo = '/today';
						}
					} catch {
						// Token decode failure is non-fatal; default redirectTo = '/' is used
					}
					toast.success('Successfully logged in!', { id: loadingToast });
					window.location.href = redirectTo;
				} else if (response.status === 409) {
					toast.error('Login already in progress. Please wait.', { id: loadingToast });
				} else if (response.status === 401) {
					toast.error('Invalid email or password.', { id: loadingToast });
				} else {
					const text = await response.text();
					toast.error('Error: ' + sanitizeText(text), { id: loadingToast });
				}
			} catch (err) {
				console.error(err);
				toast.error('Network error, please try again later.', { id: loadingToast });
			}
			return;
		}

		// Validate before submitting
		const isEmailValid = !validationErrors.email && formData.email.trim().length > 0;
		const isPhoneValid = validatePhone(formData.phone);
		const isAgeValid = validateAge(formData.dateOfBirth);

		if (!isEmailValid || !isPhoneValid || !isAgeValid) {
			toast.error('Please fix the validation errors before submitting.');
			return;
		}

		// Registration flow with loading toast
		const loadingToast = toast.loading('Creating your account...');

		try {
			const response = await fetch('/api/register', {
				method: 'POST',
				headers: { 'Content-Type': 'application/json' },
				body: JSON.stringify(normalizeFormData())
			});

			if (response.ok) {
				toast.success('Account created successfully!', { id: loadingToast });
				toggleMode();
			} else {
				const text = await response.text();
				toast.error('Error: ' + sanitizeText(text), { id: loadingToast });
			}
		} catch (err) {
			console.error(err);
			toast.error('Network error, please try again later.', { id: loadingToast });
		}
	}

	function handleSocialLogin(provider: string) {
		toast.info(`${provider} login coming soon`);
	}

	// when password changes, re-compute strength
	const passwordStrength = $derived(
		formData.password
			? (() => {
					const result = zxcvbn(formData.password);
					// Add minimum length check (6 chars) to the score feedback
					if (formData.password.length < 6) {
						return {
							...result,
							score: Math.min(result.score, 0), // Force weak for too short
							feedback: {
								warning: 'Password must be at least 6 characters',
								suggestions: ['Add more characters to meet the minimum length requirement']
							}
						};
					}
					return result;
				})()
			: null
	);

	// form completion check
	const isFormComplete = $derived(
		isLogin ||
			(formData.firstName.trim() &&
				formData.lastName.trim() &&
				formData.phone &&
				formData.dateOfBirth &&
				formData.email &&
				formData.password &&
				formData.confirmPassword &&
				formData.password === formData.confirmPassword &&
				passwordStrength &&
				formData.password.length >= 6 &&
				passwordStrength.score >= 2 &&
				agreedToPolicy &&
				!validationErrors.email &&
				!validationErrors.phone &&
				!validationErrors.dateOfBirth)
	);
</script>

<svelte:head>
	<script>
		(function () {
			// Pre-hydration auth guard: reads localStorage directly because the Svelte
			// authStore hasn't initialized yet at this point (async+$state). This runs
			// synchronously in <svelte:head> before any rendering, preventing a flash
			// of protected content. The authStore handles post-hydration auth.
			try {
				var token = localStorage.getItem('authToken');
				if (token) {
					var payload = JSON.parse(atob(token.split('.')[1]));
					if (payload.exp * 1000 > Date.now()) {
						var path = payload.role === 'admin' ? '/today' : '/';
						window.location.replace(path);
					}
				}
			} catch (e) {}
		})();
	</script>
</svelte:head>

<div class="mx-auto flex w-full justify-center p-4 pt-2">
	<div class="w-full max-w-md space-y-6">
		<!-- Header -->
		<div class="space-y-2 text-center">
			<h1 class="font-['Playfair_Display'] text-4xl font-bold">
				{isLogin ? 'Welcome back' : 'Create account'}
			</h1>
			<p class="text-muted-foreground">
				{isLogin
					? 'Sign in to your account to continue'
					: 'Choose an option below to create your account'}
			</p>
		</div>

		<!-- Social Login Buttons -->
		<div class="space-y-3">
			<Button variant="outline" onclick={() => handleSocialLogin('Google')} class="w-full">
				<svg class="mr-2" style="width: 1rem; height: 1rem;" viewBox="0 0 24 24">
					<path
						fill="currentColor"
						d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"
					/>
					<path
						fill="currentColor"
						d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
					/>
					<path
						fill="currentColor"
						d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
					/>
					<path
						fill="currentColor"
						d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
					/>
				</svg>
				Continue with Google
			</Button>

			<Button variant="outline" onclick={() => handleSocialLogin('Microsoft')} class="w-full">
				<svg
					class="mr-2"
					style="width: 1rem; height: 1rem;"
					fill="currentColor"
					viewBox="0 0 24 24"
				>
					<path
						d="M11.4 24H0V12.6h11.4V24zM24 24H12.6V12.6H24V24zM11.4 11.4H0V0h11.4v11.4zM24 11.4H12.6V0H24v11.4z"
					/>
				</svg>
				Continue with Microsoft
			</Button>

			<Button variant="outline" onclick={() => handleSocialLogin('Facebook')} class="w-full">
				<svg
					class="mr-2"
					style="width: 1rem; height: 1rem;"
					fill="currentColor"
					viewBox="0 0 24 24"
				>
					<path
						d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"
					/>
				</svg>
				Continue with Facebook
			</Button>
		</div>

		<div class="relative">
			<div class="absolute inset-0 flex items-center">
				<Separator class="w-full" />
			</div>
			<div class="relative flex justify-center text-xs uppercase">
				<span class="bg-background px-2 text-muted-foreground">or continue with email</span>
			</div>
		</div>

		<!-- Email/Password Form -->
		<form
			onsubmit={(e) => {
				e.preventDefault();
				handleSubmit();
			}}
			class="space-y-6"
		>
			{#if !isLogin}
				<!-- SECTION 1: LOGIN DETAILS -->
				<div class="space-y-4">
					<h3 class="text-lg font-semibold">What we need to log you in</h3>

					<div class="space-y-2">
						<RequiredLabel forId="email" text="Email" />
						<EmailInput
							id="email"
							bind:value={formData.email}
							bind:error={validationErrors.email}
							placeholder="john@example.com"
							required
						/>
					</div>

					<div class="space-y-2">
						<RequiredLabel forId="password" text="Password" />
						<Input
							id="password"
							type="password"
							placeholder="Enter your password"
							maxlength={72}
							bind:value={formData.password}
							required
						/>

						{#if passwordStrength}
							<!-- Strength meter bar -->
							<div class="mt-1">
								<div class="h-2 overflow-hidden rounded bg-gray-200">
									<div
										class="h-2 transition-all"
										style="
											width: {(passwordStrength.score + 1) * 20}%;
											background-color: {passwordStrength.score < 2
											? 'var(--chart-1)'
											: passwordStrength.score === 2
												? 'orange'
												: passwordStrength.score === 3
													? 'var(--chart-2)'
													: 'var(--chart-2)'};
										"
									></div>
								</div>
								<p class="mt-1 text-xs">
									{passwordStrength.feedback.warning
										? passwordStrength.feedback.warning
										: `Strength: ${['Very weak', 'Weak', 'Fair', 'Strong', 'Very strong'][passwordStrength.score]}`}
								</p>
								{#if passwordStrength.feedback.suggestions.length > 0}
									<ul class="mt-1 ml-4 list-disc text-xs text-muted-foreground">
										{#each passwordStrength.feedback.suggestions as suggestion (suggestion)}
											<li>{suggestion}</li>
										{/each}
									</ul>
								{/if}
							</div>
						{/if}
					</div>

					<div class="space-y-2">
						<RequiredLabel forId="confirmPassword" text="Confirm Password" />
						<Input
							id="confirmPassword"
							type="password"
							placeholder="Confirm your password"
							bind:value={formData.confirmPassword}
							required
						/>
						{#if formData.confirmPassword && formData.password !== formData.confirmPassword}
							<p class="mt-1 text-sm text-red-500">Passwords do not match</p>
						{/if}
					</div>
				</div>

				<Separator class="w-full" />

				<!-- SECTION 2: CONTACT DETAILS -->
				<div class="space-y-4">
					<h3 class="text-lg font-semibold">What we need to know about you</h3>

					<div class="grid grid-cols-2 gap-4">
						<div class="space-y-2">
							<RequiredLabel forId="firstName" text="First Name" />
							<Input
								id="firstName"
								placeholder="John"
								maxlength={50}
								bind:value={formData.firstName}
								onblur={() => (formData.firstName = formData.firstName.trim())}
								required
							/>
						</div>
						<div class="space-y-2">
							<RequiredLabel forId="lastName" text="Last Name" />
							<Input
								id="lastName"
								placeholder="Doe"
								maxlength={50}
								bind:value={formData.lastName}
								onblur={() => (formData.lastName = formData.lastName.trim())}
								required
							/>
						</div>
					</div>

					<div class="space-y-2">
						<RequiredLabel forId="phone" text="Phone Number" />
						<PhoneInput
							id="phone"
							bind:value={formData.phone}
							bind:error={validationErrors.phone}
							placeholder="07123 456789 or +44 7123 456789"
							_required
						/>
					</div>

					<div class="space-y-2">
						<RequiredLabel forId="dateOfBirth" text="Date of Birth" />
						<Input
							id="dateOfBirth"
							type="date"
							bind:value={formData.dateOfBirth}
							onblur={() => validateAge(formData.dateOfBirth)}
							max={new SvelteDate(
								new SvelteDate().setFullYear(new SvelteDate().getFullYear() - 16)
							).toLocaleDateString('en-CA', { timeZone: 'Europe/London' })}
							required
						/>
						{#if validationErrors.dateOfBirth}
							<p class="text-sm text-red-500">{validationErrors.dateOfBirth}</p>
						{/if}
					</div>
				</div>

				<Separator class="w-full" />

				<!-- SECTION 3: REFERRAL -->
				<div class="space-y-4">
					<!-- <h3 class="text-lg font-semibold">Referral</h3> -->

					<div class="space-y-2">
						<Label for="referralCode">Referral Code (optional)</Label>
						<Input
							id="referralCode"
							placeholder="a2c4-e6g8-i0k2"
							maxlength={14}
							value={formData.referralCode}
							oninput={handleReferralInput}
						/>
						<p class="text-xs text-muted-foreground">
							Enter a 12-character referral code if you were referred by an existing customer
						</p>
					</div>
				</div>
			{:else}
				<!-- Login Fields (Simple inline layout) -->
				<div class="space-y-4">
					<div class="space-y-2">
						<RequiredLabel forId="email" text="Email" />
						<EmailInput
							id="email"
							bind:value={formData.email}
							bind:error={validationErrors.email}
							placeholder="john@example.com"
							required
						/>
					</div>

					<div class="space-y-2">
						<RequiredLabel forId="password" text="Password" />
						<Input
							id="password"
							type="password"
							placeholder="Enter your password"
							maxlength={72}
							bind:value={formData.password}
							required
						/>
					</div>
				</div>
			{/if}

			{#if !isLogin}
				<div class="flex items-center space-x-2">
					<Checkbox id="privacy" bind:checked={agreedToPolicy} class="mt-1" />
					<div class="text-sm leading-snug">
						<Label for="privacy">
							I agree to the
							<a
								href="/terms"
								class="font-semibold text-primary hover:underline"
								target="_blank"
								rel="noopener noreferrer external">Terms & Conditions</a
							>
							and
							<a
								href="/privacy"
								class="font-semibold text-primary hover:underline"
								target="_blank"
								rel="noopener noreferrer external">Privacy Policy</a
							>
						</Label>
					</div>
				</div>
			{/if}

			<Button type="submit" class="w-full" disabled={!isFormComplete}>
				{isLogin ? 'Sign In' : 'Create Account'}
			</Button>
		</form>

		<div class="text-center text-sm text-muted-foreground">
			{isLogin ? "Don't have an account?" : 'Already have an account?'}
			<Button variant="link" onclick={toggleMode} class="px-1 font-semibold text-primary">
				{isLogin ? 'Sign up' : 'Sign in'}
			</Button>
		</div>
	</div>
</div>
