<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 ExtendedProjectTask,
		type ProjectArea,
		type ProjectAreaWithCompletions,
		type ProjectAreaWithTasks
	} from '$lib/components/session';
	import {
		OPEN_PROJECT_SESSION,
		CLOSE_PROJECT_SESSION,
		REVERT_PROJECT_SESSION,
		ADD_PROJECT_TASK_COMPLETION,
		REMOVE_PROJECT_TASK_COMPLETION,
		CREATE_PROJECT_SESSION_NOTE,
		UPDATE_PROJECT_SESSION_NOTE,
		DELETE_PROJECT_SESSION_NOTE,
		UPLOAD_PROJECT_SESSION_IMAGE,
		UPDATE_PROJECT_SESSION_IMAGE,
		DELETE_PROJECT_SESSION_IMAGE,
		UPLOAD_PROJECT_SESSION_VIDEO,
		UPDATE_PROJECT_SESSION_VIDEO,
		DELETE_PROJECT_SESSION_VIDEO
	} from '$lib/graphql/mutations/session';
	import type { WorkStatus } from '$lib/graphql/queries/projects';
	import type { ProjectSession } from '$lib/graphql/queries/session';
	import { config } from '$lib/config';

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

	let project = $derived(data.project);

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

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

	let isDispatched = $derived(!!dispatchAssignment);

	// Get active scope
	let activeScope = $derived(project.scopes?.find((s) => s.isActive) ?? null);

	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 {
		if (address.streetAddress && address.zipCode) {
			return `${address.streetAddress}, ${address.city}, ${address.state} ${address.zipCode}`;
		}
		return `${address.city}, ${address.state}`;
	}

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

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

	let session = $derived(data.session as ProjectSession | 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 categories to session areas format
	const sessionAreas = $derived.by<ProjectArea[]>(() => {
		if (!activeScope) return [];
		return activeScope.categories.map((cat) => ({
			id: cat.id,
			name: cat.name,
			description: null,
			order: cat.order,
			tasks: cat.tasks
		}));
	});

	// Flatten tasks with area context
	const allTasks = $derived.by<ExtendedProjectTask[]>(() => {
		if (!activeScope) return [];
		return activeScope.categories.flatMap((cat) =>
			cat.tasks.map((task) => ({
				...task,
				uuid: task.id,
				areaId: cat.id,
				areaName: cat.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<ProjectAreaWithCompletions[]>(() => {
		if (!session || !activeScope) return [];
		const grouped = new Map<string, ProjectAreaWithCompletions>();

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

			const cat = activeScope.categories.find((c) => c.id === task.areaId);
			if (!cat) continue;

			if (!grouped.has(cat.id)) {
				grouped.set(cat.id, {
					area: {
						id: cat.id,
						name: cat.name,
						description: null,
						order: cat.order,
						tasks: cat.tasks
					},
					completions: []
				});
			}
			grouped.get(cat.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<ProjectAreaWithTasks[]>(() => {
		const grouped = new Map<string, ProjectAreaWithTasks>();

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

			const cat = activeScope?.categories.find((c) => c.id === task.areaId);
			if (!cat) continue;

			if (!grouped.has(cat.id)) {
				grouped.set(cat.id, {
					area: {
						id: cat.id,
						name: cat.name,
						description: null,
						order: cat.order,
						tasks: cat.tasks
					},
					tasks: []
				});
			}
			grouped.get(cat.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 project is SCHEDULED and dispatched
	const canStartSession = $derived(project.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_PROJECT_SESSION,
				variables: { input: { projectId: project.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_PROJECT_SESSION,
				variables: { input: { projectId: project.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_PROJECT_SESSION,
				variables: { projectId: project.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_PROJECT_TASK_COMPLETION,
				variables: { projectId: project.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_PROJECT_TASK_COMPLETION,
				variables: { projectId: project.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_PROJECT_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_PROJECT_SESSION_NOTE,
			variables: { id: noteId, input: { content, internal } }
		});
		await invalidateAll();
	}

	async function handleDeleteNote(noteId: string) {
		await client.mutate({
			mutation: DELETE_PROJECT_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_PROJECT_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_PROJECT_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_PROJECT_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_PROJECT_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_PROJECT_SESSION_IMAGE,
			variables: { id: photoId }
		});
		await invalidateAll();
	}

	async function handleDeleteVideo(videoId: string) {
		await client.mutate({
			mutation: DELETE_PROJECT_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(`Project: ${project.name} - ${formatDate(project.date)}`);

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

<svelte:head>
	<title>Project - {project.name} - Nexus</title>
</svelte:head>

<div class="py-8">
	<ContentContainer>
		<PageHeader
			title={project.name}
			subtitle={project.customer?.name ?? undefined}
			backHref="/team/projects?month={backMonth()}"
			colorScheme="accent"
		>
			<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(
						project.status
					)}"
				>
					{formatStatusLabel(project.status)}
				</span>
				<span class="text-sm text-theme-secondary">{formatDate(project.date)}</span>
			</div>
		</PageHeader>

		<div class="space-y-6">
			<!-- Project Details Section -->
			<section
				class="overflow-hidden rounded-xl border border-accent-500/20 bg-theme-card shadow-theme-md"
			>
				<div class="section-header-accent px-6 py-4">
					<h2 class="text-lg font-semibold text-theme">Project 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(project.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(
									project.status
								)}"
							>
								{formatStatusLabel(project.status)}
							</span>
						</dd>
					</div>
					{#if project.customer}
						<div>
							<dt class="text-sm font-medium text-theme-secondary">Customer</dt>
							<dd class="mt-1 text-theme">{project.customer.name}</dd>
						</div>
					{/if}
					{#if project.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 project.accountAddress.name}
									{project.accountAddress.name} -
								{/if}
								{formatAddress(project.accountAddress)}
							</dd>
						</div>
					{/if}
				</div>
			</section>

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

			<!-- Team Members Section -->
			<section
				class="overflow-hidden rounded-xl border border-accent-500/20 bg-theme-card shadow-theme-md"
			>
				<div class="section-header-accent 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-accent-100 text-accent-600 dark:bg-accent-900/30 dark:text-accent-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-accent-500/20 bg-theme-card shadow-theme-md"
			>
				<div class="section-header-accent px-6 py-4">
					<h2 class="text-lg font-semibold text-theme">Work Session</h2>
				</div>
				<div class="p-6">
					{#if session}
						<SessionContent
							sessionType="project"
							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={project.name}
							scopeName={activeScope?.name}
							scopeDescription={activeScope?.description}
							addressInfo={project.accountAddress
								? `${project.accountAddress.city}, ${project.accountAddress.state}`
								: 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="project"
								isLoading={sessionLoading}
								onStart={handleStartSession}
							/>
						</div>
					{:else if project.status === 'IN_PROGRESS'}
						<p class="text-sm text-theme-muted">
							This project has an active session but it was not loaded. Try refreshing the page.
						</p>
					{:else if project.status === 'COMPLETED'}
						<p class="text-sm text-theme-muted">This project has been completed.</p>
					{:else if !isDispatched}
						<p class="text-sm text-theme-muted">This project has not been dispatched yet.</p>
					{:else if !activeScope}
						<p class="text-sm text-theme-muted">No active scope found for this project.</p>
					{:else}
						<p class="text-sm text-theme-muted">
							Work session is not available for this project status.
						</p>
					{/if}
				</div>
			</section>
		</div>
	</ContentContainer>
</div>
