<script lang="ts">
	import Container from "$lib/components/Container.svelte";
	import CollapsibleTable from "$lib/components/CollapsibleTable.svelte";

	interface Stats {
		todayCount: number;
		totalCount: number;
		uniquePlayers: number;
		weeklyPlayers: number;
		activeStreaks: number;
		avgGuessesToday: number | null;
		registeredUsers: number;
		monthlyPlayers: number;
	}

	interface PageData {
		todayEst: string;
		stats: Stats;
		last14Days: { date: string; count: number }[];
		streakChart: { days: number; count: number }[];
		growth: {
			completionsVelocity: number;
			completionsAcceleration: number;
			userVelocity: number;
			userAcceleration: number;
			newUsers7d: number;
			churned7d: number;
			netGrowth7d: number;
		};
		retention7dSeries: { date: string; rate: number; cohortSize: number }[];
		retention30dSeries: {
			date: string;
			rate: number;
			cohortSize: number;
		}[];
		overallReturnRate: number | null;
		newPlayerReturnSeries: {
			date: string;
			cohort: number;
			rate: number | null;
			rollingAvg: number | null;
		}[];
		newPlayerReturnVelocity: {
			current7dAvg: number | null;
			prior7dAvg: number | null;
			change: number | null;
		};
		wauWeeks: {
			weekStart: string;
			weekEnd: string;
			wau: number;
			changePct: number | null;
		}[];
		avgWau: number;
		mauMonths: { monthStart: string; monthEnd: string; mau: number; changePct: number | null }[];
		calendarMauMonths: {
			label: string;
			monthStart: string;
			monthEnd: string;
			mau: number;
			daysElapsed: number;
			daysInMonth: number;
			projectedMau: number | null;
			changePct: number | null;
			isCurrentMonth: boolean;
		}[];
		sessionDepthCards: { depth: number; players: number; returnRate: number | null }[];
	}

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

	const {
		stats,
		last14Days,
		todayEst,
		streakChart,
		growth,
		retention7dSeries,
		retention30dSeries,
		overallReturnRate,
		newPlayerReturnSeries,
		newPlayerReturnVelocity,
		wauWeeks,
		avgWau,
		mauMonths,
		calendarMauMonths,
		sessionDepthCards,
	} = $derived(data);

	let mauMode = $state<'rolling' | 'calendar'>('rolling');

	function signed(n: number, unit = ""): string {
		if (n > 0) return `+${n}${unit}`;
		if (n < 0) return `${n}${unit}`;
		return `0${unit}`;
	}

	function trendColor(n: number): string {
		if (n > 0) return "text-green-400";
		if (n < 0) return "text-red-400";
		return "text-gray-400";
	}

	const maxCount = $derived(Math.max(1, ...last14Days.map((d) => d.count)));
	const maxWau = $derived(Math.max(1, ...wauWeeks.map((w) => w.wau)));
	const maxStreakCount = $derived(Math.max(1, ...streakChart.map((r) => r.count)));
	const maxMau = $derived(Math.max(1, ...mauMonths.map((m) => m.mau)));
	const maxCalMau = $derived(Math.max(1, ...calendarMauMonths.map((m) => m.projectedMau ?? m.mau)));

	const statCards = $derived([
		{ label: "Completions Today", value: String(stats.todayCount) },
		{ label: "All-Time Completions", value: String(stats.totalCount) },
		{ label: "Unique Players", value: String(stats.uniquePlayers) },
		{ label: "Players This Week", value: String(stats.weeklyPlayers) },
		{ label: "Active Streaks", value: String(stats.activeStreaks) },
		{ label: "Registered Users", value: String(stats.registeredUsers) },
		{ label: "Players This Month", value: String(stats.monthlyPlayers) },
		{
			label: "Overall Return Rate",
			value: overallReturnRate != null ? `${overallReturnRate}%` : "N/A",
		},
	]);

	const mauModes = [
		{ value: 'rolling', label: 'Rolling 30d' },
		{ value: 'calendar', label: 'Calendar' },
	];
</script>

<svelte:head>
	<title>Global Stats | Bibdle</title>
</svelte:head>

<div
	class="min-h-screen bg-linear-to-br from-gray-900 via-slate-900 to-gray-900 text-gray-100"
