<script lang="ts">
	import SelectionModal from '$lib/components/shared/SelectionModal.svelte';
	import { AdminProjectsStore, UpdateInvoiceStore } from '$houdini';
	import { SvelteSet } from 'svelte/reactivity';
	import type { GetInvoice$result } from '$houdini';
	import type { AccountAddressInfo } from '$lib/utils/lookup';

	type Invoice = NonNullable<GetInvoice$result['invoice']>;

	interface Props {
		open: boolean;
		invoice: Invoice;
		accountLookup: Map<string, AccountAddressInfo>;
		onSuccess: () => void;
	}

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

	let loading = $state(false);
	let saving = $state(false);
	let error = $state('');
	let availableProjects = $state<
		{
			id: string;
			name: string;
			date: string;
			amount: string | number | null;
			accountAddressId: string | null;
			customerId: string;
		}[]
	>([]);
	let selectedProjectIds = new SvelteSet<string>();

	const projectsStore = new AdminProjectsStore();
	const updateStore = new UpdateInvoiceStore();

	// Get customer UUID from the invoice
	let customerUuid = $derived(invoice.customerId);

	// Get already included project IDs
	let includedProjectIds = $derived(new Set(invoice.projects.map((p) => p.id)));

	// Load available projects when modal opens
	$effect(() => {
		if (open) {
			loadAvailableProjects();
			selectedProjectIds.clear();
		}
	});

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

		try {
			const result = await projectsStore.fetch({
				variables: {
					filters: {
						customerId: { exact: customerUuid },
						status: { exact: 'COMPLETED' }
					}
				}
			});

			availableProjects = (result.data?.projects ?? []).filter(
				(project) => !includedProjectIds.has(project.id)
			);
		} catch (err) {
			console.error('Failed to load projects:', err);
			error = 'Failed to load projects';
		} finally {
			loading = false;
		}
	}

	function formatCurrency(value: string | number | null | undefined): string {
		if (value === null || value === undefined) return '$0.00';
		const num = typeof value === 'string' ? parseFloat(value) : value;
		return new Intl.NumberFormat('en-US', {
			style: 'currency',
			currency: 'USD'
		}).format(num);
	}

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

	function getProjectDisplayName(project: {
		name: string;
		date: string;
		accountAddressId: string | null;
		customerId: string;
	}): string {
		const dateStr = formatDate(project.date);

		let locationName = '';
		if (project.accountAddressId) {
			const accountInfo = accountLookup.get(project.accountAddressId);
			if (accountInfo) {
				locationName = accountInfo.accountName;
			}
		}

		if (locationName) {
			return `${dateStr} - ${locationName} - ${project.name}`;
		}
		return `${dateStr} - ${project.name}`;
	}

	function toggleProject(projectId: string) {
		if (selectedProjectIds.has(projectId)) {
			selectedProjectIds.delete(projectId);
		} else {
			selectedProjectIds.add(projectId);
		}
	}

	function selectAll() {
		for (const project of availableProjects) {
			selectedProjectIds.add(project.id);
		}
	}

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

	// Calculate total of selected projects
	let selectedTotal = $derived(
		availableProjects
			.filter((p) => selectedProjectIds.has(p.id))
			.reduce((sum, p) => sum + parseFloat(String(p.amount ?? 0)), 0)
	);

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

		saving = true;
		error = '';

		try {
			const existingIds = invoice.projects.map((p) => p.id);
			const newIds = [...selectedProjectIds];
			const allIds = [...existingIds, ...newIds];

			await updateStore.mutate({
				input: {
					id: invoice.id,
					projectIds: allIds
				}
			});

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

	function handleClose() {
		open = false;
	}
</script>

<SelectionModal
	bind:open
	title="Add Projects"
	subtitle="Select completed projects to add to this invoice."
	itemName="Project"
	{loading}
	{saving}
	{error}
	selectedCount={selectedProjectIds.size}
	hasItems={availableProjects.length > 0}
	emptyMessage="No additional completed projects available for this customer."
	showTotal={true}
	{selectedTotal}
	colorScheme="accent"
	onSave={handleSave}
	onClose={handleClose}
	{selectAll}
	{selectNone}
>
	{#each availableProjects as project (project.id)}
		<label
			class="flex cursor-pointer items-center gap-3 rounded-lg border border-theme interactive p-3"
		>
			<input
				type="checkbox"
				checked={selectedProjectIds.has(project.id)}
				onchange={() => toggleProject(project.id)}
				class="checkbox-base"
			/>
			<span class="min-w-0 flex-1">
				<span class="text-sm font-medium text-theme">{getProjectDisplayName(project)}</span>
			</span>
			<span class="text-sm font-semibold text-accent-600 dark:text-accent-400">
				{formatCurrency(project.amount)}
			</span>
		</label>
	{/each}
</SelectionModal>
