import { EditorSelection } from "@codemirror/state";
import * as MarkdownStories from "@src/stories/playground/Markdown.stories";
import { composeStories } from "@storybook/react-vite";
import { describe, expect, it } from "vitest";
import { getEditorView, mountStory, nextFrame } from "../../_setup/e2e-helpers";

const Stories = composeStories(MarkdownStories);

function clickControl(label: string): boolean {
    const button = document.querySelector<HTMLButtonElement>(`button[aria-label="${label}"]`);
    if (!button) return false;
    button.dispatchEvent(new MouseEvent("mousedown", { bubbles: true, button: 0 }));
    button.dispatchEvent(new MouseEvent("click", { bubbles: true, button: 0 }));
    return true;
}

describe("MarkdownEditor / table controls", () => {
    it("adds and removes rows and columns from the active table", async () => {
        mountStory(<Stories.EditorTableFormatter />);
        const view = await getEditorView();
        await nextFrame();

        // Park the caret inside the table to reveal the floating controls.
        const adaPos = view.state.doc.toString().indexOf("Ada");
        view.dispatch({ selection: EditorSelection.cursor(adaPos) });
        view.focus();
        await nextFrame();
        await nextFrame();

        const tableLines = () =>
            view.state.doc
                .toString()
                .split("\n")
                .filter((l) => l.includes("|"));
        const headerPipes = () => (tableLines()[0]?.match(/\|/g) ?? []).length;

        const beforeCols = headerPipes();
        const beforeRows = tableLines().length;

        expect(clickControl("Add column")).toBe(true);
        await nextFrame();
        expect(headerPipes()).toBe(beforeCols + 1);

        expect(clickControl("Add row")).toBe(true);
        await nextFrame();
        expect(tableLines().length).toBe(beforeRows + 1);

        expect(clickControl("Remove row")).toBe(true);
        await nextFrame();
        expect(tableLines().length).toBe(beforeRows);

        expect(clickControl("Remove column")).toBe(true);
        await nextFrame();
        expect(headerPipes()).toBe(beforeCols);
    });
});
