<script lang="ts">
	import { onMount } from 'svelte';
	import PageHeader from '$lib/components/layout/PageHeader.svelte';
	import FilterBar from '$lib/components/common/FilterBar.svelte';
	import LoadingState from '$lib/components/common/LoadingState.svelte';
	import EmptyState from '$lib/components/common/EmptyState.svelte';
	import { Plus, X, AlertCircle, ChevronLeft, ChevronRight, Trash2 } from 'lucide-svelte';
	import { 
		allocationService, 
		type Allocation,
		type CreateAllocationRequest 
	} from '$lib/services/allocationService';
	import { projectService, type Project } from '$lib/services/projectService';
	import { teamMemberService, type TeamMember } from '$lib/services/teamMemberService';
	import { selectedPeriod, previousMonth, nextMonth, setPeriod } from '$lib/stores/period';

	// State
	let allocations = $state<Allocation[]>([]);
	let projects = $state<Project[]>([]);
	let teamMembers = $state<TeamMember[]>([]);
	let loading = $state(true);
	let error = $state<string | null>(null);
	
	// Month navigation
	let currentPeriod = $state('2026-02');
	
	// Modal state
	let showModal = $state(false);
	let editingAllocation = $state<Allocation | null>(null);
	let formLoading = $state(false);
	let formError = $state<string | null>(null);
	
	// Form state
	let formData = $state<CreateAllocationRequest>({
		project_id: '',
		team_member_id: '',
		month: currentPeriod,
		allocated_hours: 0
	});

	// Subscribe to period store - only on client
	let unsubscribe: (() => void) | null = null;
	
	onMount(() => {
		unsubscribe = selectedPeriod.subscribe(value => {
			currentPeriod = value;
			loadAllocations();
		});
		
		return () => {
			if (unsubscribe) unsubscribe();
		};
	});

	onMount(async () => {
		await Promise.all([loadProjects(), loadTeamMembers(), loadAllocations()]);
	});

	async function loadProjects() {
		try {
			projects = await projectService.getAll();
		} catch (err) {
			console.error('Error loading projects:', err);
		}
	}

	async function loadTeamMembers() {
		try {
			teamMembers = await teamMemberService.getAll(true);
		} catch (err) {
			console.error('Error loading team members:', err);
		}
	}

	async function loadAllocations() {
		try {
			loading = true;
			error = null;
			const response = await allocationService.getAll(currentPeriod) as Allocation[];
			allocations = response;
		} catch (err) {
			error = err instanceof Error ? err.message : 'Failed to load allocations';
			console.error('Error loading allocations:', err);
		} finally {
			loading = false;
		}
	}

	function getAllocation(projectId: string, teamMemberId: string | null): Allocation | undefined {
		return allocations.find(a => a.project_id === projectId && a.team_member_id === teamMemberId);
	}

	function getProjectRowTotal(projectId: string): number {
		return allocations
			.filter(a => a.project_id === projectId)
			.reduce((sum, a) => sum + parseFloat(a.allocated_hours), 0);
	}

	/**
	 * Get row variance for a project.
	 * Uses the first allocation's row_variance data (all allocations for same project have same row variance)
	 */
	function getProjectRowVariance(projectId: string) {
		const projectAllocations = allocations.filter(a => a.project_id === projectId);
		if (projectAllocations.length === 0) return null;
		return projectAllocations[0].row_variance ?? null;
	}

	function getTeamMemberColumnTotal(teamMemberId: string): number {
		return allocations
			.filter(a => a.team_member_id === teamMemberId)
			.reduce((sum, a) => sum + parseFloat(a.allocated_hours), 0);
	}

	/**
	 * Get column variance for a team member.
	 */
	function getTeamMemberColumnVariance(teamMemberId: string) {
		const memberAllocations = allocations.filter(a => a.team_member_id === teamMemberId);
		if (memberAllocations.length === 0) return null;
		return memberAllocations[0].column_variance || null;
	}

	function getProjectTotal(): number {
		return allocations.reduce((sum, a) => sum + parseFloat(a.allocated_hours), 0);
	}

	/**
	 * Get row variance status for a project (OVER/UNDER/MATCH)
	 * Uses red/amber/neutral per design
	 */
	function getProjectRowStatus(projectId: string): 'OVER' | 'UNDER' | 'MATCH' | null {
		const variance = getProjectRowVariance(projectId);
		return variance?.status || null;
	}

	/**
	 * Get column variance status for a team member
	 */
	function getTeamMemberColumnStatus(teamMemberId: string): 'OVER' | 'UNDER' | 'MATCH' | null {
		const variance = getTeamMemberColumnVariance(teamMemberId);
		return variance?.status || null;
	}

	/**
	 * Format status badge class - red/amber/neutral per design
	 */
	function getStatusBadgeClass(status: string | null): string {
		switch (status) {
			case 'OVER': return 'badge-error';
			case 'UNDER': return 'badge-warning';
			case 'MATCH': return 'badge-neutral';
			default: return 'badge-ghost';
		}
	}

	/**
	 * Format status text
	 */
	function getStatusText(status: string | null): string {
		if (!status) return '-';
		return status;
	}

	function handleCellClick(projectId: string, teamMemberId: string | null) {
		const existing = getAllocation(projectId, teamMemberId);
		if (existing) {
			// Edit existing
			editingAllocation = existing;
			formData = {
				project_id: existing.project_id,
				team_member_id: existing.team_member_id || '',
				month: existing.month,
				allocated_hours: parseFloat(existing.allocated_hours)
			};
		} else {
			// Create new
			editingAllocation = null;
			formData = {
				project_id: projectId,
				team_member_id: teamMemberId || '',
				month: currentPeriod,
				allocated_hours: 0
			};
		}
		formError = null;
		showModal = true;
	}

	async function handleSubmit() {
		try {
			formLoading = true;
			formError = null;

			// Handle untracked: team_member_id can be empty string or null
			const submitData = {
				...formData,
				team_member_id: formData.team_member_id || null
			};

			if (editingAllocation) {
				await allocationService.update(editingAllocation.id, {
					allocated_hours: formData.allocated_hours
				});
			} else {
				await allocationService.create(submitData);
			}

			showModal = false;
			await loadAllocations();
		} catch (err) {
			const apiError = err as { message?: string; data?: { errors?: Record<string, string[]> } };
			if (apiError.data?.errors) {
				const errors = Object.entries(apiError.data.errors)
					.map(([field, msgs]) => `${field}: ${msgs.join(', ')}`)
					.join('; ');
				formError = errors;
			} else {
				formError = apiError.message || 'An error occurred';
			}
		} finally {
			formLoading = false;
		}
	}

	async function handleDelete() {
		if (!editingAllocation) return;

		try {
			formLoading = true;
			await allocationService.delete(editingAllocation.id);
			showModal = false;
			await loadAllocations();
		} catch (err) {
			const apiError = err as { message?: string };
			formError = apiError.message || 'Failed to delete allocation';
		} finally {
			formLoading = false;
		}
	}

	function closeModal() {
		showModal = false;
		editingAllocation = null;
		formError = null;
	}

	function getProjectName(projectId: string): string {
		const project = projects.find(p => p.id === projectId);
		return project ? `${project.code} - ${project.title}` : 'Unknown';
	}

	function getTeamMemberName(teamMemberId: string | null): string {
		if (!teamMemberId) return 'Untracked';
		const member = teamMembers.find(m => m.id === teamMemberId);
		return member?.name || 'Unknown';
	}

	function formatMonth(period: string): string {
		const [year, month] = period.split('-');
		const date = new Date(parseInt(year), parseInt(month) - 1);
		return date.toLocaleDateString('en-US', { month: 'long', year: 'numeric' });
	}
