<script lang="ts">
	import { onDestroy, onMount } from 'svelte';
	import YesterdayCharacter from '$lib/components/YesterdayCharacter.svelte';
	import HintsPanel from '$lib/components/HintsPanel.svelte';
	import CharacterSearchInput from '$lib/components/CharacterSearchInput.svelte';
	import GuessHistoryTable from '$lib/components/GuessHistoryTable.svelte';
	import WinPanel from '$lib/components/WinPanel.svelte';
	import FriendsTodaySection from '$lib/components/FriendsTodaySection.svelte';
	import type { CharacterWithRelations } from '$lib/server/daily-character.js';
	import { t } from '$lib/i18n';
	
	export let data;

	let selectedCharacters: CharacterWithRelations[] = [];
	let isLoaded = false;
	let isGeckoMoriaWin = false;
	
	let showOriginUnlock = false;
	let showFruitUnlock = false;
	let showAffiliationUnlock = false;
	let originUnlockTimeout: ReturnType<typeof setTimeout> | null = null;
	let fruitUnlockTimeout: ReturnType<typeof setTimeout> | null = null;
	let affiliationUnlockTimeout: ReturnType<typeof setTimeout> | null = null;

	function clearUnlockTimeout(timeout: ReturnType<typeof setTimeout> | null) {
		if (timeout) {
			clearTimeout(timeout);
		}
	}

	function pulseUnlock(type: 'origin' | 'fruit' | 'affiliation') {
		if (type === 'origin') {
			clearUnlockTimeout(originUnlockTimeout);
			showOriginUnlock = true;
			originUnlockTimeout = setTimeout(() => {
				showOriginUnlock = false;
				originUnlockTimeout = null;
			}, 600);
			return;
		}

		if (type === 'fruit') {
			clearUnlockTimeout(fruitUnlockTimeout);
			showFruitUnlock = true;
			fruitUnlockTimeout = setTimeout(() => {
				showFruitUnlock = false;
				fruitUnlockTimeout = null;
			}, 600);
			return;
		}

		clearUnlockTimeout(affiliationUnlockTimeout);
		showAffiliationUnlock = true;
		affiliationUnlockTimeout = setTimeout(() => {
			showAffiliationUnlock = false;
			affiliationUnlockTimeout = null;
		}, 600);
	}

	function syncHintAvailability(previousGuessCount: number, nextGuessCount: number, animateUnlocks = false) {
		const nextOriginAvailable = nextGuessCount >= 5;
		const nextFruitAvailable = nextGuessCount >= 10;
		const nextAffiliationAvailable = nextGuessCount >= 15;

		if (animateUnlocks && nextOriginAvailable && previousGuessCount < 5) {
			pulseUnlock('origin');
		}

		if (animateUnlocks && nextFruitAvailable && previousGuessCount < 10) {
			pulseUnlock('fruit');
		}

		if (animateUnlocks && nextAffiliationAvailable && previousGuessCount < 15) {
			pulseUnlock('affiliation');
		}

		if (!nextOriginAvailable) {
			showOriginUnlock = false;
			clearUnlockTimeout(originUnlockTimeout);
			originUnlockTimeout = null;
		}

		if (!nextFruitAvailable) {
			showFruitUnlock = false;
			clearUnlockTimeout(fruitUnlockTimeout);
			fruitUnlockTimeout = null;
		}

		if (!nextAffiliationAvailable) {
			showAffiliationUnlock = false;
			clearUnlockTimeout(affiliationUnlockTimeout);
			affiliationUnlockTimeout = null;
		}

	}
	
	// Load from localStorage on mount
	onMount(() => {
		const storedDailyCharacterId = localStorage.getItem('dailyCurrentCharacterId');
		const dailyCurrentCharacterId = dailyCharacter?.id;
		
		// If the daily character has changed, clear the history
		if (storedDailyCharacterId && storedDailyCharacterId !== dailyCurrentCharacterId) {
			localStorage.removeItem('dailyCharacterHistory');
			selectedCharacters = [];
		} else {
			// Load existing history if the character hasn't changed
			const stored = localStorage.getItem('dailyCharacterHistory');
			if (stored) {
				try {
					const storedIds = JSON.parse(stored);
					// Reconstruct character objects from IDs
					if (Array.isArray(storedIds)) {
						selectedCharacters = storedIds
							.map((id: string) => data.characters.find((c: CharacterWithRelations) => c.id === id))
							.filter((c: CharacterWithRelations | undefined): c is CharacterWithRelations => !!c);
					}
				} catch (e) {
					console.error('Failed to parse stored history', e);
				}
			}
		}
		
		// Store the current daily character ID
		if (dailyCurrentCharacterId) {
			localStorage.setItem('dailyCurrentCharacterId', dailyCurrentCharacterId);
		}

		syncHintAvailability(0, selectedCharacters.length);
		
		isLoaded = true;
	});

	onDestroy(() => {
		clearUnlockTimeout(originUnlockTimeout);
		clearUnlockTimeout(fruitUnlockTimeout);
		clearUnlockTimeout(affiliationUnlockTimeout);
	});

	// Save to localStorage whenever selectedCharacters changes (only store IDs)
	$: if (isLoaded && selectedCharacters) {
		const ids = selectedCharacters.map(char => char.id);
		localStorage.setItem('dailyCharacterHistory', JSON.stringify(ids));
	}

	$: characters = data.characters || [];
	$: dailyCharacter = data.dailyCharacter;
	$: yesterdayCharacter = data.yesterdayCharacter;
	$: columnVisibility = data.columnVisibility || {};
	$: hasWon = selectedCharacters.some(char => char.id === dailyCharacter.id);
	
	function handleCharacterSelect(character: CharacterWithRelations) {
		selectCharacter(character);
	}
	
	function selectCharacter(character: CharacterWithRelations) {
		const previousGuessCount = selectedCharacters.length;
		selectedCharacters = [character, ...selectedCharacters];
		syncHintAvailability(previousGuessCount, selectedCharacters.length, isLoaded);
		
		// Check if player won
		if (character.id === dailyCharacter.id) {
			const triedCharacterIds = selectedCharacters.map(selected => selected.id);

			// Send request to record win in database
			fetch('/daily', {
				method: 'POST',
				headers: {
					'Content-Type': 'application/json'
				},
				body: JSON.stringify({
					characterId: dailyCharacter.id,
					tryCount: selectedCharacters.length,
					triedCharacterIds
				})
			}).catch(err => console.error('Failed to record win:', err));
			
			// Check if it's gecko_moria for special animation
			if (dailyCharacter.id === 'gecko_moria_gecko_moria') {
				isGeckoMoriaWin = true;
			}
		}
	}

	function resetHistory() {
		const previousGuessCount = selectedCharacters.length;
		selectedCharacters = [];
		syncHintAvailability(previousGuessCount, 0);
		localStorage.removeItem('dailyCharacterHistory');
	}
