<script lang="ts">
	import { CreateServiceStore, UpdateServiceStore } from '$houdini';
	import { offCanvas } from '$lib/stores/offCanvas.svelte';
	import { fromGlobalId } from '$lib/utils/relay';
	import type { GetService$result, Customers$result, Accounts$result, Team$result } from '$houdini';
	import IconSpinner from '$lib/components/icons/IconSpinner.svelte';

	type Service = NonNullable<GetService$result['service']>;
	type Customer = Customers$result['customers'][number];
	type Account = Accounts$result['accounts'][number];
	type TeamProfile = Team$result['teamProfiles'][number];

	interface Props {
		service?: Service;
		customers: Customer[];
		accounts: Account[];
		teamProfiles: TeamProfile[];
		onSuccess?: () => void;
		onCancel?: () => void;
	}

	let { service, customers, accounts, teamProfiles, onSuccess, onCancel }: Props = $props();

	let isEdit = $derived(!!service);
	let submitting = $state(false);
	let error = $state('');

	// Helper to find customer Relay Global ID from UUID
	function findCustomerGlobalId(accountAddressUuid: string | null | undefined): string {
		if (!accountAddressUuid) return '';
		// Find account that contains this address, then get its customer
		for (const account of accounts) {
			const hasAddress = account.addresses?.some((a) => fromGlobalId(a.id) === accountAddressUuid);
			if (hasAddress && account.customerId) {
				const customer = customers.find((c) => fromGlobalId(c.id) === account.customerId);
				return customer?.id ?? '';
			}
		}
		return '';
	}

	// Helper to find address Relay Global ID from UUID
	function findAddressGlobalId(addressUuid: string | null | undefined): string {
		if (!addressUuid) return '';
		for (const account of accounts) {
			const address = account.addresses?.find((a) => fromGlobalId(a.id) === addressUuid);
			if (address) return address.id;
		}
		return '';
	}

	// Helper to find account that contains an address UUID
	function findAccountForAddressUuid(addressUuid: string | null | undefined): string {
		if (!addressUuid) return '';
		for (const account of accounts) {
			const hasAddress = account.addresses?.some((a) => fromGlobalId(a.id) === addressUuid);
			if (hasAddress) return account.id;
		}
		return '';
	}

	// Helper to convert team member UUIDs (pk) to Relay Global IDs
	function findTeamMemberGlobalIds(memberPks: { pk: string }[] | null | undefined): string[] {
		if (!memberPks) return [];
		return memberPks
			.map((m) => {
				const profile = teamProfiles.find((p) => fromGlobalId(p.id) === m.pk);
				return profile?.id;
			})
			.filter((id): id is string => !!id);
	}

	// Form fields
	let customerId = $state(findCustomerGlobalId(service?.accountAddressId));
	let selectedAccountId = $state(findAccountForAddressUuid(service?.accountAddressId));
	let accountAddressId = $state(findAddressGlobalId(service?.accountAddressId));
	let date = $state(service?.date ?? '');
	let notes = $state(service?.notes ?? '');
	let selectedTeamMemberIds = $state<string[]>(findTeamMemberGlobalIds(service?.teamMembers));

	// Filter accounts for selected customer
	let customerAccounts = $derived(() => {
		if (!customerId) return [];
		const customerUuid = fromGlobalId(customerId);
		return accounts.filter((a) => a.customerId === customerUuid);
	});

	// Get addresses for selected account
	let accountAddresses = $derived(() => {
		if (!selectedAccountId) return [];
		const account = customerAccounts().find((a) => a.id === selectedAccountId);
		return account?.addresses ?? [];
	});

	// Get currently selected address details for display
	let selectedAddressDetails = $derived(() => {
		if (!accountAddressId) return null;
		for (const account of customerAccounts()) {
			const address = account.addresses?.find((a) => a.id === accountAddressId);
			if (address) {
				return { account, address };
			}
		}
		return null;
	});

	// When customer changes, reset account and address
	function handleCustomerChange() {
		selectedAccountId = '';
		accountAddressId = '';
	}

	// When account changes, auto-select if only one address, otherwise reset
	function handleAccountChange() {
		const addresses = accountAddresses();
		if (addresses.length === 1) {
			accountAddressId = addresses[0].id;
		} else {
			accountAddressId = '';
		}
	}

	// Non-admin team members only (for display)
	let nonAdminTeamMembers = $derived(teamProfiles.filter((p) => p.role !== 'ADMIN'));

	// Get admin profile ID to auto-include on create
	let adminProfileId = $derived(teamProfiles.find((p) => p.role === 'ADMIN')?.id ?? null);

	// Track if service is dispatched (admin profile is in team members)
	let isDispatched = $derived(
		adminProfileId ? selectedTeamMemberIds.includes(adminProfileId) : false
	);

	function toggleDispatched() {
		if (!adminProfileId) return;
		if (isDispatched) {
			// When un-dispatching, remove admin and clear all team members
			selectedTeamMemberIds = [];
		} else {
			selectedTeamMemberIds = [...selectedTeamMemberIds, adminProfileId];
		}
	}

	const createStore = new CreateServiceStore();
	const updateStore = new UpdateServiceStore();

	async function handleSubmit(e: SubmitEvent) {
		e.preventDefault();
		submitting = true;
		error = '';

		try {
			if (!date) {
				error = 'Please provide a date';
				return;
			}

			if (!isEdit && !accountAddressId) {
				error = 'Please select an account and address';
				return;
			}

			if (isEdit && service) {
				// Update existing service - only date, notes, and team members
				const res = await updateStore.mutate({
					input: {
						id: service.id,
						date,
						notes: notes.trim() || null,
						teamMemberIds: selectedTeamMemberIds
					}
				});

				if (res.errors?.length) {
					error = res.errors.map((e) => e.message).join(', ');
					return;
				}
			} else {
				// Create new service
				// Get account ID from the selected account
				const selectedAccount = customerAccounts().find((a) => a.id === selectedAccountId);

				// Build team member IDs, always including admin profile
				const teamMemberIds = [...selectedTeamMemberIds];
				if (adminProfileId && !teamMemberIds.includes(adminProfileId)) {
					teamMemberIds.push(adminProfileId);
				}

				const res = await createStore.mutate({
					input: {
						accountId: selectedAccount?.id ?? null,
						accountAddressId,
						date,
						status: 'SCHEDULED',
						notes: notes.trim() || null,
						teamMemberIds: teamMemberIds.length > 0 ? teamMemberIds : null
					}
				});

				if (res.errors?.length) {
					error = res.errors.map((e) => e.message).join(', ');
					return;
				}
			}

			offCanvas.closeRight();
			onSuccess?.();
		} catch (err) {
			error = err instanceof Error ? err.message : 'Failed to save service';
		} finally {
			submitting = false;
		}
	}

	function handleCancel() {
		offCanvas.closeRight();
		onCancel?.();
	}

	function toggleTeamMember(id: string) {
		if (selectedTeamMemberIds.includes(id)) {
			selectedTeamMemberIds = selectedTeamMemberIds.filter((m) => m !== id);
		} else {
			selectedTeamMemberIds = [...selectedTeamMemberIds, id];
		}
	}
