import { fail, error } from '@sveltejs/kit';
import type { Actions, PageServerLoad } from './$types';
import { sendTemplatedEmail } from '$lib/server/email';

export const load: PageServerLoad = async ({ locals, params, parent }) => {
	const { member } = await parent();

	// Fetch the event
	const { data: event } = await locals.supabase
		.from('events_with_counts')
		.select('*')
		.eq('id', params.id)
		.single();

	if (!event) {
		throw error(404, 'Event not found');
	}

	// Check visibility permissions
	const visibleLevels = getVisibleLevels(member?.role);
	if (!visibleLevels.includes(event.visibility)) {
		throw error(403, 'You do not have permission to view this event');
	}

	// Fetch user's RSVP if they have one
	let rsvp = null;
	if (member) {
		const { data } = await locals.supabase
			.from('event_rsvps')
			.select('*')
			.eq('event_id', params.id)
			.eq('member_id', member.id)
			.single();
		rsvp = data;
	}

	return {
		event,
		rsvp
	};
};

export const actions: Actions = {
	rsvp: async ({ request, locals, params }) => {
		const { member } = await locals.safeGetSession();

		if (!member) {
			return fail(401, { error: 'You must be logged in to RSVP' });
		}

		const formData = await request.formData();
		const guestCount = parseInt(formData.get('guest_count') as string) || 0;

		// Fetch the event to check capacity and guest limits
		const { data: event } = await locals.supabase
			.from('events_with_counts')
			.select('*')
			.eq('id', params.id)
			.single();

		if (!event) {
			return fail(404, { error: 'Event not found' });
		}

		// Server-side guest count validation
		if (event.max_guests_per_member !== null && guestCount > event.max_guests_per_member) {
			return fail(400, {
				error: `Maximum ${event.max_guests_per_member} guest${event.max_guests_per_member === 1 ? '' : 's'} allowed per member`
			});
		}

		// Check if event is full
		const totalAttending = event.total_attendees + 1 + guestCount;
		const isFull = event.max_attendees && totalAttending > event.max_attendees;

		// Create RSVP
		const { error: rsvpError } = await locals.supabase.from('event_rsvps').insert({
			event_id: params.id,
			member_id: member.id,
			status: isFull ? 'waitlist' : 'confirmed',
			guest_count: guestCount,
			payment_status: event.is_paid ? 'pending' : 'not_required',
			payment_amount: event.is_paid ? event.member_price * (1 + guestCount) : null
		});

		if (rsvpError) {
			if (rsvpError.code === '23505') {
				return fail(400, { error: 'You have already RSVP\'d to this event' });
			}
			console.error('RSVP error:', rsvpError);
			return fail(500, { error: 'Failed to submit RSVP. Please try again.' });
		}

		return {
			success: isFull
				? 'You have been added to the waitlist. We will notify you if a spot opens up.'
				: 'RSVP submitted successfully!'
		};
	},

	updateRsvp: async ({ request, locals, params }) => {
		const { member } = await locals.safeGetSession();

		if (!member) {
			return fail(401, { error: 'You must be logged in' });
		}

		const formData = await request.formData();
		const newStatus = formData.get('status') as string;
		const guestCount = parseInt(formData.get('guest_count') as string) || 0;

		// Validate status
		const validStatuses = ['confirmed', 'declined', 'maybe'];
		if (!validStatuses.includes(newStatus)) {
			return fail(400, { error: 'Invalid RSVP status' });
		}

		// Fetch the event for validation
		const { data: event } = await locals.supabase
			.from('events_with_counts')
			.select('*')
			.eq('id', params.id)
			.single();

		if (!event) {
			return fail(404, { error: 'Event not found' });
		}

		// Get current RSVP
		const { data: currentRsvp } = await locals.supabase
			.from('event_rsvps')
			.select('*')
			.eq('event_id', params.id)
			.eq('member_id', member.id)
			.single();

		if (!currentRsvp) {
			return fail(404, { error: 'RSVP not found' });
		}

		// Validate guest count
		if (event.max_guests_per_member !== null && guestCount > event.max_guests_per_member) {
			return fail(400, {
				error: `Maximum ${event.max_guests_per_member} guest${event.max_guests_per_member === 1 ? '' : 's'} allowed`
			});
		}

		// If changing from waitlist/declined to confirmed, check capacity
		if (newStatus === 'confirmed' && currentRsvp.status !== 'confirmed') {
			const spotsNeeded = 1 + guestCount;
			const currentConfirmed = event.total_attendees;
			if (event.max_attendees && currentConfirmed + spotsNeeded > event.max_attendees) {
				return fail(400, { error: 'Event is at capacity. You will remain on the waitlist.' });
			}
		}

		// Update RSVP
		const { error: updateError } = await locals.supabase
			.from('event_rsvps')
			.update({
				status: newStatus,
				guest_count: guestCount,
				payment_amount: event.is_paid ? event.member_price * (1 + guestCount) : null,
				updated_at: new Date().toISOString()
			})
			.eq('event_id', params.id)
			.eq('member_id', member.id);

		if (updateError) {
			console.error('Update RSVP error:', updateError);
			return fail(500, { error: 'Failed to update RSVP. Please try again.' });
		}

		// If changing to declined from confirmed, try to promote someone from waitlist
		if (newStatus === 'declined' && currentRsvp.status === 'confirmed') {
			await promoteFromWaitlist(locals.supabase, params.id as string, event);
		}

		const statusMessages: Record<string, string> = {
			confirmed: 'Great! You\'re now confirmed for this event.',
			declined: 'You have declined this event.',
			maybe: 'Your tentative response has been recorded.'
		};

		return { success: statusMessages[newStatus] || 'RSVP updated successfully.' };
	},

	cancel: async ({ locals, params }) => {
		const { member } = await locals.safeGetSession();

		if (!member) {
			return fail(401, { error: 'You must be logged in' });
		}

		// Get current RSVP status before deleting
		const { data: currentRsvp } = await locals.supabase
			.from('event_rsvps')
			.select('status')
			.eq('event_id', params.id)
			.eq('member_id', member.id)
			.single();

		const { error: deleteError } = await locals.supabase
			.from('event_rsvps')
			.delete()
			.eq('event_id', params.id)
			.eq('member_id', member.id);

		if (deleteError) {
			console.error('Cancel RSVP error:', deleteError);
			return fail(500, { error: 'Failed to cancel RSVP. Please try again.' });
		}

		// If cancelling a confirmed RSVP, try to promote someone from waitlist
		if (currentRsvp?.status === 'confirmed') {
			// Fetch event for capacity check
			const { data: event } = await locals.supabase
				.from('events_with_counts')
				.select('*')
				.eq('id', params.id)
				.single();

			if (event) {
				await promoteFromWaitlist(locals.supabase, params.id as string, event);
			}
		}

		return { success: 'RSVP cancelled successfully.' };
	}
};

