<script lang="ts">
	import ContentContainer from '$lib/components/layout/ContentContainer.svelte';
	import AdminPageHeader from '$lib/components/admin/AdminPageHeader.svelte';
	import {
		SessionSectionHeader,
		SessionContent,
		StartSessionButton,
		type ExtendedServiceTask,
		type ServiceAreaWithCompletions,
		type ServiceAreaWithTasks
	} from '$lib/components/session';
	import ServiceForm from '$lib/components/admin/services/ServiceForm.svelte';
	import EventForm from '$lib/components/admin/calendar/EventForm.svelte';
	import { UpdateServiceStore } from '$houdini';
	import {
		openServiceSession,
		closeServiceSession,
		revertServiceSession,
		addServiceTask,
		removeServiceTask,
		createServiceNote,
		updateServiceNote,
		removeServiceNote,
		uploadServicePhoto,
		updateServicePhoto,
		removeServicePhoto,
		uploadServiceVideo,
		updateServiceVideo,
		removeServiceVideo
	} from '$lib/utils/session';
	import { offCanvas } from '$lib/stores/offCanvas.svelte';
	import type { PageData } from './$types';
	import { formatAddress } from '$lib/utils/lookup';
	import { formatDate } from '$lib/utils/date';
	import { fromGlobalId, toGlobalId } from '$lib/utils/relay';
	import { goto, invalidateAll } from '$app/navigation';
	import { SvelteSet, SvelteMap } from 'svelte/reactivity';

	let { data }: { data: PageData } = $props();

	// Core data
	let service = $derived(data.service);
	let session = $derived(data.session);
	let scope = $derived(data.scope);
	let serviceUuid = $derived(data.serviceUuid);
	let accountLookup = $derived(data.accountLookup);
	let nonAdminTeamIds = $derived(data.nonAdminTeamIds);
	let teamMemberLookup = $derived(data.teamMemberLookup);
	let teamProfiles = $derived(data.team?.data?.teamProfiles ?? []);
	let customers = $derived(data.customers?.data?.customers ?? []);
	let accounts = $derived(data.accounts?.data?.accounts ?? []);

	// Current user for note authorship
	let currentUserProfileId = $derived(data.user?.data?.me?.id ?? null);

	// Admin always has permission to revert
	let canRevertSession = true;

	// Account info
	let accountInfo = $derived(
		service.accountAddressId ? (accountLookup.get(service.accountAddressId) ?? null) : null
	);

	// Display name
	let displayName = $derived(accountInfo?.accountName ?? 'Service Details');

	// Address
	let address = $derived(accountInfo ? formatAddress(accountInfo) : null);

	// Account Global ID for linking to account page (derived from address lookup)
	let accountGlobalId = $derived(
		accountInfo?.accountId ? toGlobalId('AccountType', accountInfo.accountId) : null
	);

	// Team members (non-admin only)
	let teamMembers = $derived(() => {
		if (!service.teamMembers) return [];
		return service.teamMembers
			.filter((m) => nonAdminTeamIds.has(m.pk))
			.map((m) => teamMemberLookup.get(m.pk))
			.filter((m): m is NonNullable<typeof m> => m !== undefined);
	});

	// Check if admin is dispatched (admin profile is in teamMembers)
	let adminProfile = $derived(teamProfiles.find((p) => p.role === 'ADMIN'));
	let adminProfileUuid = $derived(adminProfile ? fromGlobalId(adminProfile.id) : null);
	let isDispatched = $derived(
		adminProfileUuid
			? (service.teamMembers?.some((m) => m.pk === adminProfileUuid) ?? false)
			: false
	);

	// Non-admin team members for messaging (exclude ADMIN role)
	let messagableMembers = $derived(teamMembers().filter((m) => m.role !== 'ADMIN'));

	// Build the subject line for messages
	let messageSubject = $derived(() => {
		const formattedDate = formatDate(service.date) || 'Unknown Date';
		const accountName = accountInfo?.accountName || 'Unknown';
		return `${formattedDate} - Service: ${accountName}`;
	});

	// Navigate to new message page with pre-filled params
	function messageTeamMember(memberId: string) {
		const params = new URLSearchParams({
			entityType: 'Service',
			entityId: service.id,
			participantIds: memberId,
			conversationType: 'DIRECT',
			subject: messageSubject()
		});
		goto(`/messages/new?${params.toString()}`);
	}

	// Navigate to new message page with all team members
	function messageAllTeamMembers() {
		const memberIds = messagableMembers.map((m) => m.id).join(',');
		const params = new URLSearchParams({
			entityType: 'Service',
			entityId: service.id,
			participantIds: memberIds,
			conversationType: 'GROUP',
			subject: messageSubject()
		});
		goto(`/messages/new?${params.toString()}`);
	}

	// Loading states
	let isStartingSession = $state(false);
	let isSubmitting = $state(false);
	let isReverting = $state(false);
	let submittingTaskId = $state<string | null>(null);
	let removingTaskId = $state<string | null>(null);

	// Build extended tasks from scope
	let tasks = $derived<ExtendedServiceTask[]>(
		scope?.areas?.flatMap(
			(area) =>
				area.tasks?.map((task) => ({
					...task,
					uuid: fromGlobalId(task.id),
					areaId: area.id,
					areaName: area.name
				})) || []
		) || []
	);

	// Task tracking
	let completedTaskIds = $derived(
		new SvelteSet(session?.completedTasks?.map((ct) => ct.taskId) || [])
	);
	let selectedTaskIds = new SvelteSet<string>();
	let availableTasksCount = $derived(
		tasks.filter((t) => !completedTaskIds.has(t.uuid) && !selectedTaskIds.has(t.uuid)).length
	);

	// Group completed tasks by area
	let completedTasksByArea = $derived.by((): ServiceAreaWithCompletions[] => {
		if (!session?.completedTasks || !scope?.areas) return [];
		const areaMap = new SvelteMap<string, ServiceAreaWithCompletions>();
		scope.areas.forEach((area) => {
			const areaTasks = session.completedTasks.filter((completion) => {
				const task = tasks.find((t) => t.uuid === completion.taskId);
				return task && task.areaId === area.id;
			});
			if (areaTasks.length > 0) {
				areaMap.set(area.id, { area, completions: areaTasks });
			}
		});
		return Array.from(areaMap.values());
	});

	// Group ready to submit tasks by area
	let readyToSubmitByArea = $derived.by((): ServiceAreaWithTasks[] => {
		if (!scope?.areas) return [];
		const areaMap = new SvelteMap<string, ServiceAreaWithTasks>();
		scope.areas.forEach((area) => {
			const areaTasks = tasks.filter((t) => t.areaId === area.id && selectedTaskIds.has(t.uuid));
			if (areaTasks.length > 0) {
				areaMap.set(area.id, { area, tasks: areaTasks });
			}
		});
		return Array.from(areaMap.values());
	});

	// Helper function to get team member name by ID
	function getTeamMemberName(completedById: string | null | undefined): string {
		if (!completedById) return 'Unknown';
		const member = teamMemberLookup.get(completedById);
		return member?.fullName || 'Unknown';
	}

	// Edit service
	function showEditForm() {
		offCanvas.showRight({
			title: 'Edit Service',
			content: editFormContent
		});
	}

	async function handleEditSuccess() {
		await invalidateAll();
	}

	// Schedule calendar event
	const updateServiceStore = new UpdateServiceStore();

	function showScheduleEventForm() {
		offCanvas.showRight({
			title: 'Schedule Calendar Event',
			content: scheduleEventContent
		});
	}

	async function handleEventSuccess(eventId: string) {
		// Save the calendar event ID to the service
		await updateServiceStore.mutate({
			input: {
				id: service.id,
				calendarEventId: eventId
			}
		});
		await invalidateAll();
	}

	// Build initial values for calendar event from service data
	let eventInitialValues = $derived(() => {
		const addressName = accountInfo?.addressName || 'Primary Service Address';
		const titleParts = ['SERVICE:', accountInfo?.accountName, '-', addressName].filter(Boolean);
		return {
			summary: titleParts.join(' '),
			location: address || undefined,
			date: service.date
		};
	});

	// Session handlers
	async function handleStartSession() {
		isStartingSession = true;
		try {
			await openServiceSession({ serviceId: serviceUuid });
			await invalidateAll();
		} catch (err) {
			console.error('Failed to start session:', err);
		} finally {
			isStartingSession = false;
		}
	}

	async function handleCloseSession() {
		if (!session) return;
		isSubmitting = true;
		try {
			if (selectedTaskIds.size > 0) {
				const promises = Array.from(selectedTaskIds).map((taskUuid) =>
					addServiceTask(serviceUuid, taskUuid)
				);
				await Promise.all(promises);
				selectedTaskIds.clear();
			}
			await closeServiceSession({ serviceId: serviceUuid, taskIds: [] });
			await goto('/admin/services', { invalidateAll: true });
		} catch (err) {
			console.error('Failed to close session:', err);
		} finally {
			isSubmitting = false;
		}
	}

	async function handleRevertSession() {
		if (
			!confirm(
				'Are you sure you want to cancel this session? All completed tasks, photos, videos, and notes will be deleted.'
			)
		) {
			return;
		}
		isReverting = true;
		try {
			await revertServiceSession(serviceUuid);
			await goto('/admin/services', { invalidateAll: true });
		} catch (err) {
			console.error('Failed to revert session:', err);
		} finally {
			isReverting = false;
		}
	}

	// Task handlers
	function toggleTask(taskUuid: string) {
		if (selectedTaskIds.has(taskUuid)) {
			selectedTaskIds.delete(taskUuid);
		} else {
			selectedTaskIds.add(taskUuid);
		}
	}

	async function handleSubmitTask(taskUuid: string) {
		if (!session) return;
		try {
			submittingTaskId = taskUuid;
			await addServiceTask(serviceUuid, taskUuid);
			selectedTaskIds.delete(taskUuid);
			await invalidateAll();
		} catch (err) {
			console.error('Failed to submit task:', err);
		} finally {
			submittingTaskId = null;
		}
	}

	function handleRemoveTask(taskUuid: string) {
		selectedTaskIds.delete(taskUuid);
	}

	async function handleRemoveCompletedTask(taskUuid: string) {
		if (!session) return;
		try {
			removingTaskId = taskUuid;
			await removeServiceTask(serviceUuid, taskUuid);
			await invalidateAll();
		} catch (err) {
			console.error('Failed to remove completed task:', err);
		} finally {
			removingTaskId = null;
		}
	}

	async function handleSubmitAllTasks() {
		if (!session || selectedTaskIds.size === 0) return;
		try {
			isSubmitting = true;
			const promises = Array.from(selectedTaskIds).map((taskUuid) =>
				addServiceTask(serviceUuid, taskUuid)
			);
			await Promise.all(promises);
			selectedTaskIds.clear();
			await invalidateAll();
		} catch (err) {
			console.error('Failed to submit all tasks:', err);
		} finally {
			isSubmitting = false;
		}
	}

	// Note handlers
	async function handleAddNote(content: string, internal: boolean) {
		if (!session) return;
		await createServiceNote({
			sessionId: session.id,
			content,
			internal,
			authorId: currentUserProfileId
		});
		await invalidateAll();
	}

	async function handleUpdateNote(noteId: string, content: string, internal: boolean) {
		await updateServiceNote({ id: noteId, content, internal });
		await invalidateAll();
	}

	async function handleDeleteNote(noteId: string) {
		await removeServiceNote(noteId);
		await invalidateAll();
	}

	// Media handlers
	async function handleUploadPhoto(file: File, title: string, notes: string, internal: boolean) {
		if (!session) return;
		await uploadServicePhoto(file, session.id, title, notes, internal);
		await invalidateAll();
	}

	async function handleUploadVideo(file: File, title: string, notes: string, internal: boolean) {
		if (!session) return;
		await uploadServiceVideo(file, session.id, title, notes, internal);
		await invalidateAll();
	}

	async function handleUpdatePhoto(
		photoId: string,
		title: string,
		notes: string,
		internal: boolean
	) {
		await updateServicePhoto({ id: photoId, title, notes, internal });
		await invalidateAll();
	}

	async function handleUpdateVideo(
		videoId: string,
		title: string,
		notes: string,
		internal: boolean
	) {
		await updateServiceVideo({ id: videoId, title, notes, internal });
		await invalidateAll();
	}

	async function handleDeletePhoto(photoId: string) {
		await removeServicePhoto(photoId);
		await invalidateAll();
	}

	async function handleDeleteVideo(videoId: string) {
		await removeServiceVideo(videoId);
		await invalidateAll();
	}
