<script lang="ts">
	interface CalendarEntry {
		id: string;
		type: string;
		startDate: string;
		endDate: string;
		label: string;
		description: string | null;
	}

	let {
		entries = [],
		initialMonth,
		initialYear
	}: {
		entries: CalendarEntry[];
		initialMonth?: number;
		initialYear?: number;
	} = $props();

	const DAYS = ['Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam', 'Dim'] as const;

	const MONTHS = [
		'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
		'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'
	] as const;

	const TYPE_COLORS: Record<string, string> = {
		holiday: '#ef4444',
		vacation: '#3b82f6',
		pedagogical: '#f59e0b',
		bridge: '#8b5cf6',
		closure: '#6b7280'
	};

	const TYPE_LABELS: Record<string, string> = {
		holiday: 'Jour férié',
		vacation: 'Vacances',
		pedagogical: 'J. pédagogique',
		bridge: 'Pont',
		closure: 'Fermeture'
	};

	let month = $state(initialMonth ?? new Date().getMonth());
	let year = $state(initialYear ?? new Date().getFullYear());

	let monthLabel = $derived(`${MONTHS[month]} ${year}`);

	let daysInMonth = $derived(new Date(year, month + 1, 0).getDate());

	// Monday = 0, Sunday = 6 (ISO week)
	let firstDayOffset = $derived(() => {
		const jsDay = new Date(year, month, 1).getDay(); // 0=Sun, 1=Mon...
		return jsDay === 0 ? 6 : jsDay - 1;
	});

	interface DayCell {
		day: number;
		dateStr: string;
		entries: CalendarEntry[];
		isToday: boolean;
		isWeekend: boolean;
	}

	let calendarGrid = $derived(() => {
		const offset = firstDayOffset();
		const today = new Date();
		const todayStr = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`;
		const cells: (DayCell | null)[] = [];

		// Leading blanks
		for (let i = 0; i < offset; i++) {
			cells.push(null);
		}

		for (let d = 1; d <= daysInMonth; d++) {
			const dateStr = `${year}-${String(month + 1).padStart(2, '0')}-${String(d).padStart(2, '0')}`;
			const dayOfWeek = (offset + d - 1) % 7; // 0=Mon, 5=Sat, 6=Sun

			const dayEntries = entries.filter((e) => {
				return e.startDate <= dateStr && e.endDate >= dateStr;
			});

			cells.push({
				day: d,
				dateStr,
				entries: dayEntries,
				isToday: dateStr === todayStr,
				isWeekend: dayOfWeek >= 5
			});
		}

		// Split into rows of 7
		const rows: (DayCell | null)[][] = [];
		for (let i = 0; i < cells.length; i += 7) {
			const row = cells.slice(i, i + 7);
			// Pad last row
			while (row.length < 7) {
				row.push(null);
			}
			rows.push(row);
		}

		return rows;
	});

	// Active types present in the current entries
	let activeTypes = $derived(() => {
		const types = new Set(entries.map((e) => e.type));
		return [...types].sort();
	});

	// Tooltip state
	let tooltip = $state<{ x: number; y: number; entries: CalendarEntry[] } | null>(null);

	function showTooltip(event: Event, dayEntries: CalendarEntry[]) {
		if (dayEntries.length === 0) return;
		const target = event.currentTarget;
		if (!(target instanceof HTMLElement)) return;
		const rect = target.getBoundingClientRect();
		tooltip = {
			x: rect.left + rect.width / 2,
			y: rect.top,
			entries: dayEntries
		};
	}

	function hideTooltip() {
		tooltip = null;
	}

	function prevMonth() {
		if (month === 0) {
			month = 11;
			year--;
		} else {
			month--;
		}
	}

	function nextMonth() {
		if (month === 11) {
			month = 0;
			year++;
		} else {
			month++;
		}
	}

	function goToToday() {
		const now = new Date();
		month = now.getMonth();
		year = now.getFullYear();
	}
</script>

<div class="calendar-view">
	<div class="calendar-nav">
		<button class="nav-btn" onclick={prevMonth} aria-label="Mois précédent">&lsaquo;</button>
		<button class="nav-label" onclick={goToToday} title="Revenir à aujourd'hui">
			{monthLabel}
		</button>
		<button class="nav-btn" onclick={nextMonth} aria-label="Mois suivant">&rsaquo;</button>
	</div>

	<div class="calendar-grid" role="grid" aria-label="Calendrier {monthLabel}">
		<div class="grid-header" role="row">
			{#each DAYS as day}
				<div class="grid-header-cell" role="columnheader">{day}</div>
			{/each}
		</div>

		{#each calendarGrid() as row}
			<div class="grid-row" role="row">
				{#each row as cell}
					{#if cell === null}
						<div class="grid-cell grid-cell-empty" role="gridcell"></div>
					{:else}
						<div
							class="grid-cell"
							class:grid-cell-today={cell.isToday}
							class:grid-cell-weekend={cell.isWeekend}
							class:grid-cell-has-entries={cell.entries.length > 0}
							role="gridcell"
							aria-label="{cell.day} {MONTHS[month]} {year}{cell.entries.length > 0 ? `, ${cell.entries.length} événement${cell.entries.length > 1 ? 's' : ''}` : ''}"
							onmouseenter={(e) => showTooltip(e, cell.entries)}
							onmouseleave={hideTooltip}
						>
							<span class="day-number" class:day-number-today={cell.isToday}>{cell.day}</span>
							{#if cell.entries.length > 0}
								<div class="day-dots">
									{#each cell.entries.slice(0, 3) as entry}
										<span
											class="day-dot"
											style="background: {TYPE_COLORS[entry.type] ?? '#6b7280'};"
										></span>
									{/each}
									{#if cell.entries.length > 3}
										<span class="day-dot-more">+{cell.entries.length - 3}</span>
									{/if}
								</div>
							{/if}
						</div>
					{/if}
				{/each}
			</div>
		{/each}
	</div>

	{#if activeTypes().length > 0}
		<div class="calendar-legend">
			{#each activeTypes() as type}
				<span class="legend-item">
					<span class="legend-dot" style="background: {TYPE_COLORS[type] ?? '#6b7280'};"></span>
					{TYPE_LABELS[type] ?? type}
				</span>
			{/each}
		</div>
	{/if}
</div>

{#if tooltip}
	<div
		class="tooltip"
		style="left: {tooltip.x}px; top: {tooltip.y}px;"
		role="tooltip"
	>
		{#each tooltip.entries as entry}
			<div class="tooltip-entry">
				<span class="tooltip-dot" style="background: {TYPE_COLORS[entry.type] ?? '#6b7280'};"></span>
				<span class="tooltip-label">{entry.label}</span>
			</div>
		{/each}
	</div>
{/if}

<style>
	.calendar-view {
		background: var(--surface-elevated, #fff);
		border: 1px solid var(--border-subtle, #e2e8f0);
		border-radius: 0.75rem;
		overflow: hidden;
	}

	/* Navigation */
	.calendar-nav {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: 0.75rem 1rem;
		border-bottom: 1px solid var(--border-subtle, #e2e8f0);
	}

	.nav-btn {
		width: 2rem;
		height: 2rem;
		display: flex;
		align-items: center;
		justify-content: center;
		background: transparent;
		border: 1px solid var(--border-subtle, #e2e8f0);
		border-radius: 0.375rem;
		cursor: pointer;
		font-size: 1.25rem;
		color: var(--text-secondary, #64748b);
		transition: all 0.15s;
	}

	.nav-btn:hover {
		background: var(--surface-primary, #f8fafc);
		color: var(--text-primary, #1f2937);
	}

	.nav-label {
		font-size: 0.9375rem;
		font-weight: 600;
		color: var(--text-primary, #1f2937);
		background: none;
		border: none;
		cursor: pointer;
		padding: 0.25rem 0.75rem;
		border-radius: 0.375rem;
		transition: background 0.15s;
	}

	.nav-label:hover {
		background: var(--surface-primary, #f8fafc);
	}

	/* Grid */
	.calendar-grid {
		padding: 0.5rem;
	}

	.grid-header {
		display: grid;
		grid-template-columns: repeat(7, 1fr);
		gap: 2px;
		margin-bottom: 2px;
	}

	.grid-header-cell {
		text-align: center;
		font-size: 0.75rem;
		font-weight: 600;
		color: var(--text-secondary, #64748b);
		padding: 0.375rem 0;
		text-transform: uppercase;
		letter-spacing: 0.025em;
	}

	.grid-row {
		display: grid;
		grid-template-columns: repeat(7, 1fr);
		gap: 2px;
	}

	.grid-cell {
		aspect-ratio: 1;
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: flex-start;
		padding: 0.25rem;
		border-radius: 0.375rem;
		cursor: default;
		transition: background 0.1s;
		min-height: 2.5rem;
	}

	.grid-cell-empty {
		background: transparent;
	}

	.grid-cell:not(.grid-cell-empty):hover {
		background: var(--surface-primary, #f8fafc);
	}

	.grid-cell-weekend {
		background: var(--surface-primary, #f8fafc);
	}

	.grid-cell-weekend:hover {
		background: var(--border-subtle, #e2e8f0);
	}

	.grid-cell-today {
		background: var(--accent-primary-light, #e0f2fe);
	}

	.grid-cell-today:hover {
		background: var(--accent-primary-light, #e0f2fe);
	}

	.grid-cell-has-entries {
		cursor: pointer;
	}

	/* Day number */
	.day-number {
		font-size: 0.8125rem;
		color: var(--text-primary, #1f2937);
		line-height: 1;
	}

	.day-number-today {
		font-weight: 700;
		color: var(--accent-primary, #0ea5e9);
	}

	/* Dots */
	.day-dots {
		display: flex;
		gap: 2px;
		margin-top: 0.125rem;
		flex-wrap: wrap;
		justify-content: center;
	}

	.day-dot {
		width: 6px;
		height: 6px;
		border-radius: 50%;
		flex-shrink: 0;
	}

	.day-dot-more {
		font-size: 0.5625rem;
		color: var(--text-secondary, #64748b);
		line-height: 6px;
	}

	/* Legend */
	.calendar-legend {
		display: flex;
		gap: 1rem;
		flex-wrap: wrap;
		padding: 0.625rem 1rem;
		border-top: 1px solid var(--border-subtle, #e2e8f0);
	}

	.legend-item {
		display: flex;
		align-items: center;
		gap: 0.375rem;
		font-size: 0.75rem;
		color: var(--text-secondary, #64748b);
	}

	.legend-dot {
		width: 8px;
		height: 8px;
		border-radius: 50%;
		flex-shrink: 0;
	}

	/* Tooltip */
	.tooltip {
		position: fixed;
		transform: translate(-50%, -100%);
		margin-top: -0.5rem;
		background: var(--text-primary, #1f2937);
		color: white;
		padding: 0.5rem 0.75rem;
		border-radius: 0.5rem;
		font-size: 0.75rem;
		z-index: 400;
		pointer-events: none;
		max-width: 250px;
		box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
	}

	.tooltip-entry {
		display: flex;
		align-items: center;
		gap: 0.375rem;
		white-space: nowrap;
	}

	.tooltip-entry + .tooltip-entry {
		margin-top: 0.25rem;
	}

	.tooltip-dot {
		width: 6px;
		height: 6px;
		border-radius: 50%;
		flex-shrink: 0;
	}

	.tooltip-label {
		overflow: hidden;
		text-overflow: ellipsis;
	}

	/* Responsive */
	@media (min-width: 768px) {
		.grid-cell {
			min-height: 3.5rem;
			padding: 0.375rem;
		}

		.day-number {
			font-size: 0.875rem;
		}

		.day-dot {
			width: 7px;
			height: 7px;
		}
	}
</style>
