import { describe, expect, it } from "vitest";
import { getKeysUpToLevel, getLevelByNumber, levels } from "./levels";

describe("levels", () => {
	it("has exactly 16 entries", () => {
		expect(levels).toHaveLength(16);
	});

	it("Level 1 newKeys = ['f', 'j', ' ']", () => {
		expect(levels[0]!.newKeys).toEqual(["f", "j", " "]);
	});

	it("Level 2 newKeys = ['d', 'k']", () => {
		expect(levels[1]!.newKeys).toEqual(["d", "k"]);
	});

	it("Level 3 newKeys = ['s', 'l']", () => {
		expect(levels[2]!.newKeys).toEqual(["s", "l"]);
	});

	it("Level 4 newKeys = ['a', 'ö']", () => {
		expect(levels[3]!.newKeys).toEqual(["a", "ö"]);
	});

	it("Level 5 newKeys = ['g', 'h']", () => {
		expect(levels[4]!.newKeys).toEqual(["g", "h"]);
	});

	it("Level 6 newKeys = ['e', 'i']", () => {
		expect(levels[5]!.newKeys).toEqual(["e", "i"]);
	});

	it("Level 7 newKeys = ['r', 'u']", () => {
		expect(levels[6]!.newKeys).toEqual(["r", "u"]);
	});

	it("Level 8 newKeys = ['t', 'z']", () => {
		expect(levels[7]!.newKeys).toEqual(["t", "z"]);
	});

	it("Level 9 newKeys = ['w', 'o']", () => {
		expect(levels[8]!.newKeys).toEqual(["w", "o"]);
	});

	it("Level 10 newKeys = ['q', 'p']", () => {
		expect(levels[9]!.newKeys).toEqual(["q", "p"]);
	});

	it("Level 11 newKeys = ['n', 'b']", () => {
		expect(levels[10]!.newKeys).toEqual(["n", "b"]);
	});

	it("Level 12 newKeys = ['v', 'm']", () => {
		expect(levels[11]!.newKeys).toEqual(["v", "m"]);
	});

	it("Level 13 newKeys = ['c', 'x']", () => {
		expect(levels[12]!.newKeys).toEqual(["c", "x"]);
	});

	it("Level 14 newKeys = ['ä', 'ü']", () => {
		expect(levels[13]!.newKeys).toEqual(["ä", "ü"]);
	});

	it("Level 15 newKeys = ['y', ',']", () => {
		expect(levels[14]!.newKeys).toEqual(["y", ","]);
	});

	it("Level 16 newKeys = ['.']", () => {
		expect(levels[15]!.newKeys).toEqual(["."]);
	});

	it("Level 3 allKeys includes all keys from levels 1-3", () => {
		const expected = ["f", "j", " ", "d", "k", "s", "l"];
		for (const key of expected) {
			expect(levels[2]!.allKeys).toContain(key);
		}
		expect(levels[2]!.allKeys).toHaveLength(expected.length);
	});

	it("Level 6 allKeys contains 13 keys", () => {
		expect(levels[5]!.allKeys).toHaveLength(13);
		const expected = [
			"f",
			"j",
			" ",
			"d",
			"k",
			"s",
			"l",
			"a",
			"ö",
			"g",
			"h",
			"e",
			"i",
		];
		for (const key of expected) {
			expect(levels[5]!.allKeys).toContain(key);
		}
	});

	it("Level 16 allKeys contains all QWERTZ keys", () => {
		const expected = "fjdkslagöheiruztwopqnbvmcxäüy,.".split("").concat([" "]);
		expect(levels[15]!.allKeys).toHaveLength(expected.length);
		for (const key of expected) {
			expect(levels[15]!.allKeys).toContain(key);
		}
	});

	it("each key in allKeys has a fingerMap entry", () => {
		for (const level of levels) {
			for (const key of level.allKeys) {
				expect(level.fingerMap[key]).toBeDefined();
				expect(level.fingerMap[key]).toMatch(/^--finger-/);
			}
		}
	});
});

describe("getLevelByNumber", () => {
	it("returns level 1 object", () => {
		const level = getLevelByNumber(1);
		expect(level).toBeDefined();
		expect(level?.level).toBe(1);
		expect(level?.newKeys).toEqual(["f", "j", " "]);
	});

	it("returns undefined for non-existent level", () => {
		expect(getLevelByNumber(99)).toBeUndefined();
	});
});

describe("getKeysUpToLevel", () => {
	it("returns cumulative keys for levels 1-3", () => {
		const keys = getKeysUpToLevel(3);
		const expected = ["f", "j", " ", "d", "k", "s", "l"];
		expect(keys).toHaveLength(expected.length);
		for (const key of expected) {
			expect(keys).toContain(key);
		}
	});

	it("returns empty array for non-existent level", () => {
		expect(getKeysUpToLevel(99)).toEqual([]);
	});
});
