import { pathToFileURL } from "node:url";
import { describe, expect, it } from "vitest";
import { createLspConnection } from "../utils";
import { WatchKind } from "vscode-languageserver-protocol/node";

describe("LSP initialization", () => {
  it("should start LSP server and respond to initialize request", async () => {
    const dirPath = import.meta.dirname;
    await using client = createLspConnection();
    const initResult = await client.initialize([
      { uri: pathToFileURL(dirPath).href, name: "test" },
    ]);

    expect(initResult.capabilities.diagnosticProvider).toBeUndefined();
    expect(initResult.serverInfo?.name).toBe("oxlint");
  });

  it("should start LSP server without a workspace folder or root uri", async () => {
    await using client = createLspConnection();
    const initResult = await client.initialize(null);

    expect(initResult.capabilities.diagnosticProvider).toBeUndefined();
    expect(initResult.serverInfo?.name).toBe("oxlint");
  });

  it("should start LSP server with diagnostics provider", async () => {
    const dirPath = import.meta.dirname;
    await using client = createLspConnection();
    const initResult = await client.initialize(
      [{ uri: pathToFileURL(dirPath).href, name: "test" }],
      {
        textDocument: {
          diagnostic: {},
        },
        workspace: {
          diagnostics: {
            refreshSupport: true,
          },
        },
      },
    );

    expect(initResult.capabilities.diagnosticProvider).toBeDefined();
    expect(initResult.serverInfo?.name).toBe("oxlint");
  });

  it("should append VP version to server info if VP_VERSION env variable is set", async () => {
    const vpVersion = "1.2.3";
    await using client = createLspConnection({
      VP_VERSION: vpVersion,
    });
    const initResult = await client.initialize(null);

    expect(initResult.serverInfo?.version).toContain(`(VP: ${vpVersion})`);
  });

  it.each([
    [
      undefined,
      ["**/.oxlintrc.json", "**/.oxlintrc.jsonc", "**/oxlint.config.ts", "**/oxlint.config.mts"],
    ],
    [
      { configPath: "" },
      ["**/.oxlintrc.json", "**/.oxlintrc.jsonc", "**/oxlint.config.ts", "**/oxlint.config.mts"],
    ],
    [{ configPath: "./custom-config.json" }, ["custom-config.json"]],
  ])(
    "should send correct dynamic watch pattern registration for config: %s",
    async (lspConfig, expectedPatterns) => {
      const dirUri = pathToFileURL(import.meta.dirname).href;
      await using client = createLspConnection();
      await client.initialize(
        [{ uri: dirUri, name: "test" }],
        {
          workspace: {
            didChangeWatchedFiles: {
              dynamicRegistration: true,
            },
          },
        },
        [{ workspaceUri: dirUri, options: lspConfig }],
      );
      const registrations = await client.getDynamicRegistration();
      expect(registrations).toEqual([
        {
          id: `watcher-${dirUri}`,
          method: "workspace/didChangeWatchedFiles",
          registerOptions: {
            watchers: expectedPatterns.map((pattern) => ({
              globPattern: {
                baseUri: dirUri,
                pattern,
              },
              kind: WatchKind.Create | WatchKind.Change | WatchKind.Delete,
            })),
          },
        },
      ]);
    },
  );
});
