import { Page } from "playwright-core";
import { randomBytes } from "crypto";
import { resolve, join } from "path";
import { fireEvent } from "@testing-library/vue";

const sampleFiles = ["smut.md", "smut-2.md", "somno.md"];

export function rand(min: number, max: number) {
	return Math.floor(Math.random() * (max - min + 1)) + min;
}

async function fillCharacters(page: Page, fieldId: string, count: number) {
	const el = page.getByTestId(fieldId);
	const inp = el.locator("input");
	await inp.focus();
	let existingIndices: number[] = [];

	while (existingIndices.length <= count) {
		let downPresses = rand(1, 4);
		if (existingIndices.includes(downPresses)) {
			continue;
		}
		existingIndices.push(downPresses);
	}
	for (let k = 0; k < existingIndices.length; k++) {
		await inp.focus();
		await inp.press("ArrowDown");
		for (let l = 0; l < existingIndices[k]; l++) {
			await inp.press("ArrowDown");
		}
		await inp.press("Escape");
	}
	await inp.press("Enter");
}

async function fillRelationships(page: Page, id: string) {
	const add = page.getByTestId(`${id}.form.relationships.add`);
	for (let i = 0; i < rand(1, 3); i++) {
		await add.click();

		const pairingMembers = rand(2, 3);

		await fillCharacters(page, `${id}.form.relationships.${i}`, pairingMembers);
	}
}

async function uploadOrPaste(page: Page, selector: string, index: number) {
	const uop = rand(1, 2) == 1;
	const innerSel = `${selector}.form.uploadOrPaste`;
	if (uop) {
		const fileChoosePromise = page.waitForEvent("filechooser");
		const el = page.getByTestId(`${innerSel}.radio.upload`);
		await el.click();
		const ubtn = page.getByTestId(`${innerSel}.upload`);
		await ubtn.click();
		const fc = await fileChoosePromise;
		await fc.setFiles(join(resolve(import.meta.dirname, "../../tests/inputFiles"), sampleFiles[rand(0, 2)]));
	} else {
		const el = page.getByTestId(`${innerSel}.radio.pasteOrType`);
		await el.click();
		const content = page.getByTestId(`${innerSel}.type`).frameLocator("iframe").locator("[contenteditable]");
		await content.pressSequentially(
			randomBytes(148)
				.toString("base64")
				.match(/.{1,2}/g)!
				.join(" "),
		);
		await content.focus();
		await content.press("Enter");
		await content.press("Enter");
		await content.pressSequentially(`--- end of chapter ${index + 1} ---`.toLocaleUpperCase());
	}
}

export async function partialChapter(page: Page, i: number) {
	const b = `storyform.chapters[${i}]`;
	const collapse = page.getByTestId(`${b}.collapse`);
	await collapse.click();
	await page.waitForTimeout(3000);
	const inp = page.getByTestId(`${b}.form.title`);
	const summary = page.getByTestId(`${b}.form.summary`).frameLocator("iframe").locator("[contenteditable]");
	const notes = page.getByTestId(`${b}.form.notes`).frameLocator("iframe").locator("[contenteditable]");

	await inp.pressSequentially(`~ ${i + 1} ~`);
	await summary.press("Control+A");
	await summary.press("Backspace");
	await summary.pressSequentially(
		randomBytes(25)
			.toString("hex")
			.match(/.{1,2}/g)!
			.join(" "),
	);
	await notes.pressSequentially("these are some notes. Brian Tatler fucked and abused Sean Harris!");
	await notes.focus();
	await notes.press("Enter");
	await notes.press("Enter");
	await notes.pressSequentially("0x" + i.toString(16));
}

export async function fillChapter(page: Page, i: number) {
	const b = `storyform.chapters[${i}]`;
	const nsfwBool = rand(1, 2) == 2;

	const bands = page.getByTestId(`${b}.form.bands`);
	const bandInput = bands.locator("input");
	const genre = page.getByTestId(`${b}.form.genre`);
	const genreInput = genre.locator("input");

	await partialChapter(page, i);
	await bandInput.pressSequentially("Diamond Head");
	await bandInput.press("Enter");
	await bandInput.press("Escape");
	await fillCharacters(page, `${b}.form.characters`, rand(2, 4));
	await fillRelationships(page, b);
	const nsfw = page.getByTestId(`${b}.form.nsfw`);
	nsfwBool && (await nsfw.click());
	nsfwBool && (await page.getByTestId(`${b}.form.loggedInOnly`).click());
	await genreInput.focus();
	await genreInput.pressSequentially("S");
	await genreInput.press("Enter");
	await uploadOrPaste(page, b, i);
}

export async function collapseSidebar(page: Page) {
	await page.locator(".ant-layout-sider-zero-width-trigger").click();
}

// vue stuff