import { fail, redirect } from '@sveltejs/kit';
import type { Actions, PageServerLoad } from './$types';
import { createMemberRecord, cleanupAuthUser, sendWelcomeEmail } from '$lib/server/registration';
import { checkRateLimit } from '$lib/server/rate-limit';

export const load: PageServerLoad = async ({ locals, url }) => {
	const { session } = await locals.safeGetSession();

	// If already logged in, check if onboarding is completed
	if (session) {
		// Get member profile to check onboarding status
		const { data: member } = await locals.supabase
			.from('members')
			.select('onboarding_completed_at')
			.eq('id', session.user.id)
			.single();

		// Only redirect to dashboard if onboarding is completed
		if (member?.onboarding_completed_at) {
			throw redirect(303, '/dashboard');
		}
		// Otherwise, let them continue the onboarding wizard
	}

	// Get payment settings for the payment step
	const { data: settings } = await locals.supabase
		.from('app_settings')
		.select('setting_key, setting_value')
		.eq('category', 'dues');

	const paymentSettings: Record<string, string> = {};
	if (settings) {
		for (const s of settings) {
			let value = s.setting_value;
			if (typeof value === 'string') {
				value = value.replace(/^"|"$/g, '');
			}
			paymentSettings[s.setting_key.replace('payment_', '')] = value as string;
		}
	}

	// Get default membership type for dues amount
	const { data: defaultType } = await locals.supabase
		.from('membership_types')
		.select('annual_dues')
		.eq('is_default', true)
		.single();

	// If logged in but not completed onboarding, get member data
	let member = null;
	if (session) {
		const { data } = await locals.supabase
			.from('members')
			.select('id, first_name, email, member_id')
			.eq('id', session.user.id)
			.single();
		member = data;
	}

	return {
		paymentSettings,
		duesAmount: defaultType?.annual_dues || 150,
		session: session || null,
		member
	};
};

