<script lang="ts">
	import { authStore } from '$lib/stores/auth.svelte';
	import { SvelteDate } from 'svelte/reactivity';
	import { toast } from 'svelte-sonner';
	import * as Modal from '$lib/components/ui/dialog';
	import { Button } from '$lib/components/ui/button';
	import { Input } from '$lib/components/ui/input';
	import UserPaymentModal from '$lib/components/payments/UserPaymentModal.svelte';
	import EditRequestModal from '$lib/components/account/EditRequestModal.svelte';
	import type { Booking, BookingDiscount, Payment } from '$lib/types/booking';

	interface Props {
		open: boolean;
		bookingId: string;
	}

	let { open = $bindable(), bookingId }: Props = $props();

	let selectedBooking = $state<Booking | null>(null);
	let loading = $state(false);
	let hasPendingEditRequest = $state(false);

	let showEditModal = $state(false);
	let showCancelConfirm = $state(false);
	let cancelling = $state(false);

	// IMPORTANT: Use override_duration_minutes when present — services may have been
	// customised at booking time. Showing base values misleads users about what was booked.
	let totalDuration = $derived(
		selectedBooking?.services?.reduce(
			(sum, service) => sum + (service.override_duration_minutes ?? service.duration_minutes ?? 0),
			0
		) || 0
	);

	let isFutureBooking = $derived(
		selectedBooking ? new SvelteDate(selectedBooking.start_time) > new SvelteDate() : false
	);

	let hasPayments = $derived(
		selectedBooking && selectedBooking.payments && selectedBooking.payments.length > 0
	);

	let isCancellable = $derived(
		selectedBooking && isFutureBooking && ['pending', 'confirmed'].includes(selectedBooking.status)
	);

	let canEditBooking = $derived(isCancellable && !hasPayments);

	let totalPaid = $derived(
		selectedBooking?.payments
			?.filter((p) => p.status === 'completed')
			.reduce((sum, p) => sum + p.amount, 0) || 0
	);

	let depositOutstanding = $derived(
		selectedBooking?.deposit_required && !selectedBooking?.deposit_paid
	);

	let canPayEarly = $derived(
		selectedBooking &&
			!depositOutstanding &&
			totalPaid < selectedBooking.total_amount &&
			['confirmed', 'pending'].includes(selectedBooking.status)
	);

	let isCompleted = $derived(selectedBooking?.status === 'completed');

	let showPaymentModal = $state(false);

	let showTipModal = $state(false);
	let tipAmount = $state<number>(0);
	let selectedTipPreset = $state<number | null>(null);
	let customTipInput = $state('');
	let tipProcessing = $state(false);

	let canSaveCards = $derived(
		authStore.currentUser?.role === 'verified_email' || authStore.currentUser?.role === 'affiliate'
	);

	let tipPresets = $derived(
		selectedBooking
			? [
					{ pct: 10, amount: Math.round(selectedBooking.total_amount * 0.1 * 100) / 100 },
					{ pct: 15, amount: Math.round(selectedBooking.total_amount * 0.15 * 100) / 100 },
					{ pct: 20, amount: Math.round(selectedBooking.total_amount * 0.2 * 100) / 100 }
				]
			: []
	);

	function selectTipPreset(amount: number) {
		selectedTipPreset = amount;
		customTipInput = '';
		tipAmount = amount;
	}

	function handleCustomTip(e: Event) {
		const input = e.target as HTMLInputElement;
		const cleaned = input.value.replace(/[^0-9.]/g, '');
		const firstDot = cleaned.indexOf('.');
		let sanitized: string;
		if (firstDot !== -1) {
			const integerPart = cleaned.substring(0, firstDot);
			const decimalPart = cleaned.substring(firstDot + 1).replace(/\./g, '');
			sanitized = integerPart + '.' + decimalPart;
		} else {
			sanitized = cleaned;
		}
		if (/^\d+(\.\d{0,2})?$/.test(sanitized) || sanitized === '') {
			customTipInput = sanitized;
		}
		selectedTipPreset = null;
		tipAmount = parseFloat(customTipInput) || 0;
	}

	async function submitTip() {
		if (!selectedBooking) return;
		if (tipAmount <= 0) {
			toast.error('Please select a tip amount');
			return;
		}
		tipProcessing = true;
		try {
			const response = await fetch(`/api/bookings/${selectedBooking.id}/tip`, {
				method: 'POST',
				headers: {
					'Content-Type': 'application/json',
					Authorization: `Bearer ${authStore.currentToken}`
				},
				body: JSON.stringify({
					amount: Math.round(tipAmount * 100),
					card_token: 'placeholder'
				})
			});
			if (!response.ok) {
				const errorText = await response.text();
				throw new Error(errorText || 'Tip payment failed');
			}
			toast.success('Thank you for your tip!');
			showTipModal = false;
			fetchBookingDetails();
		} catch (err) {
			toast.error(err instanceof Error ? err.message : 'Tip payment failed');
		} finally {
			tipProcessing = false;
		}
	}

	function handlePaymentComplete() {
		toast.success('Payment completed');
		showPaymentModal = false;
		fetchBookingDetails();
	}

	async function fetchBookingDetails() {
		if (!bookingId) return;
		loading = true;
		try {
			const response = await fetch(`/api/bookings/${bookingId}`, {
				method: 'GET',
				headers: {
					'Content-Type': 'application/json',
					Authorization: `Bearer ${authStore.currentToken}`
				}
			});

			if (response.ok) {
				const data = await response.json();
				selectedBooking = data as Booking;

				const editResp = await fetch(`/api/bookings/${bookingId}/edit-request`, {
					headers: { Authorization: `Bearer ${authStore.currentToken}` }
				});
				hasPendingEditRequest = editResp.ok;
			} else {
				const text = await response.text();
				toast.error('Failed to load booking: ' + text);
				open = false;
			}
		} catch (err) {
			console.error('Error fetching booking:', err);
			toast.error('Network error');
			open = false;
		} finally {
			loading = false;
		}
	}

	$effect(() => {
		if (!open) {
			setTimeout(() => {
				selectedBooking = null;
				hasPendingEditRequest = false;
				showCancelConfirm = false;
				showEditModal = false;
			}, 200);
		} else if (bookingId && !selectedBooking) {
			fetchBookingDetails();
		}
	});

	async function cancelBooking() {
		if (!selectedBooking) return;
		cancelling = true;
		try {
			const body = hasPayments ? { reason: 'client_cancelled' } : undefined;
			const response = await fetch(`/api/bookings/${selectedBooking.id}`, {
				method: 'DELETE',
				headers: {
					'Content-Type': 'application/json',
					Authorization: `Bearer ${authStore.currentToken}`
				},
				body: body ? JSON.stringify(body) : undefined
			});

			if (response.ok) {
				toast.success('Booking cancelled');
				showCancelConfirm = false;
				open = false;
			} else {
				const text = await response.text();
				toast.error('Failed to cancel: ' + text);
			}
		} catch {
			toast.error('Network error');
		} finally {
			cancelling = false;
		}
	}

	function formatPaymentMethod(method: string): string {
		switch (method) {
			case 'in_person_card':
				return 'Card, In-person';
			case 'online_square':
				return 'Card, Online';
			case 'cash':
				return 'Cash';
			case 'giftcard':
				return 'Gift Card';
			case 'discount':
				return 'Discount';
			default:
				return method.replace(/_/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase());
		}
	}

	function getPaymentName(payment: Payment, index: number, payments: Payment[], discounts: BookingDiscount[] | undefined): string {
		if (payment.payment_method === 'online_square') return 'Online Card';
		if (payment.payment_method === 'in_person_card') return 'Card Machine';
		if (payment.payment_method === 'cash') return 'Cash';
		if (payment.payment_method === 'giftcard') return 'Gift Card';
		if (payment.payment_method === 'discount') {
			const discountPaymentsBefore = payments.slice(0, index).filter(p => p.payment_method === 'discount').length;
			const discountList = (discounts ?? []).filter(d => d.discount_amount > 0.01);
			if (discountList[discountPaymentsBefore]) {
				const d = discountList[discountPaymentsBefore];
				if (d.discount_source === 'loyalty') return 'Loyalty Stamp Card (10% Off)';
				if (d.campaign_name) return `${d.campaign_name}`;
				return 'Promo Campaign Discount';
			}
			return 'Discount';
		}
		return formatPaymentMethod(payment.payment_method);
	}
