import React from "react";
import { describe, it, expect, vi } from "vitest";
import { render, screen } from "@testing-library/react";
import { WikiLinkRenderer } from "../WikiLinkRenderer";

// Mock Next.js Link component
vi.mock("next/link", () => ({
  default: ({ children, href }: { children: React.ReactNode; href: string }): React.JSX.Element => {
    return <a href={href}>{children}</a>;
  },
}));

describe("WikiLinkRenderer", (): void => {
  it("renders plain HTML without wiki-links", (): void => {
    const html = "<p>This is plain <strong>HTML</strong> content.</p>";
    render(<WikiLinkRenderer html={html} />);

    expect(screen.getByText(/This is plain/)).toBeInTheDocument();
    expect(screen.getByText("HTML")).toBeInTheDocument();
  });

  it("converts basic wiki-links [[slug]] to anchor tags", (): void => {
    const html = "<p>Check out [[my-entry]] for more info.</p>";
    const { container } = render(<WikiLinkRenderer html={html} />);

    const link = container.querySelector('a[data-wiki-link="true"]');
    expect(link).toBeInTheDocument();
    expect(link).toHaveAttribute("href", "/knowledge/my-entry");
    expect(link).toHaveAttribute("data-slug", "my-entry");
    expect(link).toHaveTextContent("my-entry");
  });

  it("converts wiki-links with display text [[slug|text]]", (): void => {
    const html = "<p>Read the [[architecture|Architecture Guide]] please.</p>";
    const { container } = render(<WikiLinkRenderer html={html} />);

    const link = container.querySelector('a[data-wiki-link="true"]');
    expect(link).toBeInTheDocument();
    expect(link).toHaveAttribute("href", "/knowledge/architecture");
    expect(link).toHaveAttribute("data-slug", "architecture");
    expect(link).toHaveTextContent("Architecture Guide");
  });

  it("handles multiple wiki-links in the same content", (): void => {
    const html = "<p>See [[page-one]] and [[page-two|Page Two]] for details.</p>";
    const { container } = render(<WikiLinkRenderer html={html} />);

    const links = container.querySelectorAll('a[data-wiki-link="true"]');
    expect(links.length).toBe(2);

    expect(links[0]).toHaveAttribute("href", "/knowledge/page-one");
    expect(links[0]).toHaveTextContent("page-one");

    expect(links[1]).toHaveAttribute("href", "/knowledge/page-two");
    expect(links[1]).toHaveTextContent("Page Two");
  });

  it("handles wiki-links with whitespace", (): void => {
    const html = "<p>Check [[ my-entry ]] and [[ other-entry | Other Entry ]]</p>";
    const { container } = render(<WikiLinkRenderer html={html} />);

    const links = container.querySelectorAll('a[data-wiki-link="true"]');
    expect(links.length).toBe(2);

    // Whitespace should be trimmed
    expect(links[0]).toHaveAttribute("href", "/knowledge/my-entry");
    expect(links[1]).toHaveAttribute("href", "/knowledge/other-entry");
    expect(links[1]).toHaveTextContent("Other Entry");
  });

  it("escapes HTML in link text to prevent XSS", (): void => {
    const html = "<p>[[entry|<script>alert('xss')</script>]]</p>";
    const { container } = render(<WikiLinkRenderer html={html} />);

    const link = container.querySelector('a[data-wiki-link="true"]');
    expect(link).toBeInTheDocument();

    // Script tags should be escaped
    const linkHtml = link?.innerHTML ?? "";
    expect(linkHtml).not.toContain("<script>");
    expect(linkHtml).toContain("&lt;script&gt;");
  });

  it("preserves other HTML structure while converting wiki-links", (): void => {
    const html = `
      <h2>Title</h2>
      <p>Paragraph with [[link-one|Link One]].</p>
      <ul>
        <li>Item with [[link-two]]</li>
      </ul>
    `;
    const { container } = render(<WikiLinkRenderer html={html} />);

    // Should preserve HTML structure
    expect(container.querySelector("h2")).toBeInTheDocument();
    expect(container.querySelector("ul")).toBeInTheDocument();
    expect(container.querySelector("li")).toBeInTheDocument();

    // Should have converted wiki-links
    const links = container.querySelectorAll('a[data-wiki-link="true"]');
    expect(links.length).toBe(2);
  });

  it("applies custom className to wrapper div", (): void => {
    const html = "<p>Content</p>";
    const { container } = render(<WikiLinkRenderer html={html} className="custom-class" />);

    const wrapper = container.querySelector(".wiki-link-content");
    expect(wrapper).toHaveClass("custom-class");
  });

  it("applies wiki-link styling classes", (): void => {
    const html = "<p>[[test-link]]</p>";
    const { container } = render(<WikiLinkRenderer html={html} />);

    const link = container.querySelector('a[data-wiki-link="true"]');
    expect(link).toHaveClass("wiki-link");
    expect(link).toHaveClass("text-blue-600");
    expect(link).toHaveClass("dark:text-blue-400");
    expect(link).toHaveClass("underline");
  });

  it("handles encoded special characters in slugs", (): void => {
    const html = "<p>[[hello-world-2026]]</p>";
    const { container } = render(<WikiLinkRenderer html={html} />);

    const link = container.querySelector('a[data-wiki-link="true"]');
    expect(link).toHaveAttribute("href", "/knowledge/hello-world-2026");
  });

  it("does not convert malformed wiki-links", (): void => {
    const html = "<p>[[incomplete and [mismatched] brackets</p>";
    const { container } = render(<WikiLinkRenderer html={html} />);

    // Should not create wiki-links for malformed patterns
    const links = container.querySelectorAll('a[data-wiki-link="true"]');
    expect(links.length).toBe(0);

    // Original text should be preserved
    expect(container.textContent).toContain("[[incomplete");
  });

  it("handles nested HTML within paragraphs containing wiki-links", (): void => {
    const html = "<p>Text with <em>emphasis</em> and [[my-link|My Link]].</p>";
    const { container } = render(<WikiLinkRenderer html={html} />);

    // Should preserve nested HTML
    expect(container.querySelector("em")).toBeInTheDocument();

    // Should still convert wiki-link
    const link = container.querySelector('a[data-wiki-link="true"]');
    expect(link).toHaveAttribute("href", "/knowledge/my-link");
  });

  it("handles empty wiki-links gracefully", (): void => {
    const html = "<p>Empty link: [[]]</p>";
    const { container } = render(<WikiLinkRenderer html={html} />);

    // Should handle empty slugs (though they're not valid)
    // The regex should match but create a link with empty slug
    // Depending on implementation, this might create a link or skip it
    // Either way, it shouldn't crash
    expect(container.textContent).toContain("Empty link:");
  });

  it("memoizes processed HTML to avoid unnecessary re-parsing", (): void => {
    const html = "<p>[[test-link]]</p>";
    const { rerender, container } = render(<WikiLinkRenderer html={html} />);

    const firstLink = container.querySelector('a[data-wiki-link="true"]');
    expect(firstLink).toBeInTheDocument();

    // Re-render with same HTML
    rerender(<WikiLinkRenderer html={html} />);

    // Should still have the link (memoization test is implicit)
    const secondLink = container.querySelector('a[data-wiki-link="true"]');
    expect(secondLink).toBeInTheDocument();
  });
});