</script>

{#snippet editFormContent()}
	<ServiceForm {service} {customers} {accounts} {teamProfiles} onSuccess={handleEditSuccess} />
{/snippet}

{#snippet scheduleEventContent()}
	<EventForm {teamProfiles} initialValues={eventInitialValues()} onSuccess={handleEventSuccess} />
{/snippet}

<svelte:head>
	<title>{displayName} - Services - Admin - Nexus</title>
</svelte:head>

<div class="py-8">
	<ContentContainer>
		<AdminPageHeader
			title={displayName}
			subtitle={accountInfo?.addressName}
			colorScheme="secondary"
			backHref="/admin/services"
			invalidateOnBack
			onEdit={showEditForm}
		/>

		<!-- Service Details Card -->
		<div class="mb-6 rounded-xl border border-theme bg-theme-card p-6">
			<div class="mb-4 flex items-center justify-between">
				<h2 class="text-lg font-semibold text-theme">Service Details</h2>
				{#if service.calendarEventId}
					<a
						href="/admin/calendar/{service.calendarEventId}"
						class="inline-flex items-center gap-2 rounded-lg bg-accent7-500/10 px-3 py-1.5 text-sm font-medium text-accent7-600 transition-colors hover:bg-accent7-500/20 dark:text-accent7-400"
					>
						<svg class="h-4 w-4" style="fill: none" stroke="currentColor" viewBox="0 0 24 24">
							<path
								stroke-linecap="round"
								stroke-linejoin="round"
								stroke-width="2"
								d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
							/>
						</svg>
						View Event
					</a>
				{:else}
					<button
						type="button"
						onclick={showScheduleEventForm}
						class="inline-flex items-center gap-2 rounded-lg bg-accent7-500/10 px-3 py-1.5 text-sm font-medium text-accent7-600 transition-colors hover:bg-accent7-500/20 dark:text-accent7-400"
					>
						<svg class="h-4 w-4" style="fill: none" stroke="currentColor" viewBox="0 0 24 24">
							<path
								stroke-linecap="round"
								stroke-linejoin="round"
								stroke-width="2"
								d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
							/>
						</svg>
						Schedule Event
					</button>
				{/if}
			</div>
			<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
				<!-- Status -->
				<div>
					<p class="detail-label">Status</p>
					<div class="flex flex-wrap gap-2">
						<span
							class="inline-block rounded-full px-3 py-1 text-xs font-medium
								{service.status === 'SCHEDULED'
								? 'badge-primary'
								: service.status === 'IN_PROGRESS'
									? 'badge-accent'
									: 'badge-secondary'}"
						>
							{service.status.replace('_', ' ')}
						</span>
						{#if isDispatched}
							<span
								class="inline-block rounded-full bg-emerald-100 px-3 py-1 text-xs font-medium text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400"
							>
								Dispatched
							</span>
						{/if}
					</div>
				</div>

				<!-- Date -->
				<div>
					<p class="detail-label">Date</p>
					<p class="text-theme">{formatDate(service.date)}</p>
				</div>
			</div>

			<!-- Address -->
			{#if address}
				<div class="mt-4 border-t border-theme pt-4">
					<p class="detail-label">Address</p>
					<p class="text-theme">{address}</p>
				</div>
			{/if}

			<!-- Team Members -->
			{#if teamMembers().length > 0}
				<div class="mt-4 border-t border-theme pt-4">
					<div class="mb-2 flex items-center justify-between">
						<p class="detail-label">Team</p>
						{#if messagableMembers.length >= 2}
							<button
								type="button"
								onclick={messageAllTeamMembers}
								class="inline-flex items-center gap-1.5 rounded-lg bg-primary-600 px-3 py-1.5 text-xs font-medium text-white transition-colors hover:bg-primary-700"
							>
								<svg
									class="h-3.5 w-3.5"
									style="fill: none"
									stroke="currentColor"
									viewBox="0 0 24 24"
								>
									<path
										stroke-linecap="round"
										stroke-linejoin="round"
										stroke-width="2"
										d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"
									/>
								</svg>
								Message Team
							</button>
						{/if}
					</div>
					<div class="space-y-2">
						{#each teamMembers() as member (member.id)}
							<div class="flex items-center gap-2">
								<span
									class="inline-flex h-6 w-6 items-center justify-center rounded text-xs font-bold {member.role ===
									'TEAM_LEADER'
										? 'bg-accent-500/20 text-accent-600 dark:text-accent-400'
										: 'bg-secondary-500/20 text-secondary-600 dark:text-secondary-400'}"
								>
									{member.role === 'TEAM_LEADER' ? 'TL' : 'TM'}
								</span>
								{#if member.role !== 'ADMIN'}
									<button
										type="button"
										onclick={() => messageTeamMember(member.id)}
										class="rounded-full p-1 text-theme-muted transition-colors hover:bg-black/5 hover:text-theme dark:hover:bg-white/10"
										aria-label="Message {member.fullName}"
									>
										<svg
											class="h-4 w-4"
											style="fill: none"
											stroke="currentColor"
											viewBox="0 0 24 24"
										>
											<path
												stroke-linecap="round"
												stroke-linejoin="round"
												stroke-width="2"
												d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"
											/>
										</svg>
									</button>
								{:else}
									<!-- Spacer to maintain alignment for admin members -->
									<span class="h-6 w-6"></span>
								{/if}
								<span class="text-theme">{member.fullName}</span>
							</div>
						{/each}
					</div>
				</div>
			{/if}

			<!-- Notes -->
			{#if service.notes}
				<div class="mt-4 border-t border-theme pt-4">
					<p class="detail-label">Notes</p>
					<p class="whitespace-pre-wrap text-theme-secondary">{service.notes}</p>
				</div>
			{/if}
		</div>

		<!-- Scope Info (read-only display) -->
		{#if scope}
			<div class="mb-6 rounded-xl border border-theme bg-theme-card p-6">
				<div class="mb-4 flex items-center justify-between">
					<h2 class="text-lg font-semibold text-theme">Service Scope</h2>
					<a
						href="/admin/accounts/{accountGlobalId}#scope"
						class="text-sm text-primary-500 hover:text-primary-600"
					>
						Manage at Account
					</a>
				</div>
				<div class="space-y-2">
					<div>
						<span class="font-medium text-theme">{scope.name}</span>
						{#if scope.isActive}
							<span
								class="ml-2 rounded bg-purple-100 px-1.5 py-0.5 text-xs font-medium text-purple-700 dark:bg-purple-900/40 dark:text-purple-400"
							>
								Active
							</span>
						{/if}
					</div>
					{#if scope.description}
						<p class="text-sm text-theme-muted">{scope.description}</p>
					{/if}
					<p class="text-xs text-theme-muted">
						{scope.areas?.length ?? 0}
						{(scope.areas?.length ?? 0) === 1 ? 'area' : 'areas'},
						{scope.areas?.reduce((acc, a) => acc + (a.tasks?.length ?? 0), 0) ?? 0} tasks
					</p>
				</div>
			</div>
		{:else}
			<div class="mb-6 warning-box">
				<div class="flex items-start gap-3">
					<svg
						class="warning-box-icon"
						style="fill: none"
						stroke="currentColor"
						viewBox="0 0 24 24"
					>
						<path
							stroke-linecap="round"
							stroke-linejoin="round"
							stroke-width="2"
							d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
						/>
					</svg>
					<div>
						<h3 class="warning-box-title">No Scope Available</h3>
						<p class="warning-box-text">
							This service's address does not have an active scope defined.
							<a
								href="/admin/accounts/{accountGlobalId}#scope"
								class="font-medium underline hover:no-underline"
							>
								Configure scope at the account level.
							</a>
						</p>
					</div>
				</div>
			</div>
		{/if}

		<!-- Session Section -->
		{#if service.status === 'IN_PROGRESS' && session}
			<section>
				<SessionSectionHeader isActive={true} sessionType="service" />
				<SessionContent
					sessionType="service"
					isActive={true}
					{session}
					entityName={displayName}
					scopeName={scope?.name}
					scopeDescription={scope?.description}
					addressInfo={address}
					teamMembers={teamMembers()}
					areas={scope?.areas || []}
					{tasks}
					{selectedTaskIds}
					{completedTaskIds}
					{completedTasksByArea}
					{readyToSubmitByArea}
					{availableTasksCount}
					{isSubmitting}
					{isReverting}
					{submittingTaskId}
					{removingTaskId}
					{getTeamMemberName}
					onClose={handleCloseSession}
					onRevert={canRevertSession ? handleRevertSession : undefined}
					onToggleTask={toggleTask}
					onSubmitTask={handleSubmitTask}
					onRemoveTask={handleRemoveTask}
					onRemoveCompletedTask={handleRemoveCompletedTask}
					onSubmitAllTasks={handleSubmitAllTasks}
					onClearSelection={() => selectedTaskIds.clear()}
					onAddNote={handleAddNote}
					onUpdateNote={handleUpdateNote}
					onDeleteNote={handleDeleteNote}
					onUploadPhoto={handleUploadPhoto}
					onUploadVideo={handleUploadVideo}
					onUpdatePhoto={handleUpdatePhoto}
					onUpdateVideo={handleUpdateVideo}
					onDeletePhoto={handleDeletePhoto}
					onDeleteVideo={handleDeleteVideo}
				/>
			</section>
		{:else if service.status === 'COMPLETED' && session}
			<section>
				<SessionSectionHeader isActive={false} sessionType="service" />
				<SessionContent
					sessionType="service"
					isActive={false}
					{session}
					entityName={displayName}
					scopeName={scope?.name}
					addressInfo={address}
					teamMembers={teamMembers()}
					areas={scope?.areas || []}
					{tasks}
					{selectedTaskIds}
					{completedTaskIds}
					{completedTasksByArea}
					{readyToSubmitByArea}
					{availableTasksCount}
					{getTeamMemberName}
					onAddNote={handleAddNote}
					onUpdateNote={handleUpdateNote}
					onDeleteNote={handleDeleteNote}
					onUploadPhoto={handleUploadPhoto}
					onUpdatePhoto={handleUpdatePhoto}
					onDeletePhoto={handleDeletePhoto}
					onUploadVideo={handleUploadVideo}
					onUpdateVideo={handleUpdateVideo}
					onDeleteVideo={handleDeleteVideo}
				/>
			</section>
		{:else if service.status === 'SCHEDULED'}
			{#if scope && (scope.areas?.length ?? 0) > 0}
				<StartSessionButton
					isLoading={isStartingSession}
					backLabel="Back to Services"
					onStart={handleStartSession}
					onBack={() => goto('/admin/services', { invalidateAll: true })}
				/>
			{:else}
				<div class="flex items-center gap-3">
					<a
						href="/admin/services"
						class="rounded-lg border border-theme interactive bg-theme px-4 py-2 text-sm font-medium text-theme"
					>
						Back to Services
					</a>
				</div>
			{/if}
		{/if}
	</ContentContainer>
</div>