export const actions: Actions = {
	createAccount: async ({ request, locals, url }) => {
		const formData = await request.formData();

		// Extract form fields
		const firstName = formData.get('first_name') as string;
		const lastName = formData.get('last_name') as string;
		const email = formData.get('email') as string;
		const phone = formData.get('phone') as string;
		const dateOfBirth = formData.get('date_of_birth') as string;
		const address = formData.get('address') as string;
		const nationalityString = formData.get('nationality') as string;
		const password = formData.get('password') as string;
		const confirmPassword = formData.get('confirm_password') as string;
		const terms = formData.get('terms');

		// Validation
		if (!firstName || firstName.length < 2) {
			return fail(400, { error: 'First name must be at least 2 characters', step: 2 });
		}

		if (!lastName || lastName.length < 2) {
			return fail(400, { error: 'Last name must be at least 2 characters', step: 2 });
		}

		if (!email || !email.includes('@')) {
			return fail(400, { error: 'Please enter a valid email address', step: 2 });
		}

		if (!phone) {
			return fail(400, { error: 'Phone number is required', step: 2 });
		}

		if (!dateOfBirth) {
			return fail(400, { error: 'Date of birth is required', step: 2 });
		} else {
			// Check if 18+
			const birthDate = new Date(dateOfBirth);
			const today = new Date();
			const age = today.getFullYear() - birthDate.getFullYear();
			const monthDiff = today.getMonth() - birthDate.getMonth();
			const dayDiff = today.getDate() - birthDate.getDate();
			const actualAge = monthDiff < 0 || (monthDiff === 0 && dayDiff < 0) ? age - 1 : age;

			if (actualAge < 18) {
				return fail(400, { error: 'You must be at least 18 years old to join', step: 2 });
			}
		}

		if (!address || address.length < 10) {
			return fail(400, { error: 'Please enter a complete address', step: 2 });
		}

		const nationality = nationalityString ? nationalityString.split(',').filter(Boolean) : [];
		if (nationality.length === 0) {
			return fail(400, { error: 'Please select at least one nationality', step: 2 });
		}

		if (!password || password.length < 8) {
			return fail(400, { error: 'Password must be at least 8 characters', step: 2 });
		}

		if (password !== confirmPassword) {
			return fail(400, { error: 'Passwords do not match', step: 2 });
		}

		if (!terms) {
			return fail(400, { error: 'You must accept the terms and conditions', step: 2 });
		}

		// Rate limit signup attempts by email
		const rateLimitKey = `signup:${email}`;
		const rateCheck = checkRateLimit(rateLimitKey, 3, 15 * 60 * 1000); // 3 attempts per 15 min
		if (!rateCheck.allowed) {
			const retryMinutes = Math.ceil((rateCheck.retryAfterMs || 0) / 60000);
			return fail(429, {
				error: `Too many signup attempts. Please try again in ${retryMinutes} minute${retryMinutes !== 1 ? 's' : ''}.`,
				step: 2
			});
		}

		// Create Supabase auth user
		const { data: authData, error: authError } = await locals.supabase.auth.signUp({
			email,
			password,
			options: {
				emailRedirectTo: `${url.origin}/join?verified=true`,
				data: {
					first_name: firstName,
					last_name: lastName
				}
			}
		});

		if (authError) {
			if (authError.message.includes('already registered')) {
				return fail(400, {
					error: 'An account with this email already exists. Try signing in instead.',
					step: 2
				});
			}
			return fail(400, { error: authError.message, step: 2 });
		}

		if (!authData.user) {
			return fail(500, { error: 'Failed to create account. Please try again.', step: 2 });
		}

		// Create member profile using shared helper
		const memberResult = await createMemberRecord(
			{
				userId: authData.user.id,
				email,
				firstName,
				lastName,
				phone,
				dateOfBirth,
				address,
				nationality
			},
			locals.supabase,
			{ statusName: 'pending', generateMemberId: true }
		);

		if (!memberResult.success) {
			await cleanupAuthUser(authData.user.id);
			return fail(500, {
				error: memberResult.error || 'Failed to create member profile.',
				step: 2
			});
		}

		const memberId = memberResult.memberId;

		// Sign in the user so they can continue the wizard
		const { error: signInError } = await locals.supabase.auth.signInWithPassword({
			email,
			password
		});

		if (signInError) {
			console.error('Failed to sign in after account creation:', signInError);
			// Continue anyway - they can verify email and sign in later
		}

		return {
			success: true,
			step: 2,
			memberId,
			email
		};
	},

	uploadPhoto: async ({ request, locals }) => {
		const { session } = await locals.safeGetSession();
		if (!session) {
			return fail(401, { error: 'Not authenticated', step: 3 });
		}

		const formData = await request.formData();
		const photoFile = formData.get('photo') as File | null;

		// Photo is optional during onboarding - allow skipping
		if (!photoFile || photoFile.size === 0) {
			return { success: true, step: 3 };
		}

		// Use the shared avatar upload handler (admin mode to bypass RLS)
		const { handleAvatarUpload } = await import('$lib/server/member-profile');
		const result = await handleAvatarUpload(
			{ id: session.user.id },
			photoFile,
			{ useAdmin: true }
		);

		if (!result.success) {
			return fail(400, { error: result.error || 'Failed to upload photo', step: 3 });
		}

		return { success: true, step: 3 };
	},

	complete: async ({ locals }) => {
		const { session } = await locals.safeGetSession();
		if (!session) {
			return fail(401, { error: 'Not authenticated', step: 6 });
		}

		// Set payment deadline (30 days from now)
		const paymentDeadline = new Date();
		paymentDeadline.setDate(paymentDeadline.getDate() + 30);

		// Update member with onboarding completion
		const { error: updateError } = await locals.supabase
			.from('members')
			.update({
				payment_deadline: paymentDeadline.toISOString(),
				onboarding_completed_at: new Date().toISOString()
			})
			.eq('id', session.user.id);

		if (updateError) {
			console.error('Failed to update member:', updateError);
			return fail(500, { error: 'Failed to complete onboarding', step: 6 });
		}

		// Get member data for email
		const { data: member } = await locals.supabase
			.from('members')
			.select('first_name, member_id, email')
			.eq('id', session.user.id)
			.single();

		// Get payment settings
		const { data: settings } = await locals.supabase
			.from('app_settings')
			.select('setting_key, setting_value')
			.eq('category', 'dues');

		const paymentSettings: Record<string, string> = {};
		if (settings) {
			for (const s of settings) {
				let value = s.setting_value;
				if (typeof value === 'string') {
					value = value.replace(/^"|"$/g, '');
				}
				paymentSettings[s.setting_key.replace('payment_', '')] = value as string;
			}
		}

		// Get default membership dues amount
		const { data: defaultType } = await locals.supabase
			.from('membership_types')
			.select('annual_dues')
			.eq('is_default', true)
			.single();

		// Send welcome email with payment instructions
		if (member) {
			await sendWelcomeEmail(
				{
					id: session.user.id,
					first_name: member.first_name,
					email: member.email,
					member_id: member.member_id
				},
				paymentSettings,
				defaultType?.annual_dues || 150,
				paymentDeadline
			);
			// Errors are logged internally; not critical to block on failure
		}

		return {
			success: true,
			step: 6
		};
	}
};