>
	<div class="max-w-6xl mx-auto px-4 py-8">
		<a
			href="/"
			class="inline-flex items-center gap-1 text-gray-400 hover:text-gray-100 text-sm mb-6 transition-colors"
		>
			← Back to Game
		</a>

		<header class="mb-8">
			<h1 class="text-3xl font-bold text-gray-100">Global Stats</h1>
			<p class="text-gray-400 text-sm mt-1">
				EST reference date: {todayEst}
			</p>
		</header>

		<section
			class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4 mb-10"
		>
			{#each statCards as card (card.label)}
				<Container class="w-full p-5 gap-2">
					<span
						class="text-gray-400 text-xs uppercase tracking-wide text-center"
						>{card.label}</span
					>
					<span class="text-2xl md:text-3xl font-bold text-gray-100"
						>{card.value}</span
					>
				</Container>
			{/each}
		</section>

		<section class="mb-10">
			<h2 class="text-lg font-semibold text-gray-100 mb-4">
				Traffic &amp; Growth <span
					class="text-xs font-normal text-gray-400"
					>(7-day windows)</span
				>
			</h2>
			<div class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4">
				<Container class="w-full p-5 gap-2">
					<span
						class="text-gray-400 text-xs uppercase tracking-wide text-center"
						>Completions Velocity</span
					>
					<span
						class="text-2xl md:text-3xl font-bold text-center {trendColor(
							growth.completionsVelocity,
						)}">{signed(growth.completionsVelocity, "/day")}</span
					>
					<span class="text-xs text-gray-500 text-center"
						>vs prior 7 days</span
					>
				</Container>
				<Container class="w-full p-5 gap-2">
					<span
						class="text-gray-400 text-xs uppercase tracking-wide text-center"
						>Completions Accel.</span
					>
					<span
						class="text-2xl md:text-3xl font-bold text-center {trendColor(
							growth.completionsAcceleration,
						)}"
						>{signed(growth.completionsAcceleration, "/day")}</span
					>
					<span class="text-xs text-gray-500 text-center"
						>rate of change of velocity</span
					>
				</Container>
				<Container class="w-full p-5 gap-2">
					<span
						class="text-gray-400 text-xs uppercase tracking-wide text-center"
						>User Velocity</span
					>
					<span
						class="text-2xl md:text-3xl font-bold text-center {trendColor(
							growth.userVelocity,
						)}">{signed(growth.userVelocity)}</span
					>
					<span class="text-xs text-gray-500 text-center"
						>unique players, wk/wk</span
					>
				</Container>
				<Container class="w-full p-5 gap-2">
					<span
						class="text-gray-400 text-xs uppercase tracking-wide text-center"
						>User Acceleration</span
					>
					<span
						class="text-2xl md:text-3xl font-bold text-center {trendColor(
							growth.userAcceleration,
						)}">{signed(growth.userAcceleration)}</span
					>
					<span class="text-xs text-gray-500 text-center"
						>rate of change of user velocity</span
					>
				</Container>
				<Container class="w-full p-5 gap-2">
					<span
						class="text-gray-400 text-xs uppercase tracking-wide text-center"
						>New Players (7d)</span
					>
					<span
						class="text-2xl md:text-3xl font-bold text-center {trendColor(
							growth.newUsers7d,
						)}">{String(growth.newUsers7d)}</span
					>
					<span class="text-xs text-gray-500 text-center"
						>first-time players</span
					>
				</Container>
				<Container class="w-full p-5 gap-2">
					<span
						class="text-gray-400 text-xs uppercase tracking-wide text-center"
						>Churned (7d)</span
					>
					<span
						class="text-2xl md:text-3xl font-bold text-center {trendColor(
							0,
						)}">{String(growth.churned7d)}</span
					>
					<span class="text-xs text-gray-500 text-center"
						>played wk prior, not this wk</span
					>
				</Container>
				<Container class="w-full p-5 gap-2">
					<span
						class="text-gray-400 text-xs uppercase tracking-wide text-center"
						>Net Growth (7d)</span
					>
					<span
						class="text-2xl md:text-3xl font-bold text-center {trendColor(
							growth.netGrowth7d,
						)}">{signed(growth.netGrowth7d)}</span
					>
					<span class="text-xs text-gray-500 text-center"
						>new minus churned</span
					>
				</Container>
			</div>
		</section>

		<section class="mb-10">
			<h2 class="text-lg font-semibold text-gray-100 mb-1">Survival Curve</h2>
			<p class="text-gray-400 text-sm mb-4">
				Of players who completed N sessions, what % came back for N+1?
			</p>
			<div class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-4">
				{#each sessionDepthCards as card (card.depth)}
					<Container class="w-full p-5 gap-2">
						<span class="text-gray-400 text-xs uppercase tracking-wide text-center"
							>After {card.depth} plays</span
						>
						<span class="text-2xl md:text-3xl font-bold text-gray-100">
							{card.returnRate != null ? `${card.returnRate}%` : "N/A"}
						</span>
						<span class="text-xs text-gray-500 text-center"
							>{card.players} players</span
						>
					</Container>
				{/each}
			</div>
		</section>

		<section class="mb-10">
			<h2 class="text-lg font-semibold text-gray-100 mb-4">
				New Player Return Rate <span
					class="text-xs font-normal text-gray-400"
					>(7-day rolling avg)</span
				>
			</h2>
			<div class="grid grid-cols-2 sm:grid-cols-3 gap-4 mb-6">
				<Container class="w-full p-5 gap-2">
					<span
						class="text-gray-400 text-xs uppercase tracking-wide text-center"
						>Return Rate (7d avg)</span
					>
					<span
						class="text-2xl md:text-3xl font-bold text-center text-gray-100"
					>
						{newPlayerReturnVelocity.current7dAvg != null
							? `${newPlayerReturnVelocity.current7dAvg}%`
							: "N/A"}
					</span>
					<span class="text-xs text-gray-500 text-center"
						>new players who came back</span
					>
				</Container>
				<Container class="w-full p-5 gap-2">
					<span
						class="text-gray-400 text-xs uppercase tracking-wide text-center"
						>Return Rate Change</span
					>
					<span
						class="text-2xl md:text-3xl font-bold text-center {newPlayerReturnVelocity.change !=
						null
							? trendColor(newPlayerReturnVelocity.change)
							: 'text-gray-400'}"
					>
						{newPlayerReturnVelocity.change != null
							? signed(newPlayerReturnVelocity.change, "pp")
							: "N/A"}
					</span>
					<span class="text-xs text-gray-500 text-center"
						>vs prior 7 days</span
					>
				</Container>
				<Container class="w-full p-5 gap-2">
					<span
						class="text-gray-400 text-xs uppercase tracking-wide text-center"
						>Prior 7d Avg</span
					>
					<span
						class="text-2xl md:text-3xl font-bold text-center text-gray-100"
					>
						{newPlayerReturnVelocity.prior7dAvg != null
							? `${newPlayerReturnVelocity.prior7dAvg}%`
							: "N/A"}
					</span>
					<span class="text-xs text-gray-500 text-center"
						>days 8–14 ago</span
					>
				</Container>
			</div>

			<CollapsibleTable
				rows={newPlayerReturnSeries}
				headers={[
					{ label: 'Date' },
					{ label: 'New Players', align: 'right' },
					{ label: 'Return Rate', align: 'right' },
					{ label: '7d Avg', align: 'right' },
					{ label: '', width: 'w-32' },
				]}
			>
				{#snippet row(item)}
					<td class="px-4 py-3 text-gray-300">{item.date}</td>
					<td class="px-4 py-3 text-right text-gray-400 text-xs">{item.cohort}</td>
					<td class="px-4 py-3 text-right text-gray-400">
						{item.rate != null ? `${item.rate}%` : '—'}
					</td>
					<td class="px-4 py-3 text-right text-gray-100 font-medium">
						{item.rollingAvg != null ? `${item.rollingAvg}%` : '—'}
					</td>
					<td class="px-4 py-3">
						<div class="w-full min-w-20">
							{#if item.rollingAvg != null}
								<div class="bg-sky-500 h-4 rounded" style="width: {item.rollingAvg}%"></div>
							{/if}
						</div>
					</td>
				{/snippet}
			</CollapsibleTable>
		</section>

		<section class="mt-8">
			<h2 class="text-lg font-semibold text-gray-100 mb-1">
				Weekly Active Users
			</h2>
			<p class="text-gray-400 text-sm mb-4">
				Unique players per 7-day window. Most recent week first. Avg
				WAU: <span class="text-gray-100 font-medium">{avgWau}</span>
			</p>
			<CollapsibleTable
				rows={wauWeeks}
				headers={[
					{ label: 'Week' },
					{ label: 'Active Users', align: 'right' },
					{ label: 'Wk/Wk Change', align: 'right' },
					{ label: '', width: 'w-48' },
				]}
			>
				{#snippet row(item)}
					{@const barPct = Math.round((item.wau / maxWau) * 100)}
					<td class="px-4 py-3 text-gray-300 text-xs">{item.weekStart} – {item.weekEnd}</td>
					<td class="px-4 py-3 text-right text-gray-100 font-medium">{item.wau}</td>
					<td class="px-4 py-3 text-right text-xs font-medium {item.changePct != null
						? item.changePct > 0 ? 'text-green-400' : item.changePct < 0 ? 'text-red-400' : 'text-gray-400'
						: 'text-gray-500'}">
						{item.changePct != null ? signed(item.changePct, '%') : '—'}
					</td>
					<td class="px-4 py-3">
						<div class="w-full min-w-24">
							<div class="bg-indigo-500 h-4 rounded" style="width: {barPct}%"></div>
						</div>
					</td>
				{/snippet}
			</CollapsibleTable>
		</section>

		<section class="mt-8">
			<h2 class="text-lg font-semibold text-gray-100 mb-1">Monthly Active Users</h2>
			<p class="text-gray-400 text-sm mb-4">
				{mauMode === 'rolling'
					? 'Unique players per 30-day window. Most recent first.'
					: 'Unique players per calendar month. Current month projected to end of month.'}
			</p>

			{#if mauMode === 'rolling'}
				<CollapsibleTable
					rows={mauMonths}
					headers={[
						{ label: 'Period' },
						{ label: 'Active Users', align: 'right' },
						{ label: 'Mo/Mo Change', align: 'right' },
						{ label: '', width: 'w-48' },
					]}
					modes={mauModes}
					bind:mode={mauMode}
				>
					{#snippet row(item)}
						{@const barPct = Math.round((item.mau / maxMau) * 100)}
						<td class="px-4 py-3 text-gray-300 text-xs">{item.monthStart} – {item.monthEnd}</td>
						<td class="px-4 py-3 text-right text-gray-100 font-medium">{item.mau}</td>
						<td class="px-4 py-3 text-right text-xs font-medium {item.changePct != null
							? item.changePct > 0 ? 'text-green-400' : item.changePct < 0 ? 'text-red-400' : 'text-gray-400'
							: 'text-gray-500'}">
							{item.changePct != null ? signed(item.changePct, '%') : '—'}
						</td>
						<td class="px-4 py-3">
							<div class="w-full min-w-24">
								<div class="bg-teal-500 h-4 rounded" style="width: {barPct}%"></div>
							</div>
						</td>
					{/snippet}
				</CollapsibleTable>
			{:else}
				<CollapsibleTable
					rows={calendarMauMonths}
					headers={[
						{ label: 'Month' },
						{ label: 'Active Users', align: 'right' },
						{ label: 'Mo/Mo Change', align: 'right' },
						{ label: '', width: 'w-48' },
					]}
					modes={mauModes}
					bind:mode={mauMode}
				>
					{#snippet row(item)}
						{@const displayMau = item.projectedMau ?? item.mau}
						{@const barPct = Math.round((displayMau / maxCalMau) * 100)}
						<td class="px-4 py-3 text-gray-300">
							{item.label}
							{#if item.isCurrentMonth}
								<span class="text-xs text-gray-500 ml-1">(projected)</span>
							{/if}
						</td>
						<td class="px-4 py-3 text-right font-medium {item.isCurrentMonth ? 'text-gray-400' : 'text-gray-100'}">
							{#if item.isCurrentMonth}
								<span class="text-gray-500 text-xs">{item.mau} → </span>{item.projectedMau ?? item.mau}
							{:else}
								{item.mau}
							{/if}
						</td>
						<td class="px-4 py-3 text-right text-xs font-medium {item.changePct != null
							? item.changePct > 0 ? 'text-green-400' : item.changePct < 0 ? 'text-red-400' : 'text-gray-400'
							: 'text-gray-500'}">
							{#if item.changePct != null}
								{item.isCurrentMonth ? '~' : ''}{signed(item.changePct, '%')}
							{:else}
								—
							{/if}
						</td>
						<td class="px-4 py-3">
							<div class="w-full min-w-24">
								<div class="bg-teal-500 h-4 rounded {item.isCurrentMonth ? 'opacity-50' : ''}" style="width: {barPct}%"></div>
							</div>
						</td>
					{/snippet}
				</CollapsibleTable>
			{/if}
		</section>

		<section class="mt-8">
			<h2 class="text-lg font-semibold text-gray-100 mb-4">
				Last 14 Days — Completions
			</h2>
			<CollapsibleTable
				rows={last14Days}
				headers={[
					{ label: 'Date' },
					{ label: 'Completions', align: 'right' },
					{ label: '', width: 'w-48' },
				]}
			>
				{#snippet row(item)}
					{@const barPct = Math.round((item.count / maxCount) * 100)}
					<td class="px-4 py-3 text-gray-300">{item.date}</td>
					<td class="px-4 py-3 text-right text-gray-100 font-medium">{item.count}</td>
					<td class="px-4 py-3">
						<div class="w-full min-w-24">
							<div class="bg-amber-500 h-4 rounded" style="width: {barPct}%"></div>
						</div>
					</td>
				{/snippet}
			</CollapsibleTable>
		</section>

		<section class="mt-8">
			<h2 class="text-lg font-semibold text-gray-100 mb-4">
				Active Streak Distribution
			</h2>
			<CollapsibleTable
				rows={streakChart}
				headers={[
					{ label: 'Days' },
					{ label: 'Players', align: 'right' },
					{ label: '', width: 'w-48' },
				]}
			>
				{#snippet row(item)}
					{@const barPct = Math.round((item.count / maxStreakCount) * 100)}
					<td class="px-4 py-3 text-gray-300">{item.days}</td>
					<td class="px-4 py-3 text-right text-gray-100 font-medium">{item.count}</td>
					<td class="px-4 py-3">
						<div class="w-full min-w-24">
							<div class="bg-blue-500 h-4 rounded" style="width: {barPct}%"></div>
						</div>
					</td>
				{/snippet}
				{#snippet empty()}
					<p class="text-gray-400 text-sm px-4 py-6">No active streaks yet.</p>
				{/snippet}
			</CollapsibleTable>
		</section>

		<section class="mt-8">
			<h2 class="text-lg font-semibold text-gray-100 mb-1">
				Retention Over Time
			</h2>
			<p class="text-gray-400 text-sm mb-6">
				% of each day's players who played again exactly 7 or 30 days later (regardless of activity in between). Cohorts with fewer than 3 players are excluded.
			</p>

			<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
				<!-- 7-day retention -->
				<div>
					<h3 class="text-base font-semibold text-gray-200 mb-3">
						7-Day Retention
					</h3>
					<CollapsibleTable
						rows={retention7dSeries}
						headers={[
							{ label: 'Cohort Date' },
							{ label: 'n', align: 'right' },
							{ label: 'Ret. %', align: 'right' },
							{ label: '', width: 'w-32' },
						]}
					>
						{#snippet row(item)}
							<td class="px-4 py-3 text-gray-300">{item.date}</td>
							<td class="px-4 py-3 text-right text-gray-400 text-xs">{item.cohortSize}</td>
							<td class="px-4 py-3 text-right text-gray-100 font-medium">{item.rate}%</td>
							<td class="px-4 py-3">
								<div class="w-full min-w-20">
									<div class="bg-emerald-500 h-4 rounded" style="width: {item.rate}%"></div>
								</div>
							</td>
						{/snippet}
					</CollapsibleTable>
				</div>

				<!-- 30-day retention -->
				<div>
					<h3 class="text-base font-semibold text-gray-200 mb-3">
						30-Day Retention
					</h3>
					<CollapsibleTable
						rows={retention30dSeries}
						headers={[
							{ label: 'Cohort Date' },
							{ label: 'n', align: 'right' },
							{ label: 'Ret. %', align: 'right' },
							{ label: '', width: 'w-32' },
						]}
					>
						{#snippet row(item)}
							<td class="px-4 py-3 text-gray-300">{item.date}</td>
							<td class="px-4 py-3 text-right text-gray-400 text-xs">{item.cohortSize}</td>
							<td class="px-4 py-3 text-right text-gray-100 font-medium">{item.rate}%</td>
							<td class="px-4 py-3">
								<div class="w-full min-w-20">
									<div class="bg-violet-500 h-4 rounded" style="width: {item.rate}%"></div>
								</div>
							</td>
						{/snippet}
					</CollapsibleTable>
				</div>
			</div>
		</section>
	</div>
</div>
