import type {
	CompanionType,
	KeyboardLayout,
	ScreenName,
	Progress,
	LessonPhase,
	TypingExerciseState,
} from "../types";
import { companions } from "../companion/characters";
import { saveProgress, getProgress } from "../storage/db";
import {
	createExerciseState,
	createWordExerciseState,
	getCurrentWordIndex,
	handleKeyPress,
	getCurrentLetter,
} from "../game/typing";
import { renderKeyboard, highlightKey, pressKey } from "../game/keyboard";
import { getLevelByNumber } from "../game/levels";
import { getLetterIntro } from "../companion/companion";
import { getWordsForLevel } from "../game/words";
import { playCorrectSound } from "../audio/sounds";
import { renderInlineMarkdown } from "../utils/markdown";

export function initWelcomeScreen(
	db: IDBDatabase,
	navigateTo: (screen: ScreenName) => void,
): void {
	let selectedCompanion: CompanionType | null = null;
	let selectedLayout: KeyboardLayout = "de";

	const grid = document.getElementById("companion-grid")!;
	const startBtn = document.getElementById("start-btn") as HTMLButtonElement;
	const layoutToggle = document.getElementById("layout-toggle")!;

	// Render companion cards
	companions.forEach((c) => {
		const card = document.createElement("button");
		card.className = "companion-card";
		card.dataset.companion = c.type;
		card.innerHTML = `
			<img class="companion-card__avatar" src="${c.avatarUrl}" alt="${c.name}"
				onerror="this.style.display='none'; this.nextElementSibling.style.display='block';">
			<span class="companion-card__emoji" style="display:none">${c.emoji}</span>
			<span class="companion-card__name">${c.name}</span>
		`;
		card.addEventListener("click", () => {
			grid.querySelectorAll(".companion-card").forEach((el) =>
				el.classList.remove("companion-card--selected"),
			);
			card.classList.add("companion-card--selected");
			selectedCompanion = c.type;
			startBtn.disabled = false;
		});
		grid.appendChild(card);
	});

	// Layout toggle
	layoutToggle.addEventListener("click", (e) => {
		const btn = (e.target as HTMLElement).closest(
			".layout-btn",
		) as HTMLButtonElement | null;
		if (!btn) return;
		layoutToggle
			.querySelectorAll(".layout-btn")
			.forEach((el) => el.classList.remove("layout-btn--active"));
		btn.classList.add("layout-btn--active");
		selectedLayout = btn.dataset.layout as KeyboardLayout;
	});

	// Start button
	startBtn.addEventListener("click", async () => {
		if (!selectedCompanion) return;
		const progress: Progress = {
			id: 1,
			currentLevel: 1,
			completedLevels: [],
			totalSessions: 0,
			sessionDates: [],
			selectedCharacter: selectedCompanion,
			selectedLayout: selectedLayout,
			totalCorrect: 0,
			totalErrors: 0,
			errorKeyCounts: {},
			lastPlayedLevels: [],
			currentForestPage: 0,
		};
		await saveProgress(db, progress);
		navigateTo("forest");
	});
}

// Finger description for companion letter intros
const fingerDescriptions: Record<string, string> = {
	f: "linker Zeigefinger",
	j: "rechter Zeigefinger",
	d: "linker Mittelfinger",
	k: "rechter Mittelfinger",
	s: "linker Ringfinger",
	l: "rechter Ringfinger",
	a: "linker kleiner Finger",
	ö: "rechter kleiner Finger",
	g: "linker Zeigefinger (Streckung)",
	h: "rechter Zeigefinger (Streckung)",
	e: "linker Mittelfinger (obere Reihe)",
	i: "rechter Mittelfinger (obere Reihe)",
	" ": "Daumen",
};

// Encouragement messages for repetition protection
const encouragementMessages = [
	"Magst du sehen, was als Nächstes kommt? Im Wald gibt es noch so viel zu entdecken!",
	"Der Wald wartet auf dich! Jedes Mal, wenn du übst, wächst etwas Neues.",
	"Schau mal, was sich im Wald versteckt! Probier es einfach noch einmal.",
	"Dein Wald wird immer schöner. Komm, wir entdecken zusammen weiter!",
];