/**
 * Promote the oldest waitlisted member to confirmed status
 */
async function promoteFromWaitlist(
	supabase: typeof import('@supabase/supabase-js').SupabaseClient,
	eventId: string,
	event: { max_attendees: number | null; total_attendees: number; is_paid: boolean; member_price: number; title?: string; start_datetime?: string; location?: string }
) {
	// Check if there's room
	if (event.max_attendees && event.total_attendees >= event.max_attendees) {
		return; // Still full
	}

	// Get oldest waitlisted member with their info
	const { data: waitlisted } = await supabase
		.from('event_rsvps')
		.select('id, member_id, guest_count, member:members(first_name, last_name, email)')
		.eq('event_id', eventId)
		.eq('status', 'waitlist')
		.order('created_at', { ascending: true })
		.limit(1)
		.single();

	if (!waitlisted) {
		return; // No one on waitlist
	}

	// Check if promoting them (plus guests) would exceed capacity
	const spotsNeeded = 1 + (waitlisted.guest_count || 0);
	if (event.max_attendees && event.total_attendees + spotsNeeded > event.max_attendees) {
		return; // Not enough room for this person + guests
	}

	// Promote to confirmed
	await supabase
		.from('event_rsvps')
		.update({
			status: 'confirmed',
			updated_at: new Date().toISOString()
		})
		.eq('id', waitlisted.id);

	// Send email notification to promoted member
	const member = waitlisted.member as { first_name: string; last_name: string; email: string } | null;
	if (member?.email) {
		const eventDate = event.start_datetime
			? new Date(event.start_datetime).toLocaleDateString('en-US', {
					weekday: 'long',
					month: 'long',
					day: 'numeric',
					year: 'numeric'
				})
			: 'TBD';

		await sendTemplatedEmail(
			'waitlist_promotion',
			member.email,
			{
				first_name: member.first_name,
				event_title: event.title || 'Event',
				event_date: eventDate,
				event_location: event.location || 'TBD'
			},
			{
				recipientId: waitlisted.member_id,
				recipientName: `${member.first_name} ${member.last_name}`
			}
		);

		console.log(`Promoted member ${waitlisted.member_id} from waitlist for event ${eventId} and sent notification`);
	}
}

function getVisibleLevels(role: string | undefined): string[] {
	switch (role) {
		case 'admin':
			return ['public', 'members', 'board', 'admin'];
		case 'board':
			return ['public', 'members', 'board'];
		default:
			return ['public', 'members'];
	}
}
