<script lang="ts">
	import type { PageData } from './$types';
	import { goto, invalidateAll } from '$app/navigation';
	import { SvelteSet } from 'svelte/reactivity';
	import { client } from '$lib/graphql/client';
	import { ContentContainer } from '$lib/components/layout';
	import { PageHeader } from '$lib/components/admin';
	import {
		SessionContent,
		StartSessionButton,
		type ExtendedServiceTask,
		type ServiceArea,
		type ServiceAreaWithCompletions,
		type ServiceAreaWithTasks
	} from '$lib/components/session';
	import {
		OPEN_SERVICE_SESSION,
		CLOSE_SERVICE_SESSION,
		REVERT_SERVICE_SESSION,
		ADD_SERVICE_TASK_COMPLETION,
		REMOVE_SERVICE_TASK_COMPLETION,
		CREATE_SERVICE_SESSION_NOTE,
		UPDATE_SERVICE_SESSION_NOTE,
		DELETE_SERVICE_SESSION_NOTE,
		UPLOAD_SERVICE_SESSION_IMAGE,
		UPDATE_SERVICE_SESSION_IMAGE,
		DELETE_SERVICE_SESSION_IMAGE,
		UPLOAD_SERVICE_SESSION_VIDEO,
		UPDATE_SERVICE_SESSION_VIDEO,
		DELETE_SERVICE_SESSION_VIDEO
	} from '$lib/graphql/mutations/session';
	import type { WorkStatus } from '$lib/graphql/queries/services';
	import type { ServiceSession } from '$lib/graphql/queries/session';
	import { config } from '$lib/config';

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

	let service = $derived(data.service);

	// Get the dispatch assignment
	let dispatchAssignment = $derived(
		service.teamMembers.find((m) => m.teamProfileId === config.dispatch.profileId) ?? null
	);

	// Filter out dispatch from team members display
	let teamMembers = $derived(
		service.teamMembers.filter((m) => m.teamProfileId !== config.dispatch.profileId)
	);

	let isDispatched = $derived(!!dispatchAssignment);

	function getStatusBadgeClass(status: WorkStatus): string {
		switch (status) {
			case 'SCHEDULED':
				return 'bg-accent2-100 text-accent2-800 dark:bg-accent2-900/30 dark:text-accent2-400';
			case 'IN_PROGRESS':
				return 'bg-accent-100 text-accent-800 dark:bg-accent-900/30 dark:text-accent-400';
			case 'COMPLETED':
				return 'bg-primary-100 text-primary-800 dark:bg-primary-900/30 dark:text-primary-400';
			case 'CANCELLED':
				return 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400';
			default:
				return 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300';
		}
	}

	function formatStatusLabel(status: WorkStatus): string {
		switch (status) {
			case 'IN_PROGRESS':
				return 'In Progress';
			default:
				return status.charAt(0) + status.slice(1).toLowerCase();
		}
	}

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

	function formatAddress(address: {
		streetAddress: string;
		city: string;
		state: string;
		zipCode: string;
	}): string {
		return `${address.streetAddress}, ${address.city}, ${address.state} ${address.zipCode}`;
	}

	// Get month from service date for back navigation
	let backMonth = $derived(() => {
		const [year, month] = service.date.split('-');
		return `${year}-${month}`;
	});

	// ==================== SESSION STATE ====================

	let session = $derived(data.session as ServiceSession | null);
	let scope = $derived(service.accountAddress?.activeScope ?? null);

	// Session loading states
	let sessionLoading = $state(false);
	let isClosingSession = $state(false);
	let isRevertingSession = $state(false);
	let submittingTaskId = $state<string | null>(null);
	let removingTaskId = $state<string | null>(null);

	// Convert scope areas to session format
	const sessionAreas = $derived.by<ServiceArea[]>(() => {
		if (!scope) return [];
		return scope.areas.map((area) => ({
			id: area.id,
			name: area.name,
			description: null,
			order: area.order,
			tasks: area.tasks
		}));
	});

	// Flatten tasks with area context
	const allTasks = $derived.by<ExtendedServiceTask[]>(() => {
		if (!scope) return [];
		return scope.areas.flatMap((area) =>
			area.tasks.map((task) => ({
				...task,
				uuid: task.id,
				areaId: area.id,
				areaName: area.name
			}))
		);
	});

	// Task selection state
	let selectedTaskIds = $state(new SvelteSet<string>());
	const completedTaskIds = $derived.by(() => {
		const ids = new SvelteSet<string>();
		if (session) {
			for (const completion of session.completedTasks) {
				ids.add(completion.taskId);
			}
		}
		return ids;
	});

	// Group completed tasks by area
	const completedTasksByArea = $derived.by<ServiceAreaWithCompletions[]>(() => {
		if (!session || !scope) return [];
		const grouped = new Map<string, ServiceAreaWithCompletions>();

		for (const completion of session.completedTasks) {
			const task = allTasks.find((t) => t.id === completion.taskId);
			if (!task) continue;

			const area = scope.areas.find((a) => a.id === task.areaId);
			if (!area) continue;

			if (!grouped.has(area.id)) {
				grouped.set(area.id, {
					area: {
						id: area.id,
						name: area.name,
						description: null,
						order: area.order,
						tasks: area.tasks
					},
					completions: []
				});
			}
			grouped.get(area.id)!.completions.push(completion);
		}

		return Array.from(grouped.values()).sort((a, b) => a.area.order - b.area.order);
	});

	// Group selected tasks by area
	const readyToSubmitByArea = $derived.by<ServiceAreaWithTasks[]>(() => {
		const grouped = new Map<string, ServiceAreaWithTasks>();

		for (const taskId of selectedTaskIds) {
			const task = allTasks.find((t) => t.id === taskId);
			if (!task) continue;

			const area = scope?.areas.find((a) => a.id === task.areaId);
			if (!area) continue;

			if (!grouped.has(area.id)) {
				grouped.set(area.id, {
					area: {
						id: area.id,
						name: area.name,
						description: null,
						order: area.order,
						tasks: area.tasks
					},
					tasks: []
				});
			}
			grouped.get(area.id)!.tasks.push(task);
		}

		return Array.from(grouped.values()).sort((a, b) => a.area.order - b.area.order);
	});

	const availableTasksCount = $derived(
		allTasks.filter((t) => !selectedTaskIds.has(t.id) && !completedTaskIds.has(t.id)).length
	);

	// Can start session when service is SCHEDULED and dispatched
	const canStartSession = $derived(service.status === 'SCHEDULED' && isDispatched && !session);

	function getTeamMemberName(id: string | null | undefined): string {
		if (!id) return 'Unknown';
		const profile = data.teamProfiles?.find((p) => p.id === id);
		return profile?.fullName ?? 'Unknown';
	}

	// ==================== SESSION HANDLERS ====================

	async function handleStartSession() {
		sessionLoading = true;
		try {
			await client.mutate({
				mutation: OPEN_SERVICE_SESSION,
				variables: { input: { serviceId: service.id } }
			});
			await invalidateAll();
		} catch (err) {
			console.error('Failed to start session:', err);
		} finally {
			sessionLoading = false;
		}
	}

	async function handleCloseSession() {
		if (!session) return;
		isClosingSession = true;
		try {
			const taskIds = Array.from(completedTaskIds);
			await client.mutate({
				mutation: CLOSE_SERVICE_SESSION,
				variables: { input: { serviceId: service.id, taskIds } }
			});
			await invalidateAll();
		} catch (err) {
			console.error('Failed to close session:', err);
		} finally {
			isClosingSession = false;
		}
	}

	async function handleRevertSession() {
		isRevertingSession = true;
		try {
			await client.mutate({
				mutation: REVERT_SERVICE_SESSION,
				variables: { serviceId: service.id }
			});
			await invalidateAll();
		} catch (err) {
			console.error('Failed to revert session:', err);
		} finally {
			isRevertingSession = false;
		}
	}

	function handleToggleTask(taskId: string) {
		if (selectedTaskIds.has(taskId)) {
			selectedTaskIds.delete(taskId);
		} else {
			selectedTaskIds.add(taskId);
		}
	}

	async function handleSubmitTask(taskId: string) {
		submittingTaskId = taskId;
		try {
			await client.mutate({
				mutation: ADD_SERVICE_TASK_COMPLETION,
				variables: { serviceId: service.id, taskId }
			});
			selectedTaskIds.delete(taskId);
			await invalidateAll();
		} catch (err) {
			console.error('Failed to submit task:', err);
		} finally {
			submittingTaskId = null;
		}
	}

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

	async function handleRemoveCompletedTask(taskId: string) {
		removingTaskId = taskId;
		try {
			await client.mutate({
				mutation: REMOVE_SERVICE_TASK_COMPLETION,
				variables: { serviceId: service.id, taskId }
			});
			await invalidateAll();
		} catch (err) {
			console.error('Failed to remove task completion:', err);
		} finally {
			removingTaskId = null;
		}
	}

	async function handleSubmitAllTasks() {
		for (const taskId of selectedTaskIds) {
			await handleSubmitTask(taskId);
		}
	}

	function handleClearSelection() {
		selectedTaskIds.clear();
	}

	// Note handlers
	async function handleAddNote(content: string, internal: boolean) {
		if (!session) return;
		await client.mutate({
			mutation: CREATE_SERVICE_SESSION_NOTE,
			variables: { input: { sessionId: session.id, content, internal } }
		});
		await invalidateAll();
	}

	async function handleUpdateNote(noteId: string, content: string, internal: boolean) {
		await client.mutate({
			mutation: UPDATE_SERVICE_SESSION_NOTE,
			variables: { id: noteId, input: { content, internal } }
		});
		await invalidateAll();
	}

	async function handleDeleteNote(noteId: string) {
		await client.mutate({
			mutation: DELETE_SERVICE_SESSION_NOTE,
			variables: { id: noteId }
		});
		await invalidateAll();
	}

	// Media handlers
	async function handleUploadPhoto(file: File, title: string, notes: string, internal: boolean) {
		if (!session) return;
		await client.mutate({
			mutation: UPLOAD_SERVICE_SESSION_IMAGE,
			variables: {
				sessionId: session.id,
				file,
				title: title || null,
				notes: notes || null,
				internal
			}
		});
		await invalidateAll();
	}

	async function handleUploadVideo(file: File, title: string, notes: string, internal: boolean) {
		if (!session) return;
		await client.mutate({
			mutation: UPLOAD_SERVICE_SESSION_VIDEO,
			variables: {
				sessionId: session.id,
				file,
				title: title || null,
				notes: notes || null,
				internal
			}
		});
		await invalidateAll();
	}

	async function handleUpdatePhoto(
		photoId: string,
		title: string,
		notes: string,
		internal: boolean
	) {
		await client.mutate({
			mutation: UPDATE_SERVICE_SESSION_IMAGE,
			variables: { id: photoId, input: { title: title || null, notes: notes || null, internal } }
		});
		await invalidateAll();
	}

	async function handleUpdateVideo(
		videoId: string,
		title: string,
		notes: string,
		internal: boolean
	) {
		await client.mutate({
			mutation: UPDATE_SERVICE_SESSION_VIDEO,
			variables: { id: videoId, input: { title: title || null, notes: notes || null, internal } }
		});
		await invalidateAll();
	}

	async function handleDeletePhoto(photoId: string) {
		await client.mutate({
			mutation: DELETE_SERVICE_SESSION_IMAGE,
			variables: { id: photoId }
		});
		await invalidateAll();
	}

	async function handleDeleteVideo(videoId: string) {
		await client.mutate({
			mutation: DELETE_SERVICE_SESSION_VIDEO,
			variables: { id: videoId }
		});
		await invalidateAll();
	}

	function handleMessageTeam() {
		if (teamMembers.length === 0) return;

		const participants = teamMembers.map((m) => m.teamProfileId).join(',');
		const subject = encodeURIComponent(
			`Service: ${service.account?.name ?? 'Unknown'} - ${formatDate(service.date)}`
		);

		goto(
			`/messages/new?subject=${subject}&entityType=service&entityId=${service.id}&participants=${participants}`
		);
	}
