<script lang="ts">
	import { fmtInt, fmtCompact, fmtUsd } from '$lib/format';
	import type { Punchcard } from '$lib/server/stats/punchcard';

	interface Props {
		punchcard: Punchcard;
		metric?: 'events' | 'tokens';
	}

	let { punchcard, metric = 'events' }: Props = $props();

	// Row labels, Monday-first to match the server's dow index (0=Mon..6=Sun).
	const DAY_LABELS = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
	const hours = Array.from({ length: 24 }, (_, h) => h);
	const tickHours = [0, 6, 12, 18, 23];

	const cells = $derived(punchcard.cells);
	const maxValue = $derived(
		metric === 'events'
			? Math.max(1, punchcard.maxEventCount)
			: Math.max(1, punchcard.maxTotalTokens)
	);
	const hasData = $derived(punchcard.totalEvents > 0);

	function cellValue(dow: number, hour: number): number {
		const c = cells[dow][hour];
		return metric === 'events' ? c.eventCount : c.totalTokens;
	}

	// Intensity 0..1 → opacity of the accent fill. sqrt gives lighter cells more
	// visible contrast at the low end.
	function intensity(dow: number, hour: number): number {
		const v = cellValue(dow, hour);
		if (v <= 0) return 0;
		return Math.sqrt(v / maxValue);
	}

	function hourLabel(hour: number): string {
		return `${String(hour).padStart(2, '0')}:00`;
	}
</script>

{#if !hasData}
	<p class="empty">No data in this window.</p>
{:else}
	<div class="punch">
		<div class="grid" role="img" aria-label="Activity by day of week and hour of day (UTC)">
			{#each DAY_LABELS as day, dow (day)}
				<span class="day-label mono">{day}</span>
				{#each hours as hour (hour)}
					{@const cell = cells[dow][hour]}
					{@const op = intensity(dow, hour)}
					<span
						class="cell"
						class:zero={op === 0}
						style={`--op:${op}`}
						title={`${day} ${hourLabel(hour)} UTC · ${fmtInt(cell.eventCount)} events · ${fmtCompact(cell.totalTokens)} tok · ${fmtUsd(cell.costUsd)}`}
					></span>
				{/each}
			{/each}
			<span class="corner"></span>
			{#each hours as hour (hour)}
				<span class="hour-tick mono">{tickHours.includes(hour) ? hour : ''}</span>
			{/each}
		</div>
		<div class="legend">
			<span>Less</span>
			<span class="swatch" style="--op:0.1"></span>
			<span class="swatch" style="--op:0.4"></span>
			<span class="swatch" style="--op:0.7"></span>
			<span class="swatch" style="--op:1"></span>
			<span>More</span>
			<span class="utc-note mono">UTC</span>
		</div>
	</div>
{/if}

<style>
	.punch {
		display: flex;
		flex-direction: column;
		gap: 0.6rem;
	}

	.grid {
		display: grid;
		/* day label column + 24 hour columns */
		grid-template-columns: auto repeat(24, 1fr);
		gap: 3px;
		align-items: center;
	}

	.day-label {
		font-size: 0.7rem;
		color: var(--text-faint);
		text-align: right;
		padding-right: 0.5rem;
		white-space: nowrap;
	}

	.cell {
		aspect-ratio: 1 / 1;
		border-radius: 3px;
		background: var(--accent);
		opacity: var(--op);
		min-height: 12px;
		transition: transform 0.12s ease;
	}

	.cell:hover {
		transform: scale(1.18);
	}

	.cell.zero {
		background: var(--bg-raised);
		opacity: 1;
	}

	.corner {
		/* aligns with the day-label column under the grid */
		display: block;
	}

	.hour-tick {
		font-size: 0.62rem;
		color: var(--text-faint);
		text-align: center;
	}

	.legend {
		display: flex;
		align-items: center;
		gap: 0.35rem;
		font-size: 0.7rem;
		color: var(--text-faint);
	}

	.swatch {
		width: 12px;
		height: 12px;
		border-radius: 3px;
		background: var(--accent);
		opacity: var(--op);
	}

	.utc-note {
		margin-left: auto;
		text-transform: uppercase;
		letter-spacing: 0.05em;
	}

	.empty {
		color: var(--text-dim);
		font-size: 13px;
		padding: 24px 0;
		text-align: center;
	}
</style>
