<script lang="ts">
	import { fade, scale } from 'svelte/transition';
	import { AdminServicesStore, UpdateReportStore } from '$houdini';
	import { SvelteSet } from 'svelte/reactivity';
	import type { GetReport$result } from '$houdini';

	type Report = NonNullable<GetReport$result['report']>;

	interface AccountInfo {
		accountName: string;
		addressName?: string | null;
	}

	interface Props {
		open: boolean;
		report: Report;
		teamMemberId: string;
		accountLookup: Map<string, AccountInfo>;
		onSuccess: () => void;
	}

	let { open = $bindable(false), report, teamMemberId, accountLookup, onSuccess }: Props = $props();

	let loading = $state(false);
	let saving = $state(false);
	let error = $state('');
	let availableServices = $state<{ id: string; date: string; accountAddressId: string | null }[]>(
		[]
	);
	let selectedServiceIds = new SvelteSet<string>();

	const servicesStore = new AdminServicesStore();
	const updateStore = new UpdateReportStore();

	// Get already included service IDs
	let includedServiceIds = $derived(new Set(report.services.map((s) => s.id)));

	// Load available services when modal opens
	$effect(() => {
		if (open) {
			loadAvailableServices();
			selectedServiceIds.clear();
		}
	});

	async function loadAvailableServices() {
		loading = true;
		error = '';

		// Extract year-month from report date (YYYY-MM)
		const [year, month] = report.date.split('-');
		const startOfMonth = `${year}-${month}-01`;
		const endOfMonth = new Date(parseInt(year), parseInt(month), 0).toISOString().split('T')[0];

		try {
			const result = await servicesStore.fetch({
				variables: {
					filters: {
						status: { exact: 'COMPLETED' },
						date: { gte: startOfMonth, lte: endOfMonth }
					}
				}
			});

			// Filter to only services assigned to this team member and not already included
			availableServices = (result.data?.services ?? []).filter((service) => {
				const isAssigned = service.teamMembers?.some((m) => m.pk === teamMemberId);
				const notIncluded = !includedServiceIds.has(service.id);
				return isAssigned && notIncluded;
			});
		} catch (err) {
			console.error('Failed to load services:', err);
			error = 'Failed to load services';
		} finally {
			loading = false;
		}
	}

	function formatItemDate(dateStr: string): string {
		return new Date(dateStr + 'T00:00:00').toLocaleDateString('en-US', {
			month: 'short',
			day: 'numeric'
		});
	}

	function getServiceDisplayName(service: {
		date: string;
		accountAddressId: string | null;
	}): string {
		const dateStr = formatItemDate(service.date);
		const accountInfo = service.accountAddressId
			? accountLookup.get(service.accountAddressId)
			: null;
		const accountName = accountInfo?.accountName ?? 'Unknown Account';
		return `${dateStr}, ${accountName}`;
	}

	function toggleService(serviceId: string) {
		if (selectedServiceIds.has(serviceId)) {
			selectedServiceIds.delete(serviceId);
		} else {
			selectedServiceIds.add(serviceId);
		}
	}

	function selectAll() {
		for (const service of availableServices) {
			selectedServiceIds.add(service.id);
		}
	}

	function selectNone() {
		selectedServiceIds.clear();
	}

	async function handleSave() {
		if (selectedServiceIds.size === 0) return;

		saving = true;
		error = '';

		try {
			// Combine existing service IDs with newly selected ones
			const existingIds = report.services.map((s) => s.id);
			const newIds = [...selectedServiceIds];
			const allIds = [...existingIds, ...newIds];

			await updateStore.mutate({
				input: {
					id: report.id,
					serviceIds: allIds
				}
			});

			open = false;
			onSuccess();
		} catch (err) {
			console.error('Failed to add services:', err);
			error = 'Failed to add services';
		} finally {
			saving = false;
		}
	}

	function handleClose() {
		open = false;
	}

	function handleBackdropClick(e: MouseEvent) {
		if (e.target === e.currentTarget) {
			handleClose();
		}
	}
</script>

{#if open}
	<!-- svelte-ignore a11y_no_static_element_interactions -->
	<div
		class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4"
		transition:fade={{ duration: 150 }}
		onmousedown={handleBackdropClick}
		onkeydown={(e) => e.key === 'Escape' && handleClose()}
	>
		<div
			class="max-h-[90vh] w-full max-w-lg overflow-hidden rounded-xl bg-theme-card shadow-xl"
			transition:scale={{ duration: 150, start: 0.95 }}
		>
			<!-- Header -->
			<div class="border-b border-theme px-6 py-4">
				<h2 class="text-lg font-semibold text-theme">Add Services</h2>
				<p class="mt-1 text-sm text-theme-muted">
					Select completed services to add to this report.
				</p>
			</div>

			<!-- Content -->
			<div class="max-h-[60vh] overflow-y-auto p-6">
				{#if loading}
					<div class="flex items-center justify-center py-8">
						<svg
							class="h-8 w-8 animate-spin text-secondary-500"
							style="fill: none"
							viewBox="0 0 24 24"
						>
							<circle
								class="opacity-25"
								cx="12"
								cy="12"
								r="10"
								stroke="currentColor"
								stroke-width="4"
							></circle>
							<path
								class="opacity-75"
								fill="currentColor"
								d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
							></path>
						</svg>
					</div>
				{:else if availableServices.length === 0}
					<p class="py-8 text-center text-sm text-theme-muted italic">
						No additional services available for this team member in this month.
					</p>
				{:else}
					<!-- Select All / None -->
					<div class="mb-4 flex items-center gap-4">
						<button
							onclick={selectAll}
							class="text-sm font-medium text-secondary-600 hover:underline dark:text-secondary-400"
						>
							Select All
						</button>
						<button
							onclick={selectNone}
							class="text-sm font-medium text-theme-muted hover:underline"
						>
							Select None
						</button>
						<span class="ml-auto text-sm text-theme-muted">
							{selectedServiceIds.size} selected
						</span>
					</div>

					<div class="space-y-2">
						{#each availableServices as service (service.id)}
							<label
								class="flex cursor-pointer items-center gap-3 rounded-lg border border-theme interactive p-3"
							>
								<input
									type="checkbox"
									checked={selectedServiceIds.has(service.id)}
									onchange={() => toggleService(service.id)}
									class="border-theme-muted h-4 w-4 rounded text-primary-500 focus:ring-primary-500"
								/>
								<span class="flex-1 text-sm text-theme">
									{getServiceDisplayName(service)}
								</span>
							</label>
						{/each}
					</div>
				{/if}

				{#if error}
					<div class="mt-4 rounded-lg bg-error-500/10 p-3">
						<p class="text-sm text-error-600 dark:text-error-400">{error}</p>
					</div>
				{/if}
			</div>

			<!-- Footer -->
			<div class="flex items-center justify-end gap-3 border-t border-theme px-6 py-4">
				<button onclick={handleClose} class="btn-ghost" disabled={saving}> Cancel </button>
				<button
					onclick={handleSave}
					class="btn-primary"
					disabled={saving || selectedServiceIds.size === 0}
				>
					{#if saving}
						Adding...
					{:else}
						Add {selectedServiceIds.size} Service{selectedServiceIds.size !== 1 ? 's' : ''}
					{/if}
				</button>
			</div>
		</div>
	</div>
{/if}