</script>

<svelte:head>
	<title>Service - {service.account?.name ?? 'Unknown'} - Nexus</title>
</svelte:head>

<div class="py-8">
	<ContentContainer>
		<PageHeader
			title={service.account?.name ?? 'Unknown Account'}
			subtitle={service.account?.customer?.name ?? undefined}
			backHref="/team/services?month={backMonth()}"
			colorScheme="secondary"
		>
			<div class="flex flex-wrap items-center gap-2">
				<span
					class="inline-flex rounded-full px-2 py-0.5 text-xs font-semibold {getStatusBadgeClass(
						service.status
					)}"
				>
					{formatStatusLabel(service.status)}
				</span>
				<span class="text-sm text-theme-secondary">{formatDate(service.date)}</span>
			</div>
		</PageHeader>

		<div class="space-y-6">
			<!-- Service Details Section -->
			<section
				class="overflow-hidden rounded-xl border border-secondary-500/20 bg-theme-card shadow-theme-md"
			>
				<div class="section-header-secondary px-6 py-4">
					<h2 class="text-lg font-semibold text-theme">Service Details</h2>
				</div>
				<div class="grid grid-cols-1 gap-4 p-6 sm:grid-cols-2">
					<div>
						<dt class="text-sm font-medium text-theme-secondary">Date</dt>
						<dd class="mt-1 text-theme">{formatDate(service.date)}</dd>
					</div>
					<div>
						<dt class="text-sm font-medium text-theme-secondary">Status</dt>
						<dd class="mt-1">
							<span
								class="inline-flex rounded-full px-2 py-0.5 text-xs font-semibold {getStatusBadgeClass(
									service.status
								)}"
							>
								{formatStatusLabel(service.status)}
							</span>
						</dd>
					</div>
					<div>
						<dt class="text-sm font-medium text-theme-secondary">Account</dt>
						<dd class="mt-1 text-theme">{service.account?.name ?? 'Unknown'}</dd>
					</div>
					{#if service.account?.customer}
						<div>
							<dt class="text-sm font-medium text-theme-secondary">Customer</dt>
							<dd class="mt-1 text-theme">{service.account.customer.name}</dd>
						</div>
					{/if}
					{#if service.accountAddress}
						<div class="sm:col-span-2">
							<dt class="text-sm font-medium text-theme-secondary">Location</dt>
							<dd class="mt-1 text-theme">
								{#if service.accountAddress.name}
									{service.accountAddress.name} -
								{/if}
								{formatAddress(service.accountAddress)}
							</dd>
						</div>
					{/if}
				</div>
			</section>

			<!-- Service Notes Section -->
			{#if service.notes}
				<section
					class="overflow-hidden rounded-xl border border-secondary-500/20 bg-theme-card shadow-theme-md"
				>
					<div class="section-header-secondary px-6 py-4">
						<h2 class="text-lg font-semibold text-theme">Service Notes</h2>
					</div>
					<div class="p-6">
						<p class="whitespace-pre-wrap text-theme">{service.notes}</p>
					</div>
				</section>
			{/if}

			<!-- Team Members Section -->
			<section
				class="overflow-hidden rounded-xl border border-secondary-500/20 bg-theme-card shadow-theme-md"
			>
				<div class="section-header-secondary px-6 py-4">
					<div class="flex items-center justify-between">
						<h2 class="text-lg font-semibold text-theme">Team Members</h2>
						{#if teamMembers.length > 0}
							<button
								type="button"
								onclick={handleMessageTeam}
								class="flex items-center gap-1 text-sm font-medium text-accent-600 hover:text-accent-700 dark:text-accent-400 dark:hover:text-accent-300"
							>
								<svg class="h-4 w-4" 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>
								Message Team
							</button>
						{/if}
					</div>
				</div>
				{#if teamMembers.length > 0}
					<div class="p-6">
						<ul class="divide-theme divide-y">
							{#each teamMembers as member}
								<li class="py-3">
									<div class="flex items-center gap-3">
										<div
											class="flex h-8 w-8 items-center justify-center rounded-full bg-secondary-100 text-secondary-600 dark:bg-secondary-900/30 dark:text-secondary-400"
										>
											<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
												<path
													stroke-linecap="round"
													stroke-linejoin="round"
													stroke-width="2"
													d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
												/>
											</svg>
										</div>
										<div>
											<p class="text-sm font-medium text-theme">
												{member.teamProfile?.fullName ?? 'Unknown'}
											</p>
											{#if member.teamProfile?.role}
												<p class="text-xs text-theme-muted">
													{member.teamProfile.role === 'TEAM_LEADER'
														? 'Team Leader'
														: 'Team Member'}
												</p>
											{/if}
										</div>
									</div>
								</li>
							{/each}
						</ul>
					</div>
				{:else}
					<p class="p-6 text-sm text-theme-muted">No team members assigned yet.</p>
				{/if}
			</section>

			<!-- Work Session Section -->
			<section
				class="overflow-hidden rounded-xl border border-secondary-500/20 bg-theme-card shadow-theme-md"
			>
				<div class="section-header-secondary px-6 py-4">
					<h2 class="text-lg font-semibold text-theme">Work Session</h2>
				</div>
				<div class="p-6">
					{#if session}
						<SessionContent
							sessionType="service"
							isActive={session.isActive}
							session={{
								isActive: session.isActive,
								start: session.start,
								end: session.end,
								durationSeconds: session.durationSeconds,
								images: session.images,
								videos: session.videos,
								notes: session.notes,
								completedTasks: session.completedTasks,
								createdBy: session.createdBy,
								closedBy: session.closedBy
							}}
							entityName={service.account?.name ?? 'Service'}
							scopeName={scope?.name}
							scopeDescription={scope?.description}
							addressInfo={service.accountAddress
								? `${service.accountAddress.streetAddress}, ${service.accountAddress.city}`
								: null}
							teamMembers={data.teamProfiles?.map((p) => ({ id: p.id, fullName: p.fullName })) ??
								[]}
							areas={sessionAreas}
							tasks={allTasks}
							{selectedTaskIds}
							{completedTaskIds}
							{completedTasksByArea}
							{readyToSubmitByArea}
							{availableTasksCount}
							isSubmitting={isClosingSession}
							isReverting={isRevertingSession}
							{submittingTaskId}
							{removingTaskId}
							onClose={handleCloseSession}
							onRevert={handleRevertSession}
							onToggleTask={handleToggleTask}
							onSubmitTask={handleSubmitTask}
							onRemoveTask={handleRemoveTask}
							onRemoveCompletedTask={handleRemoveCompletedTask}
							onSubmitAllTasks={handleSubmitAllTasks}
							onClearSelection={handleClearSelection}
							onAddNote={handleAddNote}
							onUpdateNote={handleUpdateNote}
							onDeleteNote={handleDeleteNote}
							onUploadPhoto={handleUploadPhoto}
							onUploadVideo={handleUploadVideo}
							onUpdatePhoto={handleUpdatePhoto}
							onUpdateVideo={handleUpdateVideo}
							onDeletePhoto={handleDeletePhoto}
							onDeleteVideo={handleDeleteVideo}
							{getTeamMemberName}
						/>
					{:else if canStartSession}
						<div class="flex flex-col items-center gap-4 py-8">
							<p class="text-sm text-theme-muted">
								Start a work session to track time, complete tasks, and capture notes/photos.
							</p>
							<StartSessionButton
								sessionType="service"
								isLoading={sessionLoading}
								onStart={handleStartSession}
							/>
						</div>
					{:else if service.status === 'IN_PROGRESS'}
						<p class="text-sm text-theme-muted">
							This service has an active session but it was not loaded. Try refreshing the page.
						</p>
					{:else if service.status === 'COMPLETED'}
						<p class="text-sm text-theme-muted">This service has been completed.</p>
					{:else if !isDispatched}
						<p class="text-sm text-theme-muted">This service has not been dispatched yet.</p>
					{:else if !scope}
						<p class="text-sm text-theme-muted">No active scope found for this location.</p>
					{:else}
						<p class="text-sm text-theme-muted">
							Work session is not available for this service status.
						</p>
					{/if}
				</div>
			</section>
		</div>
	</ContentContainer>
</div>