</script>

<svelte:head>
	<title>{$t.game.daily.metaTitle}</title>
	<style>
		@keyframes shadow-pulse {
			0% {
				text-shadow: 0 0 20px rgba(0, 0, 0, 0.5), 0 0 40px rgba(50, 50, 50, 0.8);
				opacity: 1;
			}
			50% {
				text-shadow: 0 0 60px rgba(0, 0, 0, 0.9), 0 0 100px rgba(30, 30, 30, 1), inset 0 0 50px rgba(0, 0, 0, 0.7);
				opacity: 0.9;
			}
			100% {
				text-shadow: 0 0 20px rgba(0, 0, 0, 0.5), 0 0 40px rgba(50, 50, 50, 0.8);
				opacity: 1;
			}
		}
		@keyframes moria-chaos {
			0% {
				transform: rotate(0deg) scale(1);
				filter: invert(0%) hue-rotate(0deg) blur(0px);
			}
			10% {
				transform: rotate(15deg) scale(1.02);
				filter: invert(30%) hue-rotate(45deg) blur(2px);
			}
			20% {
				transform: rotate(-10deg) scale(0.98);
				filter: invert(60%) hue-rotate(90deg) blur(1px);
			}
			30% {
				transform: rotate(25deg) scale(1.05);
				filter: invert(100%) hue-rotate(180deg) blur(3px);
			}
			40% {
				transform: rotate(-20deg) scale(0.95);
				filter: invert(80%) hue-rotate(270deg) blur(2px);
			}
			50% {
				transform: rotate(30deg) scale(1.08);
				filter: invert(100%) hue-rotate(0deg) blur(4px);
			}
			60% {
				transform: rotate(-25deg) scale(0.92);
				filter: invert(70%) hue-rotate(90deg) blur(2px);
			}
			70% {
				transform: rotate(20deg) scale(1.03);
				filter: invert(50%) hue-rotate(180deg) blur(3px);
			}
			80% {
				transform: rotate(-15deg) scale(1.01);
				filter: invert(80%) hue-rotate(270deg) blur(1px);
			}
			100% {
				transform: rotate(360deg) scale(1);
				filter: invert(0%) hue-rotate(360deg) blur(0px);
			}
		}
		.gecko-moria-effect {
			animation: shadow-pulse 1.5s ease-in-out infinite;
		}
		.moria-screen-chaos {
			animation: moria-chaos 4s ease-in-out;
		}
	</style>