</script>

<svelte:head>
	<title>Allocations | Headroom</title>
</svelte:head>

<PageHeader title="Resource Allocations" description="Manage team member allocations to projects">
	{#snippet children()}
		<div class="flex items-center gap-2">
			<button class="btn btn-ghost btn-sm btn-circle" onclick={() => previousMonth()}>
				<ChevronLeft size={18} />
			</button>
			<span class="min-w-[140px] text-center font-medium">
				{formatMonth(currentPeriod)}
			</span>
			<button class="btn btn-ghost btn-sm btn-circle" onclick={() => nextMonth()}>
				<ChevronRight size={18} />
			</button>
		</div>
	{/snippet}
</PageHeader>

{#if loading}
	<LoadingState />
{:else if error}
	<div class="alert alert-error">
		<AlertCircle size={20} />
		<span>{error}</span>
	</div>
{:else}
	<!-- Allocation Matrix -->
	<div class="overflow-x-auto">
		<table class="table table-xs w-full">
			<thead>
				<tr>
					<th class="sticky left-0 bg-base-200 z-10 min-w-[200px]">Project</th>
					{#each teamMembers as member}
						<th class="text-center min-w-[100px]">{member.name}</th>
					{/each}
					<th class="text-center bg-base-200 font-bold">Total</th>
				</tr>
			</thead>
			<tbody>
				{#each projects as project}
					<tr class="hover">
						<td class="sticky left-0 bg-base-100 z-10 font-medium">
							{project.code} - {project.title}
						</td>
						{#each teamMembers as member}
							{@const allocation = getAllocation(project.id, member.id)}
							<td 
								class="text-center cursor-pointer hover:bg-base-200 transition-colors"
								onclick={() => handleCellClick(project.id, member.id)}
							>
								{#if allocation}
									{@const indicator = allocation.allocation_indicator || 'gray'}
									<span 
										class="badge badge-sm {indicator === 'green' ? 'badge-success' : indicator === 'yellow' ? 'badge-warning' : indicator === 'red' ? 'badge-error' : 'badge-ghost'}"
										title="{indicator === 'green' ? 'Fully allocated' : indicator === 'yellow' ? 'Under allocated' : indicator === 'red' ? 'Over allocated' : 'No budget'}"
									>
										{allocation.allocated_hours}h
									</span>
								{:else}
									<span class="text-base-content/30">-</span>
								{/if}
							</td>
						{/each}
						<!-- Untracked column -->
						<td 
							class="text-center cursor-pointer hover:bg-base-200 transition-colors bg-base-200/30"
							onclick={() => handleCellClick(project.id, null)}
						>
							{#if getAllocation(project.id, null)}
								{@const untracked = getAllocation(project.id, null)}
								<span class="badge badge-sm badge-ghost" title="Untracked allocation">
									{untracked?.allocated_hours}h
								</span>
							{:else}
								<span class="text-base-content/30">-</span>
							{/if}
						</td>
						<!-- Row Total with Variance Status -->
						<td class="text-center bg-base-200 font-bold">
							{getProjectRowTotal(project.id)}h
							{#if getProjectRowStatus(project.id)}
								{@const rowStatus = getProjectRowStatus(project.id)}
								<span class="badge badge-sm {getStatusBadgeClass(rowStatus)} ml-1">
									{getStatusText(rowStatus)}
								</span>
							{/if}
						</td>
					</tr>
				{/each}
			</tbody>
			
			<!-- Variance Summary Section - replaces Monthly Budget -->
			<tfoot>
				<tr class="bg-base-200/50">
					<td class="font-bold">Planned</td>
					{#each teamMembers as member}
						<td class="text-center">-</td>
					{/each}
					<td class="text-center bg-base-200/50">-</td>
					<td class="text-center">-</td>
				</tr>
				<tr class="bg-base-200/50">
					<td class="font-bold">Variance</td>
					{#each teamMembers as member}
						{@const colStatus = getTeamMemberColumnStatus(member.id)}
						<td class="text-center">
							{#if colStatus}
								<span class="badge badge-sm {getStatusBadgeClass(colStatus)}">
									{getStatusText(colStatus)}
								</span>
							{:else}
								-
							{/if}
						</td>
					{/each}
					<td class="text-center bg-base-200/50">-</td>
					<td class="text-center">-</td>
				</tr>
			</tfoot>
			<tfoot>
				<tr class="font-bold bg-base-200">
					<td class="sticky left-0 bg-base-200 z-10">Total</td>
					{#each teamMembers as member}
						<td class="text-center">
							{getTeamMemberColumnTotal(member.id)}h
						</td>
					{/each}
					<td class="text-center bg-base-200">
						{allocations.filter(a => a.team_member_id === null).reduce((sum, a) => sum + parseFloat(a.allocated_hours), 0)}h
					</td>
					<td class="text-center">
						{getProjectTotal()}h
					</td>
				</tr>
			</tfoot>
		</table>
	</div>

	{#if projects.length === 0}
		<EmptyState 
			title="No projects"
			description="Create a project first to manage allocations."
		/>
	{/if}
{/if}

<!-- Allocation Modal -->
{#if showModal}
<div class="modal modal-open">
	<div class="modal-box max-w-md">
		<div class="flex justify-between items-center mb-4">
			<h3 class="font-bold text-lg">
				{editingAllocation ? 'Edit Allocation' : 'New Allocation'}
			</h3>
			<button class="btn btn-ghost btn-sm btn-circle" onclick={closeModal}>
				<X size={18} />
			</button>
		</div>

		{#if formError}
			<div class="alert alert-error mb-4">
				<AlertCircle size={16} />
				<span>{formError}</span>
			</div>
		{/if}

		<form onsubmit={(e) => { e.preventDefault(); handleSubmit(); }}>
			<!-- Project (read-only for existing) -->
			<div class="form-control mb-4">
				<label class="label" for="project">
					<span class="label-text font-medium">Project</span>
				</label>
				<input 
					type="text" 
					id="project"
					class="input input-bordered w-full" 
					value={getProjectName(formData.project_id)}
					disabled
				/>
			</div>

			<!-- Team Member (read-only for existing) -->
			<div class="form-control mb-4">
				<label class="label" for="team_member">
					<span class="label-text font-medium">Team Member</span>
				</label>
				<input 
					type="text" 
					id="team_member"
					class="input input-bordered w-full" 
					value={getTeamMemberName(formData.team_member_id)}
					disabled
				/>
			</div>

			<!-- Month (read-only) -->
			<div class="form-control mb-4">
				<label class="label" for="month">
					<span class="label-text font-medium">Month</span>
				</label>
				<input 
					type="text" 
					id="month"
					class="input input-bordered w-full" 
					value={formatMonth(formData.month)}
					disabled
				/>
			</div>

			<!-- Allocated Hours -->
			<div class="form-control mb-6">
				<label class="label" for="allocated_hours">
					<span class="label-text font-medium">Allocated Hours</span>
				</label>
				<input 
					type="number" 
					id="allocated_hours"
					class="input input-bordered w-full" 
					bind:value={formData.allocated_hours}
					min="0"
					step="0.5"
					required
				/>
			</div>

			<div class="modal-action">
				{#if editingAllocation}
					<button 
						type="button" 
						class="btn btn-error"
						onclick={handleDelete}
						disabled={formLoading}
					>
						<Trash2 size={16} />
						Delete
					</button>
				{/if}
				<button type="button" class="btn btn-ghost" onclick={closeModal}>Cancel</button>
				<button type="submit" class="btn btn-primary" disabled={formLoading}>
					{#if formLoading}
						<span class="loading loading-spinner loading-sm"></span>
					{/if}
					{editingAllocation ? 'Update' : 'Create'}
				</button>
			</div>
		</form>
	</div>
	<div class="modal-backdrop" onclick={closeModal} onkeydown={(e) => e.key === 'Escape' && closeModal()} role="button" tabindex="-1"></div>
</div>
{/if}
