import { bibleBooks, type BibleBook } from '$lib/types/bible';

export interface Guess {
	book: BibleBook;
	testamentMatch: boolean;
	sectionMatch: boolean;
	adjacent: boolean;
	firstLetterMatch: boolean;
}

export function getBookById(id: string): BibleBook | undefined {
	return bibleBooks.find((b) => b.id === id);
}

export function isAdjacent(id1: string, id2: string): boolean {
	const b1 = getBookById(id1);
	const b2 = getBookById(id2);
	return !!(b1 && b2 && Math.abs(b1.order - b2.order) === 1);
}

export function getFirstLetter(bookName: string): string {
	const match = bookName.match(/[a-zA-Z]/);
	return match ? match[0] : bookName[0];
}

export function evaluateGuess(guessBookId: string, correctBookId: string): Guess | null {
	const book = getBookById(guessBookId);
	const correctBook = getBookById(correctBookId);
	if (!book || !correctBook) return null;

	const testamentMatch = book.testament === correctBook.testament;
	const sectionMatch = book.section === correctBook.section;
	const adjacent = isAdjacent(guessBookId, correctBookId);

	// Special case: if correct book is in the Epistles + starts with "1",
	// any guess starting with "1" counts as first letter match
	const correctIsEpistlesWithNumber =
		(correctBook.section === "Pauline Epistles" ||
			correctBook.section === "General Epistles") &&
		correctBook.name[0] === "1";
	const guessIsEpistlesWithNumber =
		(book.section === "Pauline Epistles" ||
			book.section === "General Epistles") &&
		book.name[0] === "1";

	const firstLetterMatch =
		correctIsEpistlesWithNumber && guessIsEpistlesWithNumber
			? true
			: getFirstLetter(book.name).toUpperCase() ===
				getFirstLetter(correctBook.name).toUpperCase();

	return {
		book,
		testamentMatch,
		sectionMatch,
		adjacent,
		firstLetterMatch,
	};
}

export function getGrade(numGuesses: number): string {
	if (numGuesses === 1) return "S+";
	if (numGuesses === 2) return "A+";
	if (numGuesses === 3) return "A";
	if (numGuesses >= 4 && numGuesses <= 6) return "B+";
	if (numGuesses >= 7 && numGuesses <= 10) return "B";
	if (numGuesses >= 11 && numGuesses <= 15) return "C+";
	return "C";
}

export function getNextGradeMessage(numGuesses: number): string {
	if (numGuesses === 1) return "";
	if (numGuesses === 2) return "Next grade: 1 guess or less";
	if (numGuesses === 3) return "Next grade: 2 guesses or less";
	if (numGuesses >= 4 && numGuesses <= 6) return "Next grade: 3 guesses or less";
	if (numGuesses >= 7 && numGuesses <= 10) return "Next grade: 6 guesses or less";
	if (numGuesses >= 11 && numGuesses <= 15) return "Next grade: 10 guesses or less";
	return "Next grade: 15 guesses or less";
}

export function toOrdinal(n: number): string {
	if (n % 100 >= 11 && n % 100 <= 13) {
		return `${n}th`;
	}
	const mod = n % 10;
	const suffix = mod === 1 ? "st" : mod === 2 ? "nd" : mod === 3 ? "rd" : "th";
	return `${n}${suffix}`;
}

export function generateUUID(): string {
	if (typeof window !== 'undefined' && typeof (window as any).crypto?.randomUUID === "function") {
		return (window as any).crypto.randomUUID();
	}
	// Fallback
	return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
		const r = ((window as any).crypto.getRandomValues(new Uint8Array(1))[0] % 16) | 0;
		const v = c === "x" ? r : (r & 0x3) | 0x8;
		return v.toString(16);
	});
}
