<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 ExtendedProjectTask,
		type ProjectAreaWithCompletions,
		type ProjectAreaWithTasks
	} from '$lib/components/session';
	import {
		openProjectSession,
		closeProjectSession,
		revertProjectSession,
		addProjectTask,
		removeProjectTask,
		createProjectNote,
		updateProjectNote,
		removeProjectNote,
		uploadProjectPhoto,
		updateProjectPhoto,
		removeProjectPhoto,
		uploadProjectVideo,
		updateProjectVideo,
		removeProjectVideo
	} 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 project = $derived(data.project);
	let session = $derived(data.session);
	let scope = $derived(data.scope);
	let projectUuid = $derived(data.projectUuid); // UUID for session and task mutations
	let accountLookup = $derived(data.accountLookup);
	let customerLookup = $derived(data.customerLookup);
	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 project
	let isAssignedToProject = $derived(() => {
		if (!currentUserProfileId || !project.teamMembers) return false;
		const currentUserUuid = fromGlobalId(currentUserProfileId);
		return project.teamMembers.some((m) => m.pk === currentUserUuid);
	});

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

	// Account or customer info
	let accountInfo = $derived(
		project.accountAddressId ? (accountLookup.get(project.accountAddressId) ?? null) : null
	);
	let customerInfo = $derived(
		project.customerId ? (customerLookup.get(project.customerId) ?? null) : null
	);

	// Display name (account or customer)
	let displayName = $derived(
		accountInfo?.accountName ?? customerInfo?.customerName ?? 'Project Details'
	);

	// Address - from account or direct project fields
	let address = $derived(() => {
		if (accountInfo) {
			return formatAddress(accountInfo);
		}
		return formatAddress({
			streetAddress: project.streetAddress,
			city: project.city,
			state: project.state,
			zipCode: project.zipCode
		});
	});

	// Team members (non-admin only)
	let teamMembers = $derived(() => {
		if (!project.teamMembers) return [];
		return project.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 (projects use projectAreas and projectTasks)
	let tasks = $derived<ExtendedProjectTask[]>(
		scope?.projectAreas?.flatMap(
			(area) =>
				area.projectTasks?.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((): ProjectAreaWithCompletions[] => {
		if (!session?.completedTasks || !scope?.projectAreas) return [];
		const areaMap = new SvelteMap<string, ProjectAreaWithCompletions>();
		scope.projectAreas.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((): ProjectAreaWithTasks[] => {
		if (!scope?.projectAreas) return [];
		const areaMap = new SvelteMap<string, ProjectAreaWithTasks>();
		scope.projectAreas.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 openProjectSession({ projectId: projectUuid });
			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) =>
					addProjectTask(projectUuid, taskUuid)
				);
				await Promise.all(promises);
				selectedTaskIds.clear();
			}
			await closeProjectSession({ projectId: projectUuid });
			await goto('/team/projects', { 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 revertProjectSession(projectUuid);
			await goto('/team/projects', { 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 addProjectTask(projectUuid, 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 removeProjectTask(projectUuid, 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) =>
				addProjectTask(projectUuid, 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 createProjectNote({
			sessionId: session.id,
			content,
			internal,
			authorId: currentUserProfileId
		});
		await invalidateAll();
	}

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

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

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

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

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

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

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

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

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

<div class="py-8">
	<ContentContainer>
		<TeamPageHeader
			title={displayName}
			subtitle={project.name}
			colorScheme="accent"
			backHref="/team/projects"
			invalidateOnBack={true}
		/>

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

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