<script lang="ts">
	import { formatZoned, getZonedHour } from '$lib/utils/date';

	import * as m from '$lib/paraglide/messages';

	import { getWeatherDescription, getWeatherIconName } from '../../utils/weather-codes';

	interface Props {
		timestamps: number[];
		hourlyFlat: Record<string, number[]>;
		models: string[];
		sunrise: number[];
		sunset: number[];
		timezone: string;
	}

	let { timestamps, hourlyFlat, models, sunrise, sunset, timezone }: Props = $props();

	let hourlyInterval = $state<1 | 3>(3);

	let filteredIndices = $derived(
		timestamps.reduce<number[]>((acc, ts, i) => {
			if (hourlyInterval === 1 || getZonedHour(new Date(ts), timezone) % 3 === 0) {
				acc.push(i);
			}
			return acc;
		}, [])
	);

	function checkNewDay(i: number, ts: number): boolean {
		if (i === 0) return false;
		const prevTs = timestamps[filteredIndices[i - 1]];
		return (
			formatZoned(new Date(ts), timezone, 'd') !== formatZoned(new Date(prevTs), timezone, 'd')
		);
	}

	/**
	 * Determines if it's daytime for each timestamp based on sunrise/sunset data.
	 */
	let allDaytimeFlags = $derived(
		timestamps.map((ts) => {
			const tsS = ts / 1000;
			for (let i = 0; i < sunrise.length; i++) {
				const s = sunrise[i];
				const e = sunset[i];
				// Between sunrise and sunset of the same day
				if (tsS >= s && tsS < e) return true;
				// Between sunset of day i and sunrise of day i+1 (night)
				const nextS = sunrise[i + 1] || Infinity;
				if (tsS >= e && tsS < nextS) return false;
			}
			// Fallback: before the first sunrise
			if (sunrise.length > 0 && tsS < sunrise[0]) return false;
			return true;
		})
	);

	/**
	 * Filters models that actually have weather_code data available in the response.
	 */
	let displayModels = $derived(models.filter((m) => hourlyFlat[`weather_code_${m}`]));
</script>

{#snippet weatherIcon(name: string, size: number = 24, description: string = '')}
	<svg class="inline-block fill-foreground" width={size} height={size}>
		{#if description}<title>{description}</title>{/if}
		<use xlink:href="/images/weather-icons/{name}.svg#Layer_1"></use>
	</svg>
{/snippet}

{#if displayModels.length > 0}
	<div class="mt-8">
		<div class="mb-4 flex items-center justify-between">
			<h3 class="text-xl font-bold">{m.compare_timeline_title()}</h3>
			<div class="flex items-center gap-1.5 text-[13px] font-semibold">
				<span class="select-none text-muted-foreground">3h</span>
				<button
					class="relative h-6 w-11 cursor-pointer rounded-full border transition-colors
						{hourlyInterval === 1 ? 'border-primary/40 bg-primary' : 'border-border bg-muted'}"
					onclick={() => (hourlyInterval = hourlyInterval === 1 ? 3 : 1)}
					title={m.interval_toggle()}
				>
					<span
						class="absolute top-0.75 size-4.5 rounded-full bg-white shadow-sm transition-[left] duration-200
							{hourlyInterval === 1 ? 'left-5.5' : 'left-0.75'}"
					></span>
				</button>
				<span class="select-none text-muted-foreground">1h</span>
			</div>
		</div>
		<div
			class="overflow-x-auto rounded-lg border border-border bg-card shadow-sm"
			style="scrollbar-width: thin"
		>
			<table class="w-full border-collapse">
				<thead>
					<tr class="bg-muted/30">
						<th
							class="sticky left-0 z-20 w-32 border-b border-r border-border bg-muted/95 p-2 text-left text-xs font-bold"
						>
							{m.compare_model_label()}
						</th>
						{#each filteredIndices as idx, i (idx)}
							{@const ts = timestamps[idx]}
							{@const isNewDay = checkNewDay(i, ts)}
							<th
								class="min-w-11 border-b border-r border-border/50 p-2 text-center text-[10px] {isNewDay
									? 'border-l-2 border-l-primary/30'
									: ''}"
							>
								<div class="font-bold">{formatZoned(new Date(ts), timezone, 'HH')}</div>
								<div class="text-muted-foreground">
									{isNewDay ? formatZoned(new Date(ts), timezone, 'EEE d') : ''}
								</div>
							</th>
						{/each}
					</tr>
				</thead>
				<tbody>
					{#each displayModels as model (model)}
						<tr class="group hover:bg-muted/10">
							<td
								class="sticky left-0 z-10 border-b border-r border-border bg-card p-2 text-[11px] font-semibold group-hover:bg-muted/20"
							>
								{model.replace(/_/g, ' ')}
							</td>
							{#each filteredIndices as idx, i (idx)}
								{@const ts = timestamps[idx]}
								{@const codes = hourlyFlat[`weather_code_${model}`]}
								{@const code = codes ? codes[idx] : 0}
								{@const day = allDaytimeFlags[idx]}
								{@const isNewDay = checkNewDay(i, ts)}
								<td
									class="border-b border-r border-border/30 p-1.5 text-center {isNewDay
										? 'border-l-2 border-l-primary/20'
										: ''} {!day ? 'bg-indigo-950/5 dark:bg-indigo-500/5' : ''}"
								>
									{@render weatherIcon(
										getWeatherIconName(code, day),
										24,
										getWeatherDescription(code)
									)}
								</td>
							{/each}
						</tr>
					{/each}
				</tbody>
			</table>
		</div>
	</div>
{/if}

<style>
	th,
	td {
		white-space: nowrap;
	}
</style>
