<script lang="ts">
	import ContentContainer from '$lib/components/layout/ContentContainer.svelte';
	import TeamPageHeader from '$lib/components/team/TeamPageHeader.svelte';
	import { EntityDetailsCard } from '$lib/components/entity';
	import {
		SessionSectionHeader,
		SessionContent,
		StartSessionButton,
		type ExtendedServiceTask,
		type ServiceAreaWithCompletions,
		type ServiceAreaWithTasks
	} from '$lib/components/session';
	import {
		openServiceSession,
		closeServiceSession,
		revertServiceSession,
		addServiceTask,
		removeServiceTask,
		createServiceNote,
		updateServiceNote,
		removeServiceNote,
		uploadServicePhoto,
		updateServicePhoto,
		removeServicePhoto,
		uploadServiceVideo,
		updateServiceVideo,
		removeServiceVideo
	} from '$lib/utils/session';
	import type { PageData } from './$types';
	import { formatAddress } from '$lib/utils/lookup';
	import { fromGlobalId } 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);

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

	// Check if current user is assigned to this service
	let isAssignedToService = $derived(() => {
		if (!currentUserProfileId || !service.teamMembers) return false;
		const currentUserUuid = fromGlobalId(currentUserProfileId);
		return service.teamMembers.some((m) => m.pk === currentUserUuid);
	});

	// Role-based permissions - must be admin/team leader AND assigned to the service
	let canRevertSession = $derived(() => {
		const me = data.user?.data?.me;
		if (me?.__typename === 'TeamProfileType') {
			const hasRole = me.role === 'ADMIN' || me.role === 'TEAM_LEADER';
			return hasRole && isAssignedToService();
		}
		return false;
	});

	// Account info
	let accountInfo = $derived(
		service.accountAddressId ? (accountLookup.get(service.accountAddressId) ?? null) : null
	);
	let address = $derived(accountInfo ? formatAddress(accountInfo) : 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);
	});

	// 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';
	}

	// 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('/team/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('/team/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>

<svelte:head>
	<title>{accountInfo?.accountName ?? 'Service'} - Services - Nexus</title>
</svelte:head>

<div class="py-8">
	<ContentContainer>
		<TeamPageHeader
			title={accountInfo?.accountName ?? 'Service Details'}
			subtitle={accountInfo?.addressName ?? 'View service information and log your work.'}
			colorScheme="secondary"
			backHref="/team/services"
			invalidateOnBack={true}
		/>

		<EntityDetailsCard
			entityType="service"
			entityId={service.id}
			status={service.status}
			date={service.date}
			{address}
			teamMembers={teamMembers()}
			notes={service.notes}
			{accountInfo}
		/>

		{#if service.status === 'IN_PROGRESS' && session}
			<section>
				<SessionSectionHeader isActive={true} sessionType="service" />
				<SessionContent
					sessionType="service"
					isActive={true}
					{session}
					entityName={accountInfo?.accountName ?? 'Service'}
					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={accountInfo?.accountName ?? 'Service'}
					scopeName={scope?.name}
					addressInfo={address}
					teamMembers={teamMembers()}
					areas={scope?.areas || []}
					{tasks}
					{selectedTaskIds}
					{completedTaskIds}
					{completedTasksByArea}
					{readyToSubmitByArea}
					{availableTasksCount}
					{getTeamMemberName}
				/>
			</section>
		{:else if service.status === 'SCHEDULED'}
			<StartSessionButton
				isLoading={isStartingSession}
				backLabel="Back to Services"
				onStart={handleStartSession}
				onBack={() => goto('/team/services', { invalidateAll: true })}
			/>
		{/if}
	</ContentContainer>
</div>