</script>

<Modal.Root bind:open>
	<Modal.Content
		class="!z-[60] max-h-[90vh] max-w-[calc(100%-2rem)] overflow-y-auto sm:max-w-md md:max-w-3xl"
	>
		<Modal.Header>
			<div class="flex items-center justify-between">
				<div>
					<Modal.Title class="text-lg font-semibold">Booking Details</Modal.Title>
					{#if selectedBooking}
						<div class="mt-1 text-sm text-gray-500">ID: {selectedBooking.id}</div>
					{/if}
				</div>

				{#if selectedBooking}
					{@const isPastBooking = new SvelteDate(selectedBooking.start_time) < new SvelteDate()}
					{@const isUnpaid = selectedBooking.amount_due > 0}
					{@const showChip = !isPastBooking || isUnpaid}
					{@const isConfirmedOrLater = ['confirmed', 'in_progress', 'completed'].includes(
						selectedBooking.status
					)}

					{#if showChip}
						<div class="flex items-center gap-2">
							<span
								class="inline-flex items-center rounded-full px-3 py-1 text-sm font-medium
								{isPastBooking
									? 'bg-red-100 text-red-800'
									: selectedBooking.status === 'confirmed' || selectedBooking.status === 'completed'
										? 'bg-emerald-100 text-emerald-800'
										: selectedBooking.status === 'pending'
											? 'bg-amber-100 text-amber-800'
											: 'bg-gray-100 text-gray-800'}"
							>
								{isPastBooking ? 'Unpaid' : selectedBooking.status.replace('_', ' ')}
							</span>

							{#if selectedBooking.deposit_required}
								{#if selectedBooking.status === 'pending'}
									<span
										class="inline-flex items-center rounded-full bg-blue-100 px-3 py-1 text-sm font-medium text-blue-800"
									>
										Will Require Deposit
									</span>
								{:else if isConfirmedOrLater}
									<span
										class="inline-flex items-center rounded-full px-3 py-1 text-sm font-medium
										{selectedBooking.deposit_paid ? 'bg-green-100 text-green-800' : 'bg-orange-100 text-orange-800'}"
									>
										{selectedBooking.deposit_paid ? 'Deposit Paid' : 'Deposit Due'}
									</span>
								{/if}
							{/if}
						</div>
					{/if}
				{/if}
			</div>
		</Modal.Header>

		{#if loading}
			<div class="flex items-center justify-center p-8 text-gray-500">Loading...</div>
		{:else if selectedBooking}
			<div class="space-y-6 px-4 pb-4">
				<div class="rounded-lg border border-gray-200 bg-gray-50 p-4">
					<h3 class="mb-3 text-sm font-semibold tracking-wide text-gray-600 uppercase">
						Appointment Details
					</h3>
					<div class="grid gap-3 md:grid-cols-2">
						<div>
							<div class="text-xs text-gray-500">Scheduled Date & Time</div>
							<div class="font-medium">
								{(() => {
									const date = new SvelteDate(selectedBooking.start_time);
									const dateStr = date.toLocaleDateString('en-US', {
										weekday: 'long',
										day: 'numeric',
										month: 'short'
									});
									const timeStr = date.toLocaleTimeString('en-US', {
										hour: 'numeric',
										minute: '2-digit',
										hour12: true
									});
									return `${dateStr} at ${timeStr}`;
								})()}
							</div>
						</div>
						<div>
							<div class="text-xs text-gray-500">Duration</div>
							<div class="font-medium">{totalDuration} minutes</div>
						</div>
						{#if selectedBooking.notes}
							<div class="md:col-span-2">
								<div class="text-xs text-gray-500">Notes</div>
								<div class="mt-1 rounded-md border border-gray-300 bg-white p-2 text-sm">
									{selectedBooking.notes}
								</div>
							</div>
						{/if}
					</div>
				</div>

				{#if selectedBooking.services && selectedBooking.services.length > 0}
					<div class="rounded-lg border border-gray-200 bg-gray-50 p-4">
						<h3 class="mb-3 text-sm font-semibold tracking-wide text-gray-600 uppercase">
							Services
						</h3>
						<div class="space-y-3">
							{#each selectedBooking.services as service, index (index)}
								<div class="rounded-md border border-gray-300 bg-white p-3">
									<div class="font-medium">{service.service_name || '—'}</div>
									{#if service.service_description}
										<div class="mt-1 text-sm text-gray-600">{service.service_description}</div>
									{/if}
									<div class="mt-2 flex items-center justify-between text-sm">
										<span class="text-gray-600"
											>{service.override_duration_minutes ?? service.duration_minutes} min</span
										>
										<span class="font-semibold"
											>£{(service.override_price ?? service.price ?? 0).toFixed(2)}</span
										>
									</div>
								</div>
							{/each}
						</div>
					</div>
				{/if}

				<div class="rounded-lg border border-gray-200 bg-gray-50 p-4">
					<h3 class="mb-3 text-sm font-semibold tracking-wide text-gray-600 uppercase">
						Financial Summary
					</h3>
					<div class="space-y-2">
						{#if ['confirmed', 'in_progress', 'completed'].includes(selectedBooking.status) && selectedBooking.deposit_required}
							<div class="flex items-center justify-between border-b border-gray-200 pb-2">
								<span class="text-sm text-gray-600">Deposit Required</span>
								<div class="text-right">
									<div class="font-semibold">
										£{selectedBooking.deposit_amount?.toFixed(2) || '0.00'}
									</div>
									<div class="text-xs">
										<span
											class={selectedBooking.deposit_paid ? 'text-green-600' : 'text-orange-600'}
										>
											{selectedBooking.deposit_paid ? 'Paid' : 'Outstanding'}
										</span>
										{#if !selectedBooking.deposit_paid && selectedBooking.deposit_deadline}
											<span class="text-gray-500">
												• Due: {new SvelteDate(selectedBooking.deposit_deadline).toLocaleDateString(
													'en-GB',
													{
														weekday: 'short',
														day: 'numeric',
														month: 'short',
														year: 'numeric'
													}
												)} at {new SvelteDate(selectedBooking.deposit_deadline).toLocaleTimeString(
													'en-GB',
													{
														hour: 'numeric',
														minute: '2-digit',
														hour12: true
													}
												)}
											</span>
										{/if}
									</div>
								</div>
							</div>
						{/if}

						<div class="flex items-center justify-between">
							<span class="text-sm text-gray-600">Subtotal (Services)</span>
							<span class="font-semibold">£{selectedBooking.total_amount.toFixed(2)}</span>
						</div>

						{#if selectedBooking.discounts && selectedBooking.discounts.length > 0}
							<div class="border-y border-fuchsia-100 bg-fuchsia-50/20 py-2 my-2 space-y-1 rounded-md px-2">
								{#each selectedBooking.discounts as d}
									<div class="flex items-center justify-between text-xs text-fuchsia-800">
										<span class="flex items-center gap-1.5">
											<span class="h-1.5 w-1.5 rounded-full bg-fuchsia-400"></span>
											{#if d.discount_source === 'loyalty'}
												Loyalty Stamp Card (10% Off)
											{:else if d.campaign_name}
												{d.campaign_name} ({d.discount_percent}% Off)
											{:else}
												Promo Campaign ({d.discount_percent}% Off)
											{/if}
										</span>
										<span class="font-medium">-£{d.discount_amount.toFixed(2)}</span>
									</div>
								{/each}
							</div>
							<div class="flex items-center justify-between font-medium text-gray-900">
								<span class="text-sm">Net Total</span>
								<span>£{(selectedBooking.total_amount - selectedBooking.discounts.reduce((sum, d) => sum + d.discount_amount, 0)).toFixed(2)}</span>
							</div>
						{/if}

						<div class="flex items-center justify-between">
							<span class="text-sm text-gray-600">Amount Paid (Card/Cash)</span>
							<span class="font-semibold text-green-700">
								£{(selectedBooking.payments ?? []).filter(p => p.payment_method !== 'discount' && p.status === 'completed').reduce((sum, p) => sum + p.amount, 0).toFixed(2)}
							</span>
						</div>

						{#if Math.max(0, selectedBooking.total_amount - (selectedBooking.discounts ?? []).reduce((sum, d) => sum + d.discount_amount, 0) - (selectedBooking.payments ?? []).filter(p => p.payment_method !== 'discount' && p.status === 'completed').reduce((sum, p) => sum + p.amount, 0)) > 0.01}
							<div class="flex items-center justify-between border-t border-gray-300 pt-2">
								<span class="font-medium text-gray-900">
									{isFutureBooking ? 'Estimated Subtotal' : 'Amount Due'}
								</span>
								<span class="text-lg font-bold text-red-600">
									£{Math.max(0, selectedBooking.total_amount - (selectedBooking.discounts ?? []).reduce((sum, d) => sum + d.discount_amount, 0) - (selectedBooking.payments ?? []).filter(p => p.payment_method !== 'discount' && p.status === 'completed').reduce((sum, p) => sum + p.amount, 0)).toFixed(2)}
								</span>
							</div>
						{/if}
					</div>
				</div>

				{#if selectedBooking.payments && selectedBooking.payments.length > 0}
					<div class="rounded-lg border border-gray-200 bg-gray-50 p-4">
						<h3 class="mb-3 text-sm font-semibold tracking-wide text-gray-600 uppercase">
							Payment History
						</h3>
						<div class="space-y-3">
							{#each selectedBooking.payments as payment, index (index)}
								<div class="rounded-md border border-gray-300 bg-white p-3">
									<div class="flex items-start justify-between">
										<div class="flex-1">
											<div class="flex items-center gap-2">
												<span class="font-medium text-gray-900"
													>{getPaymentName(payment, index, selectedBooking.payments, selectedBooking.discounts)}</span
>
												<span
													class="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium
                                                    {payment.status === 'completed'
														? 'bg-green-100 text-green-800'
														: payment.status === 'pending'
															? 'bg-yellow-100 text-yellow-800'
															: 'bg-gray-100 text-gray-800'}"
												>
													{payment.status}
												</span>
											</div>
											<div class="mt-1 text-xs text-gray-500">
												{#if payment.payment_method === 'discount'}
													Applied automatically on completion
												{:else}
													{payment.payment_type.charAt(0).toUpperCase() +
														payment.payment_type.slice(1)} payment
													{#if payment.card_last4}
														, Card ending in {payment.card_last4}
													{/if}
												{/if}
											</div>
											{#if payment.is_vat_applicable}
												<div class="mt-2 text-xs text-gray-600">
													<div>Net: £{payment.net_amount?.toFixed(2) || '0.00'}</div>
													{#if payment.vat_amount}
														<div>
															VAT ({(payment.vat_rate || 0) * 100}%): £{payment.vat_amount.toFixed(
																2
															)}
														</div>
													{/if}
												</div>
											{/if}
											<div class="mt-1 text-xs text-gray-400">
												{new SvelteDate(payment.created_at).toLocaleString()}
											</div>
										</div>
										<div class="text-right font-semibold">
											{payment.payment_method === 'discount' ? '-' : ''}£{payment.amount.toFixed(2)}
										</div>
									</div>
								</div>
							{/each}
						</div>
					</div>
				{/if}
			</div>
		{/if}

		<div class="flex flex-col gap-2 border-t px-4 py-3">
			<div class="flex gap-2">
				{#if isCancellable}
					<Button
						variant="destructive"
						size="sm"
						class="flex-1"
						onclick={() => (showCancelConfirm = true)}
					>
						Cancel Booking
					</Button>
					{#if canEditBooking}
						<Button
							variant="outline"
							size="sm"
							class="flex-1"
							onclick={() => {
								showEditModal = true;
							}}
						>
							Edit Request
						</Button>
					{/if}
				{/if}
			</div>
			<div class="flex gap-2">
				{#if isCompleted}
					<Button
						size="sm"
						class="flex-1 hover:bg-fuchsia-50"
						variant="outline"
						onclick={() => (showTipModal = true)}
					>
						Leave a Tip
					</Button>
				{/if}
				{#if depositOutstanding}
					<Button
						size="sm"
						class="flex-1 bg-amber-600 text-white hover:bg-amber-700"
						onclick={() => (showPaymentModal = true)}
						disabled={hasPendingEditRequest}
					>
						Pay Deposit
					</Button>
				{:else if canPayEarly && !hasPendingEditRequest}
					<Button
						size="sm"
						class="flex-1 bg-emerald-600 text-white hover:bg-emerald-700"
						onclick={() => (showPaymentModal = true)}
						disabled={hasPendingEditRequest}
					>
						Pay Early
					</Button>
				{/if}
			</div>
			<Button size="sm" class="w-full" variant="ghost" onclick={() => (open = false)}>Close</Button>
		</div>
	</Modal.Content>
</Modal.Root>

{#if showEditModal && selectedBooking}
	<EditRequestModal
		bind:open={showEditModal}
		booking={selectedBooking}
		onSubmitted={() => {
			showEditModal = false;
			fetchBookingDetails();
		}}
	/>
{/if}

{#if showPaymentModal && selectedBooking}
	<UserPaymentModal
		booking={selectedBooking}
		onClose={() => (showPaymentModal = false)}
		onComplete={handlePaymentComplete}
		{canSaveCards}
	/>
{/if}

<Modal.Root open={showCancelConfirm} onOpenChange={(v) => (showCancelConfirm = v)}>
	<Modal.Content class="!z-[70] max-w-[calc(100%-2rem)]">
		<Modal.Header>
			<Modal.Title>Cancel Booking</Modal.Title>
			<Modal.Description>
				{#if hasPayments}
					<p>
						Are you sure you want to cancel this booking? You have already made payments totalling
						<span class="font-semibold">£{totalPaid.toFixed(2)}</span>.
					</p>
				{:else}
					Are you sure you want to cancel this booking?
				{/if}
				{#if hasPayments}
					<div
						class="mt-2 rounded-md border border-amber-200 bg-amber-50 p-3 text-sm text-amber-800"
					>
						<p class="font-medium">Please note:</p>
						<p class="mt-1">
							Any amounts paid (<span class="font-semibold">£{totalPaid.toFixed(2)}</span>) will
							not be refunded, but will be retained as credit towards a future appointment.
						</p>
						{#if selectedBooking}
							{#if selectedBooking.deposit_paid}
								<p class="mt-1">
									The deposit of
									<span class="font-semibold">£{selectedBooking.deposit_amount?.toFixed(2)}</span>
									paid for this booking may be forfeited.
								</p>
							{/if}
							{#if selectedBooking.deposit_required && !selectedBooking.deposit_paid}
								<p class="mt-1">Any outstanding deposit will no longer be due.</p>
							{/if}
						{/if}
					</div>
				{/if}
			</Modal.Description>
		</Modal.Header>
		<Modal.Footer>
			<Button variant="outline" onclick={() => (showCancelConfirm = false)}>Keep Booking</Button>
			<Button variant="destructive" onclick={cancelBooking} disabled={cancelling}>
				{cancelling ? 'Cancelling...' : 'Yes, Cancel'}
			</Button>
		</Modal.Footer>
	</Modal.Content>
</Modal.Root>

<Modal.Root
	open={showTipModal}
	onOpenChange={(v) => {
		if (!v) {
			showTipModal = false;
			tipAmount = 0;
			selectedTipPreset = null;
			customTipInput = '';
		}
	}}
>
	<Modal.Content class="!z-[70] max-w-[calc(100%-2rem)]">
		<Modal.Header>
			<Modal.Title>Leave a Tip</Modal.Title>
			<Modal.Description>Show your appreciation for great service</Modal.Description>
		</Modal.Header>

		<div class="space-y-4 px-4 pb-4">
			<div class="grid grid-cols-3 gap-3">
				{#each tipPresets as preset (preset.pct)}
					<button
						class="rounded-lg border border-input bg-background py-3 text-center font-semibold transition-colors hover:bg-fuchsia-50 {selectedTipPreset ===
						preset.amount
							? 'bg-fuchsia-100'
							: ''}"
						onclick={() => selectTipPreset(preset.amount)}
						type="button"
					>
						<div>£{preset.amount.toFixed(2)}</div>
						<div class="text-xs font-normal text-gray-500">{preset.pct}%</div>
					</button>
				{/each}
			</div>

			<div>
				<label for="custom-tip" class="text-sm font-medium text-gray-700"
					>Or enter custom amount</label
				>
				<div class="relative mt-1">
					<span class="absolute top-1/2 left-3 -translate-y-1/2 text-gray-500">£</span>
					<Input
						id="custom-tip"
						type="text"
						inputmode="decimal"
						step="0.01"
						min="0"
						placeholder="0.00"
						class="pl-7"
						value={customTipInput}
						oninput={handleCustomTip}
					/>
				</div>
			</div>
		</div>

		<Modal.Footer>
			<Button variant="outline" onclick={() => (showTipModal = false)}>Cancel</Button>
			<Button
				class="hover:bg-fuchsia-50"
				onclick={submitTip}
				disabled={tipAmount <= 0 || tipProcessing}
				loading={tipProcessing}
			>
				{tipProcessing ? 'Processing...' : `Pay Tip £${tipAmount.toFixed(2)}`}
			</Button>
		</Modal.Footer>
	</Modal.Content>
</Modal.Root>
