import type { TypingExerciseState } from "../types";
import { getKeysUpToLevel } from "./levels";

const MIN_LETTERS = 8;
const MAX_LETTERS = 12;
const INITIAL_INTERVAL = 3000;
const INTERVAL_DECREASE = 200;
const INTERVAL_INCREASE = 500;
const MIN_INTERVAL = 1500;
const MAX_INTERVAL = 4000;
const STREAK_THRESHOLD = 2;

export interface KeyPressResult {
	correct: boolean;
	exerciseComplete: boolean;
	newInterval: number;
}

export function generateLetters(level: number): string[] {
	const keys = getKeysUpToLevel(level);
	const letterKeys = keys.filter((k) => k !== " ");
	const count =
		MIN_LETTERS + Math.floor(Math.random() * (MAX_LETTERS - MIN_LETTERS + 1));
	const letters: string[] = [];
	for (let i = 0; i < count; i++) {
		if (keys.includes(" ") && Math.random() < 0.2) {
			letters.push(" ");
		} else {
			letters.push(letterKeys[Math.floor(Math.random() * letterKeys.length)]!);
		}
	}
	return letters;
}

export function createExerciseState(level: number): TypingExerciseState {
	return {
		currentLetterIndex: 0,
		letters: generateLetters(level),
		intervalMs: INITIAL_INTERVAL,
		correctStreak: 0,
		totalCorrect: 0,
		totalErrors: 0,
		mode: "letters",
		words: undefined,
		wordBoundaries: undefined,
	};
}

export function createWordExerciseState(words: string[]): TypingExerciseState {
	const letters: string[] = [];
	const wordBoundaries: number[] = [];
	for (const word of words) {
		wordBoundaries.push(letters.length);
		for (const ch of word) {
			letters.push(ch);
		}
	}
	return {
		currentLetterIndex: 0,
		letters,
		intervalMs: 0,
		correctStreak: 0,
		totalCorrect: 0,
		totalErrors: 0,
		mode: "words",
		words,
		wordBoundaries,
	};
}

export function getCurrentWordIndex(state: TypingExerciseState): number {
	if (!state.wordBoundaries || state.wordBoundaries.length === 0) return 0;
	let wordIndex = 0;
	for (let i = 0; i < state.wordBoundaries.length; i++) {
		if (state.wordBoundaries[i]! <= state.currentLetterIndex) {
			wordIndex = i;
		} else {
			break;
		}
	}
	return wordIndex;
}

export function handleKeyPress(
	state: TypingExerciseState,
	pressedKey: string,
): KeyPressResult {
	const expectedKey = state.letters[state.currentLetterIndex]!;
	const correct = pressedKey.toLowerCase() === expectedKey.toLowerCase();

	if (correct) {
		state.currentLetterIndex++;
		state.totalCorrect++;
		state.correctStreak++;

		if (state.correctStreak >= STREAK_THRESHOLD) {
			state.intervalMs = Math.max(
				MIN_INTERVAL,
				state.intervalMs - INTERVAL_DECREASE,
			);
			state.correctStreak = 0;
		}
	} else {
		state.totalErrors++;
		state.correctStreak = 0;
		state.intervalMs = Math.min(
			MAX_INTERVAL,
			state.intervalMs + INTERVAL_INCREASE,
		);
	}

	return {
		correct,
		exerciseComplete: state.currentLetterIndex >= state.letters.length,
		newInterval: state.intervalMs,
	};
}

export function getCurrentLetter(state: TypingExerciseState): string | null {
	if (state.currentLetterIndex >= state.letters.length) return null;
	return state.letters[state.currentLetterIndex]!;
}

export function isExerciseComplete(state: TypingExerciseState): boolean {
	return state.currentLetterIndex >= state.letters.length;
}