export function initLessonScreen(
	db: IDBDatabase,
	level: number,
	layout: KeyboardLayout,
	onComplete: (
		level: number,
		stats: {
			totalCorrect: number;
			totalErrors: number;
			errorKeys: Record<string, number>;
		},
	) => void,
	onCancel?: () => void,
	isReview = false,
	showEncouragement = false,
): () => void {
	const letterArea = document.getElementById("letter-area")!;
	const keyboardContainer = document.getElementById("lesson-keyboard")!;
	const backBtn = document.getElementById(
		"lesson-back-btn",
	) as HTMLButtonElement;
	const phaseIndicator = document.getElementById("lesson-phase-indicator")!;
	const companionArea = document.getElementById("lesson-companion")!;
	const companionText = document.getElementById("lesson-companion-text")!;

	// Cumulative stats across all phases
	let cumulativeCorrect = 0;
	let cumulativeErrors = 0;
	const errorKeys: Record<string, number> = {};

	// Active keydown handler reference for cleanup
	let activeKeyDown: ((e: KeyboardEvent) => void) | null = null;
	let cancelled = false;

	function cleanup(): void {
		cancelled = true;
		if (activeKeyDown) {
			document.removeEventListener("keydown", activeKeyDown);
			activeKeyDown = null;
		}
		letterArea.innerHTML = "";
	}

	function setPhase(phase: LessonPhase): void {
		const labels: Record<LessonPhase, string> = {
			discover: "Entdecken",
			practice:
				"Jetzt kannst du üben! Drücke die Taste zu dem Buchstaben, der herunterfällt.",
			words: "Jetzt kommen ganze Wörter! Tippe die Buchstaben nacheinander ein.",
		};
		phaseIndicator.textContent = labels[phase];
	}

	// Show companion avatar
	let characterType: CompanionType = "fee";
	const progressPromise = getProgress(db).then((progress) => {
		if (!progress) return;
		characterType = progress.selectedCharacter;
		const companion = companions.find(
			(c) => c.type === progress.selectedCharacter,
		);
		if (!companion) return;
		const avatar = document.getElementById(
			"lesson-companion-avatar",
		) as HTMLImageElement;
		avatar.src = companion.avatarUrl;
		avatar.alt = companion.name;
		companionArea.style.display = "flex";
	});

	// Render keyboard
	renderKeyboard(keyboardContainer, layout, level);

	// --- Helper: run a letter exercise phase (practice or fallback) ---
	function runLetterExercise(
		state: TypingExerciseState,
		onDone: () => void,
	): void {
		function showCurrentLetter(): void {
			const letter = getCurrentLetter(state);
			if (!letter) return;
			letterArea.innerHTML = "";
			const letterEl = document.createElement("div");
			letterEl.className = "falling-letter";
			letterEl.textContent =
				letter === " " ? "\u2423" : letter.toUpperCase();
			letterArea.appendChild(letterEl);
			highlightKey(letter);
		}

		showCurrentLetter();

		function onKeyDown(e: KeyboardEvent): void {
			if (e.key.length > 1 && e.key !== " ") return;
			e.preventDefault();

			const expectedKey = getCurrentLetter(state);
			const result = handleKeyPress(state, e.key);
			pressKey(e.key);

			if (result.correct) {
				cumulativeCorrect++;
				playCorrectSound();
				const currentEl = letterArea.querySelector(".falling-letter");
				if (currentEl) {
					currentEl.classList.add("falling-letter--dissolve");
				}

				if (result.exerciseComplete) {
					document.removeEventListener("keydown", onKeyDown);
					activeKeyDown = null;
					onDone();
				} else {
					setTimeout(() => showCurrentLetter(), 300);
				}
			} else {
				cumulativeErrors++;
				if (expectedKey) {
					errorKeys[expectedKey] = (errorKeys[expectedKey] || 0) + 1;
				}
			}
		}

		if (activeKeyDown) {
			document.removeEventListener("keydown", activeKeyDown);
		}
		activeKeyDown = onKeyDown;
		document.addEventListener("keydown", onKeyDown);
	}

	// --- Helper: run word exercise phase ---
	function runWordExercise(
		state: TypingExerciseState,
		onDone: () => void,
	): void {
		function renderWordDisplay(): void {
			letterArea.innerHTML = "";
			if (!state.words || !state.wordBoundaries) return;

			const wordIdx = getCurrentWordIndex(state);
			const wordStart = state.wordBoundaries[wordIdx]!;
			const word = state.words[wordIdx]!;

			const container = document.createElement("div");
			container.className = "word-display";

			for (let i = 0; i < word.length; i++) {
				const span = document.createElement("span");
				span.className = "word-display__letter";
				const globalIdx = wordStart + i;
				if (globalIdx < state.currentLetterIndex) {
					span.classList.add("word-display__letter--done");
				} else if (globalIdx === state.currentLetterIndex) {
					span.classList.add("word-display__letter--active");
				}
				span.textContent = word[i]!.toUpperCase();
				container.appendChild(span);
			}

			letterArea.appendChild(container);

			// Highlight expected key on keyboard
			const currentLetter = getCurrentLetter(state);
			if (currentLetter) highlightKey(currentLetter);
		}

		renderWordDisplay();

		function onKeyDown(e: KeyboardEvent): void {
			if (e.key.length > 1 && e.key !== " ") return;
			e.preventDefault();

			const expectedKey = getCurrentLetter(state);
			const result = handleKeyPress(state, e.key);
			pressKey(e.key);

			if (result.correct) {
				cumulativeCorrect++;
				playCorrectSound();

				if (result.exerciseComplete) {
					document.removeEventListener("keydown", onKeyDown);
					activeKeyDown = null;
					onDone();
				} else {
					renderWordDisplay();
				}
			} else {
				cumulativeErrors++;
				if (expectedKey) {
					errorKeys[expectedKey] = (errorKeys[expectedKey] || 0) + 1;
				}
			}
		}

		if (activeKeyDown) {
			document.removeEventListener("keydown", activeKeyDown);
		}
		activeKeyDown = onKeyDown;
		document.addEventListener("keydown", onKeyDown);
	}

	// --- Phase flow ---

	async function startFlow(): Promise<void> {
		await progressPromise;
		if (cancelled) return;

		// Encouragement message before starting (repetition protection)
		if (showEncouragement) {
			companionText.textContent =
				encouragementMessages[
					Math.floor(Math.random() * encouragementMessages.length)
				]!;
			companionArea.style.display = "flex";
			await new Promise<void>((resolve) => setTimeout(resolve, 3000));
			if (cancelled) return;
		}

		// PHASE 1: DISCOVER (skip for reviews)
		if (!isReview) {
			await runDiscoverPhase();
			if (cancelled) return;
		}

		// PHASE 2: PRACTICE
		await runPracticePhase();
		if (cancelled) return;

		// PHASE 3: WORDS
		await runWordsPhase();
		if (cancelled) return;

		// All phases complete
		onComplete(level, {
			totalCorrect: cumulativeCorrect,
			totalErrors: cumulativeErrors,
			errorKeys,
		});
	}

	async function runDiscoverPhase(): Promise<void> {
		setPhase("discover");
		const levelDef = getLevelByNumber(level);
		if (!levelDef) return;

		for (const key of levelDef.newKeys) {
			if (cancelled) return;

			if (key === " ") {
				// Special space bar discover step
				companionText.textContent =
					"Siehst du die große Taste ganz unten? Das ist die Leertaste! Wenn du dieses Zeichen siehst: \u2423 \u2014 dann drückst du mit dem Daumen die Leertaste. Probier es aus!";
				companionArea.style.display = "flex";

				letterArea.innerHTML = "";
				const spaceLetterEl = document.createElement("div");
				spaceLetterEl.className = "falling-letter";
				spaceLetterEl.textContent = "\u2423";
				letterArea.appendChild(spaceLetterEl);
				const spaceLabelEl = document.createElement("div");
				spaceLabelEl.style.cssText =
					"text-align: center; font-size: 1.2rem; color: var(--text-secondary, #666); margin-top: 0.5rem; font-family: 'Quicksand', sans-serif;";
				spaceLabelEl.textContent = "Leertaste";
				letterArea.appendChild(spaceLabelEl);

				highlightKey(" ");
				const spaceKeyEl = document.querySelector(
					'[data-key=" "]',
				) as HTMLElement | null;
				if (spaceKeyEl) {
					spaceKeyEl.classList.add("keyboard__key--discover-pulse");
				}

				await new Promise<void>((resolve) => {
					function onSpaceDown(e: KeyboardEvent): void {
						if (e.key !== " ") return;
						e.preventDefault();
						pressKey(e.key);
						document.removeEventListener("keydown", onSpaceDown);
						activeKeyDown = null;
						if (spaceKeyEl) {
							spaceKeyEl.classList.remove(
								"keyboard__key--discover-pulse",
							);
						}
						resolve();
					}
					if (activeKeyDown) {
						document.removeEventListener("keydown", activeKeyDown);
					}
					activeKeyDown = onSpaceDown;
					document.addEventListener("keydown", onSpaceDown);
				});
				continue;
			}

			const fingerDesc = fingerDescriptions[key] || "ein Finger";
			const introText = await getLetterIntro(
				characterType,
				key.toUpperCase(),
				fingerDesc,
				db,
			);
			if (cancelled) return;

			// Show companion intro text
			companionText.innerHTML = renderInlineMarkdown(introText);
			companionArea.style.display = "flex";

			// Show the letter
			letterArea.innerHTML = "";
			const letterEl = document.createElement("div");
			letterEl.className = "falling-letter";
			letterEl.textContent = key.toUpperCase();
			letterArea.appendChild(letterEl);

			// Highlight and pulse the target key
			highlightKey(key);
			const keyEl = document.querySelector(
				`[data-key="${key}"]`,
			) as HTMLElement | null;
			if (keyEl) {
				keyEl.classList.add("keyboard__key--discover-pulse");
			}

			// Wait for child to press the correct key once
			await new Promise<void>((resolve) => {
				function onKeyDown(e: KeyboardEvent): void {
					if (e.key.length > 1 && e.key !== " ") return;
					e.preventDefault();
					pressKey(e.key);
					if (e.key.toLowerCase() === key.toLowerCase()) {
						document.removeEventListener("keydown", onKeyDown);
						activeKeyDown = null;
						if (keyEl) {
							keyEl.classList.remove(
								"keyboard__key--discover-pulse",
							);
						}
						resolve();
					}
				}
				if (activeKeyDown) {
					document.removeEventListener("keydown", activeKeyDown);
				}
				activeKeyDown = onKeyDown;
				document.addEventListener("keydown", onKeyDown);
			});
		}

		// Clear discover UI
		letterArea.innerHTML = "";
		companionText.textContent = "";
	}

	async function runPracticePhase(): Promise<void> {
		setPhase("practice");
		const state = createExerciseState(level);
		return new Promise<void>((resolve) => {
			runLetterExercise(state, resolve);
		});
	}

	async function runWordsPhase(): Promise<void> {
		setPhase("words");
		const wordCount = 4;
		let words: string[];
		if (isReview) {
			// Mix words from current and previous 1-2 levels
			const levelsToMix = [level];
			if (level > 1) levelsToMix.push(level - 1);
			if (level > 2) levelsToMix.push(level - 2);
			words = [];
			for (const lvl of levelsToMix) {
				words.push(...getWordsForLevel(lvl, 2));
			}
			// Shuffle and take wordCount
			for (let i = words.length - 1; i > 0; i--) {
				const j = Math.floor(Math.random() * (i + 1));
				[words[i], words[j]] = [words[j]!, words[i]!];
			}
			words = words.slice(0, wordCount);
		} else {
			words = getWordsForLevel(level, wordCount);
			if (words.length < 3) {
				words = getWordsForLevel(level, 3);
			}
		}

		if (words.length === 0) {
			// Fallback: skip words phase if no words available
			return;
		}

		const state = createWordExerciseState(words);
		return new Promise<void>((resolve) => {
			runWordExercise(state, resolve);
		});
	}

	// Start the flow
	startFlow();

	// Back button to cancel lesson
	backBtn.onclick = () => {
		cleanup();
		if (onCancel) onCancel();
	};

	// Return cleanup function
	return cleanup;
}
