import { describe, expect, it, vi } from "vitest";
import {
  computeDiffPreviewWithShiki,
} from "../src/dimsdk/ui/chat/diff-highlight.ts";
import {
  computeMarkdownCodeBlockPreviewWithShiki,
  computeReadPreviewWithShiki,
} from "../src/dimsdk/ui/chat/read-highlight.ts";

describe("ui chat highlight helpers", () => {
  it("builds markdown code block previews from typed shiki output", async () => {
    const codeToTokensBase = vi.fn(async () => [
      [
        { content: "const", color: "#ffffff", fontStyle: 2 },
        { content: " answer = 42" },
      ],
    ]);

    const preview = await computeMarkdownCodeBlockPreviewWithShiki(
      "const answer = 42",
      {
        language: "ts",
        theme: "github-light",
        loadShiki: async () => ({ codeToTokensBase }),
      },
    );

    expect(codeToTokensBase).toHaveBeenCalledWith("const answer = 42", {
      lang: "ts",
      theme: "github-light",
    });
    expect(preview).toMatchObject({
      kind: "shiki",
      language: "ts",
      theme: "github-light",
      totalLines: 1,
      lines: [
        {
          content: "const answer = 42",
          tokens: [
            { content: "const", color: "#ffffff", fontStyle: 2 },
            { content: " answer = 42" },
          ],
        },
      ],
    });
  });

  it("reads structured text output and maps shiki lines into read previews", async () => {
    const codeToTokensBase = vi.fn(async () => [
      [{ content: "const", color: "#ffffff" }],
      [{ content: "console", fontStyle: 1 }],
    ]);

    const preview = await computeReadPreviewWithShiki(
      JSON.stringify([
        {
          type: "text",
          text: "const x = 1\nconsole.log(x)",
        },
      ]),
      {
        filePath: "/tmp/demo.ts",
        mode: "collapsed",
        loadShiki: async () => ({ codeToTokensBase }),
      },
    );

    expect(codeToTokensBase).toHaveBeenCalledWith(
      "const x = 1\nconsole.log(x)",
      {
        lang: "ts",
        theme: "monokai",
      },
    );
    expect(preview).toMatchObject({
      kind: "shiki",
      mode: "collapsed",
      language: "ts",
      lines: [
        {
          gutter: "",
          content: "const x = 1",
          tokens: [{ content: "const", color: "#ffffff" }],
        },
        {
          gutter: "",
          content: "console.log(x)",
          tokens: [{ content: "console", fontStyle: 1 }],
        },
      ],
    });
  });

  it("builds diff previews from sanitized shiki token lines", async () => {
    const codeToTokensBase = vi.fn(async () => [
      [{ content: "const", color: "#ff0000" }],
      [{ content: "const", color: "#00ff00" }],
    ]);

    const preview = await computeDiffPreviewWithShiki(
      "const x = 1",
      "const x = 2",
      {
        filePath: "/tmp/demo.ts",
        loadShiki: async () => ({ codeToTokensBase }),
      },
    );

    expect(codeToTokensBase).toHaveBeenCalledWith(
      "const x = 1\nconst x = 2",
      {
        lang: "ts",
        theme: "monokai",
      },
    );
    expect(preview).toMatchObject({
      kind: "shiki",
      language: "ts",
      oldString: "const x = 1",
      newString: "const x = 2",
      lines: [
        {
          type: "removed",
          content: "const x = 1",
          tokens: [{ content: "const", color: "#ff0000" }],
        },
        {
          type: "added",
          content: "const x = 2",
          tokens: [{ content: "const", color: "#00ff00" }],
        },
      ],
    });
  });
});