</svelte:head>

<main
	class="relative min-h-screen overflow-hidden bg-slate-950 text-slate-100 {isGeckoMoriaWin ? 'moria-screen-chaos' : ''}"
>
	<div class="absolute inset-0 bg-linear-to-br from-slate-950/85 via-slate-900/60 to-slate-950/80"></div>
	<div class="absolute inset-0 mix-blend-screen opacity-20 bg-[radial-gradient(circle_at_top,rgba(255,215,84,0.35),transparent_55%)]"></div>

	<div class="relative mx-auto flex min-h-screen w-full max-w-6xl flex-col px-6 py-8 sm:py-10">
		<header class="flex flex-col items-start gap-6 w-full">
			<div class="flex w-full items-center justify-between gap-4">
				<div>
					<h1 class="text-3xl font-black uppercase tracking-[0.25em] text-amber-50 sm:text-5xl">
						{$t.game.daily.characterTitle}
					</h1>
					<p class="mt-2 text-sm text-amber-300">
						{data.winCount} {data.winCount > 1 ? $t.game.daily.winsPeoplePlural : $t.game.daily.winsPeopleSingular} {data.winCount > 1 ? $t.game.daily.winsVerbPlural : $t.game.daily.winsVerbSingular} {$t.game.daily.winsSuffix}
					</p>
				</div>
				{#if hasWon}
					<button 
						class="rounded-full border border-amber-200/40 bg-transparent px-5 py-3 text-sm font-semibold text-amber-100 transition hover:border-amber-200 hover:text-amber-50"
						onclick={resetHistory}
					>
						{$t.game.daily.reset}
					</button>
				{/if}
			</div>
			<p class="max-w-2xl text-base text-slate-200 sm:text-lg">
				{$t.game.daily.description}
			</p>
		</header>

		<section class="mt-10 grid gap-6">
			{#if selectedCharacters.length > 0 && !hasWon}
				<HintsPanel 
					{dailyCharacter} 
					{selectedCharacters}
					{showOriginUnlock}
					{showFruitUnlock}
					{showAffiliationUnlock}
				/>
			{/if}

			{#if hasWon}
				<WinPanel 
					selectedCharacter={dailyCharacter}
					{selectedCharacters}
					{isGeckoMoriaWin}
				/>
			{:else}
			<CharacterSearchInput 
				{characters}
				{selectedCharacters}
				onSelect={handleCharacterSelect}
			/>
			{/if}
		</section>


		{#if hasWon && data.friendsTodayResults && data.friendsTodayResults.length > 0}
			<FriendsTodaySection friendsTodayResults={data.friendsTodayResults} />
		{/if}

		<GuessHistoryTable 
			{selectedCharacters}
			{dailyCharacter}
			{columnVisibility}
		/>

		<YesterdayCharacter {yesterdayCharacter} />
	</div>
</main>
