import { MantineProvider, v8CssVariablesResolver } from "@mantine/core";
import { extractHeadings, markdownSourceFromString, parseMarkdownTree } from "@src/lib/markdown";
import { MarkdownViewer } from "@src/primitives/MarkdownViewer";
import { MANTINE_THEME } from "@src/theme/mantine";
import type { ReactElement } from "react";
import { renderToString } from "react-dom/server";
import { beforeAll, describe, expect, it } from "vitest";

beforeAll(() => {
    if (typeof window !== "undefined" && typeof window.matchMedia !== "function") {
        Object.defineProperty(window, "matchMedia", {
            writable: true,
            value: (query: string) => ({
                matches: false,
                media: query,
                onchange: null,
                addListener: () => {},
                removeListener: () => {},
                addEventListener: () => {},
                removeEventListener: () => {},
                dispatchEvent: () => false,
            }),
        });
    }
});

function shell(node: ReactElement): string {
    return renderToString(
        <MantineProvider
            theme={MANTINE_THEME}
            cssVariablesResolver={v8CssVariablesResolver}
            forceColorScheme="dark"
        >
            {node}
        </MantineProvider>,
    );
}

describe("MarkdownViewer / features", () => {
    it("renders bare URL autolinks as links", () => {
        const html = shell(<MarkdownViewer content="Visit https://example.com today." />);
        expect(html).toContain('href="https://example.com"');
        expect(html).toContain("https://example.com");
    });

    it("renders www autolinks with https href", () => {
        const html = shell(<MarkdownViewer content="Go to www.example.com" />);
        expect(html).toContain('href="https://www.example.com"');
    });

    it("renders inline <u> and inline <Since /> with default components", () => {
        const html = shell(
            <MarkdownViewer content={'Text <u>underlined</u> and <Since v="2.0.0" /> here.'} />,
        );
        expect(html).toContain("<u>");
        expect(html).toContain("underlined");
        expect(html).toContain("2.0.0");
        expect(html).not.toContain("<Since");
        expect(html).not.toMatch(/<p[^>]*>underlined<\/p>/);
    });

    it("uses custom heading id from {#suffix}", () => {
        const html = shell(<MarkdownViewer content="## Visible {#my-anchor}" />);
        expect(html).toMatch(/id="my-anchor"/);
        expect(html).toContain('href="#my-anchor"');
        expect(html).not.toContain("{#my-anchor}");
    });

    it("extractHeadings respects custom {#id}", () => {
        const source = "## Title {#custom}\n";
        const tree = parseMarkdownTree(source);
        const headings = extractHeadings(tree, markdownSourceFromString(source));
        expect(headings[0]?.id).toBe("custom");
        expect(headings[0]?.text).toBe("Title");
    });

    it("preserves ordered list start attribute", () => {
        const html = shell(
            <MarkdownViewer
                content={`3. Third step
4. Fourth step`}
            />,
        );
        expect(html).toMatch(/start="3"/);
        expect(html).toContain("3.");
        expect(html).toContain("4.");
    });

    it("renders HTML table cells with markdown and inline HTML", () => {
        const html = shell(
            <MarkdownViewer
                content={`<table>
<thead><tr><th>Fn</th></tr></thead>
<tbody><tr><td>**bold** and <code>x</code></td></tr></tbody>
</table>`}
            />,
        );
        expect(html).toContain("<table");
        expect(html).toContain("bold");
        expect(html).toContain("<code");
    });

    it("renders default Button component", () => {
        const html = shell(
            <MarkdownViewer content={'<Button label="Go" url="https://surrealdb.com" />'} />,
        );
        expect(html).toContain("Go");
        expect(html).toContain('href="https://surrealdb.com"');
    });
});