</script>

<div class="min-w-0 space-y-6">
	{#if error}
		<div class="alert-error">
			{error}
		</div>
	{/if}

	<form class="space-y-4" onsubmit={handleSubmit}>
		<!-- Customer (only for create) -->
		{#if !isEdit}
			<div>
				<label for="customerId" class="mb-1.5 block text-sm font-medium text-theme">
					Customer <span class="text-red-500">*</span>
				</label>
				<div class="relative w-full">
					<select
						id="customerId"
						bind:value={customerId}
						onchange={handleCustomerChange}
						disabled={submitting}
						class="w-full appearance-none rounded-lg border border-theme bg-theme py-2 pr-10 pl-3 text-theme focus:border-primary-500 focus:ring-1 focus:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50"
					>
						<option value="">Select a customer</option>
						{#each customers as customer (customer.id)}
							<option value={customer.id}>{customer.name}</option>
						{/each}
					</select>
					<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3">
						<svg
							class="h-4 w-4 text-theme-muted"
							style="fill: none"
							stroke="currentColor"
							viewBox="0 0 24 24"
						>
							<path
								stroke-linecap="round"
								stroke-linejoin="round"
								stroke-width="2"
								d="M19 9l-7 7-7-7"
							/>
						</svg>
					</div>
				</div>
			</div>

			<!-- Account/Address Selection (only for create) -->
			{#if customerId}
				<div class="space-y-4 rounded-lg border border-theme bg-theme-card p-4">
					<p class="text-sm font-medium text-theme">Service Location</p>

					{#if customerAccounts().length > 0}
						<!-- Account Selection -->
						<div>
							<label for="selectedAccountId" class="mb-1.5 block text-sm text-theme-secondary">
								Account <span class="text-red-500">*</span>
							</label>
							<div class="relative w-full">
								<select
									id="selectedAccountId"
									bind:value={selectedAccountId}
									onchange={handleAccountChange}
									disabled={submitting}
									class="w-full appearance-none rounded-lg border border-theme bg-theme py-2 pr-10 pl-3 text-theme focus:border-primary-500 focus:ring-1 focus:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50"
								>
									<option value="">Select an account</option>
									{#each customerAccounts() as account (account.id)}
										<option value={account.id}>{account.name}</option>
									{/each}
								</select>
								<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3">
									<svg
										class="h-4 w-4 text-theme-muted"
										style="fill: none"
										stroke="currentColor"
										viewBox="0 0 24 24"
									>
										<path
											stroke-linecap="round"
											stroke-linejoin="round"
											stroke-width="2"
											d="M19 9l-7 7-7-7"
										/>
									</svg>
								</div>
							</div>
						</div>

						<!-- Address Selection (shown when account is selected) -->
						{#if selectedAccountId && accountAddresses().length > 0}
							<div>
								<label for="accountAddressId" class="mb-1.5 block text-sm text-theme-secondary">
									Address <span class="text-red-500">*</span>
								</label>
								{#if accountAddresses().length === 1}
									<!-- Single address - show as confirmation -->
									{@const address = accountAddresses()[0]}
									<div
										class="rounded-lg border border-primary-200 bg-primary-50 p-3 dark:border-primary-800 dark:bg-primary-900/20"
									>
										<div class="flex items-start gap-2">
											<svg
												class="mt-0.5 h-4 w-4 flex-shrink-0 text-primary-500"
												style="fill: none"
												stroke="currentColor"
												viewBox="0 0 24 24"
											>
												<path
													stroke-linecap="round"
													stroke-linejoin="round"
													stroke-width="2"
													d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"
												/>
												<path
													stroke-linecap="round"
													stroke-linejoin="round"
													stroke-width="2"
													d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"
												/>
											</svg>
											<div class="text-sm">
												<p class="font-medium text-theme">{address.streetAddress}</p>
												<p class="text-theme-secondary">
													{address.city}, {address.state}
													{address.zipCode}
												</p>
											</div>
										</div>
									</div>
								{:else}
									<!-- Multiple addresses - show dropdown -->
									<div class="relative w-full">
										<select
											id="accountAddressId"
											bind:value={accountAddressId}
											disabled={submitting}
											class="w-full appearance-none rounded-lg border border-theme bg-theme py-2 pr-10 pl-3 text-theme focus:border-primary-500 focus:ring-1 focus:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50"
										>
											<option value="">Select an address</option>
											{#each accountAddresses() as address (address.id)}
												<option value={address.id}>
													{address.streetAddress}, {address.city}, {address.state}
												</option>
											{/each}
										</select>
										<div
											class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3"
										>
											<svg
												class="h-4 w-4 text-theme-muted"
												style="fill: none"
												stroke="currentColor"
												viewBox="0 0 24 24"
											>
												<path
													stroke-linecap="round"
													stroke-linejoin="round"
													stroke-width="2"
													d="M19 9l-7 7-7-7"
												/>
											</svg>
										</div>
									</div>
								{/if}
							</div>

							<!-- Show selected address confirmation (for multi-address accounts) -->
							{#if accountAddresses().length > 1 && selectedAddressDetails()}
								{@const details = selectedAddressDetails()}
								<div
									class="rounded-lg border border-primary-200 bg-primary-50 p-3 dark:border-primary-800 dark:bg-primary-900/20"
								>
									<div class="flex items-start gap-2">
										<svg
											class="mt-0.5 h-4 w-4 flex-shrink-0 text-primary-500"
											style="fill: none"
											stroke="currentColor"
											viewBox="0 0 24 24"
										>
											<path
												stroke-linecap="round"
												stroke-linejoin="round"
												stroke-width="2"
												d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"
											/>
											<path
												stroke-linecap="round"
												stroke-linejoin="round"
												stroke-width="2"
												d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"
											/>
										</svg>
										<div class="text-sm">
											<p class="font-medium text-theme">{details?.address.streetAddress}</p>
											<p class="text-theme-secondary">
												{details?.address.city}, {details?.address.state}
												{details?.address.zipCode}
											</p>
										</div>
									</div>
								</div>
							{/if}
						{:else if selectedAccountId && accountAddresses().length === 0}
							<p class="text-sm text-warning">
								This account has no addresses. Please select a different account or add an address
								to this account first.
							</p>
						{/if}
					{:else}
						<p class="text-sm text-warning">
							This customer has no accounts. Please create an account first.
						</p>
					{/if}
				</div>
			{/if}
		{/if}

		<!-- Date -->
		<div>
			<label for="date" class="mb-1.5 block text-sm font-medium text-theme">
				Date <span class="text-red-500">*</span>
			</label>
			<input
				id="date"
				type="date"
				bind:value={date}
				disabled={submitting}
				class="w-full rounded-lg border border-theme bg-theme px-3 py-2 text-theme focus:border-primary-500 focus:ring-1 focus:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50"
			/>
		</div>

		<!-- Dispatched Toggle -->
		<div class="flex items-center justify-between rounded-lg border border-theme bg-theme-card p-3">
			<div>
				<p class="text-sm font-medium text-theme">Dispatched</p>
				<p class="text-xs text-theme-muted">Required before assigning team members</p>
			</div>
			<button
				type="button"
				onclick={toggleDispatched}
				disabled={submitting}
				class="relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 {isDispatched
					? 'bg-emerald-500'
					: 'bg-gray-200 dark:bg-gray-700'}"
				role="switch"
				aria-checked={isDispatched}
				aria-label="Toggle dispatched status"
			>
				<span
					class="pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out {isDispatched
						? 'translate-x-5'
						: 'translate-x-0'}"
				></span>
			</button>
		</div>

		<!-- Team Members -->
		<div>
			<p class="mb-1.5 text-sm font-medium text-theme">Team Members</p>
			<div
				class="space-y-2 rounded-lg border border-theme bg-theme-card p-3 {!isDispatched
					? 'opacity-50'
					: ''}"
			>
				{#if !isDispatched}
					<p class="text-sm text-theme-muted italic">Enable "Dispatched" to assign team members</p>
				{:else if nonAdminTeamMembers.length > 0}
					{#each nonAdminTeamMembers as member (member.id)}
						<label class="flex cursor-pointer items-center gap-3 rounded-lg interactive p-2">
							<input
								type="checkbox"
								checked={selectedTeamMemberIds.includes(member.id)}
								onchange={() => toggleTeamMember(member.id)}
								disabled={submitting}
								class="h-4 w-4 rounded border-input text-primary-500 focus:ring-primary-500"
							/>
							<span class="text-sm text-theme">{member.fullName}</span>
							{#if member.role === 'TEAM_LEADER'}
								<span
									class="rounded bg-primary-100 px-1.5 py-0.5 text-xs text-primary-700 dark:bg-primary-900/40 dark:text-primary-400"
								>
									TL
								</span>
							{/if}
						</label>
					{/each}
				{:else}
					<p class="text-sm text-theme-muted">No team members available</p>
				{/if}
			</div>
		</div>

		<!-- Notes -->
		<div>
			<label for="notes" class="mb-1.5 block text-sm font-medium text-theme">Notes</label>
			<textarea
				id="notes"
				bind:value={notes}
				disabled={submitting}
				rows="3"
				placeholder="Optional notes about this service"
				class="placeholder-theme-muted w-full rounded-lg border border-theme bg-theme px-3 py-2 text-theme focus:border-primary-500 focus:ring-1 focus:ring-primary-500 disabled:cursor-not-allowed disabled:opacity-50"
			></textarea>
		</div>

		<!-- Submit Buttons -->
		<div class="flex items-center gap-3 pt-4">
			<button
				type="submit"
				disabled={submitting}
				class="flex-1 rounded-lg bg-primary-500 px-4 py-2 font-medium text-white transition-colors hover:bg-primary-600 disabled:cursor-not-allowed disabled:opacity-50"
			>
				{#if submitting}
					<span class="flex items-center justify-center gap-2">
						<IconSpinner class="h-4 w-4" />
						<span>{isEdit ? 'Saving...' : 'Creating...'}</span>
					</span>
				{:else}
					{isEdit ? 'Save Changes' : 'Create Service'}
				{/if}
			</button>
			<button
				type="button"
				onclick={handleCancel}
				disabled={submitting}
				class="rounded-lg border border-theme bg-theme px-4 py-2 font-medium text-theme transition-colors hover:bg-black/5 disabled:cursor-not-allowed disabled:opacity-50 dark:hover:bg-white/10"
			>
				Cancel
			</button>
		</div>
	</form>
</div>
