import { test, expect, type Page } from "@playwright/test";

import { login } from "./auth";
test.setTimeout(140000);
async function fits(page: Page) {
    expect(
        await page.evaluate(
            () => document.documentElement.scrollWidth <= innerWidth + 1,
        ),
    ).toBeTruthy();
}

test("student directory and all profile sections work for read-only administrators", async ({
    page,
}, info) => {
    const errors: string[] = [];
    page.on("pageerror", (error) => errors.push(error.message));
    page.on("response", (response) => {
        if (
            response.status() >= 400 &&
            response.url().includes("127.0.0.1") &&
            !(
                response.status() === 429 &&
                new URL(response.url()).pathname === "/login"
            )
        )
            errors.push(`${response.status()} ${response.url()}`);
    });
    await login(page, "admin");
    await page.goto("/students");
    await expect(
        page.getByRole("heading", { name: "Student records", exact: true }),
    ).toBeVisible();
    await expect(
        page.getByRole("button", { name: "Add student", exact: true }),
    ).toHaveCount(0);
    await fits(page);
    await page.screenshot({
        path: `design/implementation/students-${info.project.name}.png`,
        fullPage: true,
    });
    await page
        .getByRole("textbox", { name: "Search student name or number" })
        .fill("Jamie Cruz");
    await page.getByRole("button", { name: "Search", exact: true }).click();
    await expect(page.locator("tbody tr")).toHaveCount(1);
    await page.getByRole("link", { name: "View student", exact: true }).click();
    await expect(
        page.getByRole("heading", { name: "Jamie Cruz", exact: true }),
    ).toBeVisible();
    await expect(
        page.getByRole("button", { name: "Edit details", exact: true }),
    ).toHaveCount(0);
    if (info.project.name === "mobile")
        await page
            .getByRole("button", { name: "Open menu", exact: true })
            .click();
    await expect(
        page.getByRole("link", { name: "Students", exact: true }),
    ).toHaveAttribute("aria-current", "page");
    if (info.project.name === "mobile")
        await page
            .getByRole("button", { name: "Close menu", exact: true })
            .click();
    await page.screenshot({
        path: `design/implementation/student-profile-${info.project.name}.png`,
        fullPage: true,
    });
    for (const name of [
        "Current records",
        "Grades",
        "Enrollment history",
        "Files",
    ]) {
        await page.getByRole("tab", { name, exact: true }).click();
        await expect(page.getByRole("tabpanel")).toBeVisible();
        await fits(page);
        if (name === "Grades")
            await page.screenshot({
                path: `design/implementation/student-grades-${info.project.name}.png`,
                fullPage: true,
            });
    }
    await expect(
        page.getByRole("button", { name: "Upload document", exact: true }),
    ).toHaveCount(0);
    await page.getByRole("tab", { name: "Overview", exact: true }).focus();
    await page.keyboard.press("ArrowRight");
    await expect(
        page.getByRole("tab", { name: "Current records", exact: true }),
    ).toHaveAttribute("aria-selected", "true");
    expect(errors).toEqual([]);
});

test("registrar creates a student and maintains details photo and private files", async ({
    page,
}, info) => {
    const errors: string[] = [];
    page.on("pageerror", (error) => errors.push(error.message));
    const number = `PROFILE-${Date.now()}-${info.project.name}`;
    await login(page, "registrar");
    await page.goto("/students");
    await page
        .getByRole("button", { name: "Add student", exact: true })
        .click();
    let dialog = page.getByRole("dialog");
    await dialog.getByLabel("First name", { exact: true }).fill("Profile");
    await dialog
        .getByLabel("Middle name (optional)", { exact: true })
        .fill("Sample");
    await dialog.getByLabel("Last name", { exact: true }).fill("Student");
    await dialog.getByLabel("Student number", { exact: true }).fill(number);
    await dialog
        .getByLabel("Home branch", { exact: true })
        .selectOption({ label: "Main campus" });
    await dialog
        .getByLabel("Phone (optional)", { exact: true })
        .fill("09170000000");
    await dialog
        .getByLabel("Parent or guardian (optional)", { exact: true })
        .fill("Sample Guardian");
    await dialog
        .getByRole("button", { name: "Create student", exact: true })
        .click();
    await expect(dialog).toHaveCount(0);
    await page
        .getByRole("textbox", { name: "Search student name or number" })
        .fill(number);
    await page.getByRole("button", { name: "Search", exact: true }).click();
    await expect(page.locator("tbody tr")).toHaveCount(1);
    await page.getByRole("link", { name: "View student", exact: true }).click();
    await expect(
        page.getByRole("heading", {
            name: "Profile Sample Student",
            exact: true,
        }),
    ).toBeVisible();
    await expect(
        page.getByText("Sample Guardian", { exact: true }),
    ).toBeVisible();
    await page
        .getByRole("button", { name: "Edit details", exact: true })
        .click();
    dialog = page.getByRole("dialog");
    await dialog.getByLabel("Address (optional)").fill("Sample school road");
    await dialog
        .getByRole("button", { name: "Save student details", exact: true })
        .click();
    await expect(dialog).toHaveCount(0);
    await expect(
        page.getByText("Sample school road", { exact: true }),
    ).toBeVisible();
    const samplePhoto = await page.locator(".student-avatar").screenshot();
    await page.getByRole("button", { name: "Add photo", exact: true }).click();
    dialog = page.getByRole("dialog");
    await dialog.getByLabel("Photo", { exact: true }).setInputFiles({
        name: "sample.png",
        mimeType: "image/png",
        buffer: samplePhoto,
    });
    await dialog
        .getByRole("button", { name: "Save photo", exact: true })
        .click();
    await expect(dialog).toHaveCount(0);
    const image = page.getByRole("img", {
        name: "Photo of Profile Sample Student",
        exact: true,
    });
    await expect(image).toBeVisible();
    await expect
        .poll(() =>
            image.evaluate((img) => (img as HTMLImageElement).naturalWidth),
        )
        .toBeGreaterThan(0);
    await page.getByRole("tab", { name: "Files", exact: true }).click();
    await page
        .getByRole("button", { name: "Upload document", exact: true })
        .click();
    dialog = page.getByRole("dialog");
    await dialog
        .getByLabel("Document title", { exact: true })
        .fill("Sample admission record");
    await dialog
        .getByLabel("Category", { exact: true })
        .selectOption("admission");
    const body = "Sample student document for browser verification.";
    await dialog.getByLabel("File", { exact: true }).setInputFiles({
        name: "sample-admission.txt",
        mimeType: "text/plain",
        buffer: Buffer.from(body),
    });
    await dialog
        .getByRole("button", { name: "Upload document", exact: true })
        .click();
    await expect(dialog).toHaveCount(0);
    await expect(
        page.getByText("Sample admission record", { exact: true }),
    ).toBeVisible();
    const downloadPromise = page.waitForEvent("download");
    await page.getByRole("link", { name: "Download", exact: true }).click();
    const download = await downloadPromise;
    expect(download.suggestedFilename()).toBe("sample-admission.txt");
    const response = await page.request.get(
        (await page
            .getByRole("link", { name: "Download", exact: true })
            .getAttribute("href")) ?? "",
    );
    expect(response.ok()).toBeTruthy();
    expect(await response.text()).toBe(body);
    await fits(page);
    await page.reload();
    await page.getByRole("tab", { name: "Files", exact: true }).click();
    await expect(
        page.getByText("Sample admission record", { exact: true }),
    ).toBeVisible();
    expect(errors).toEqual([]);
});
