import { afterEach, describe, expect, it, vi } from "vitest";
import {
  buildCliCreateAgentRuntimeOptions,
  readCliRuntimeConfig,
} from "../src/dimsdk/cli/runtime-host.ts";

const realFetch = globalThis.fetch

afterEach(() => {
  Object.defineProperty(globalThis, "fetch", {
    configurable: true,
    value: realFetch,
  })
  vi.restoreAllMocks()
})

describe("dimsdk runtime host", () => {
  it("maps the runtime context window into the memory context budget", () => {
    const options = buildCliCreateAgentRuntimeOptions({
      context: {
        env: {
          DIMCODE_CONTEXT_WINDOW: "128000",
          DIMCODE_MODEL: "gpt-5.4-mini",
        },
        system: "",
      } as never,
      stateDir: "/tmp/best-agent-runtime-host-test",
    });

    expect(options.maxInputTokens).toBe(128000);
    expect((options as { memory?: { contextTokenBudget?: number } }).memory).toEqual({
      contextTokenBudget: 128000,
    });
  });

  it("reads the active model and base URL from the current runtime env keys", () => {
    const config = readCliRuntimeConfig({
      DIMCODE_MODEL: "gpt-5.4-mini",
      OPENAI_BASE_URL: "https://example.test/v1",
      OPENAI_API_KEY: "sk-test",
    });

    expect(config.modelId).toBe("gpt-5.4-mini");
    expect(config.baseUrl).toBe("https://example.test/v1");
  });

  it("ignores removed MODEL, MODEL_ID, and OPENAI_API_BASE_URL aliases", () => {
    const config = readCliRuntimeConfig({
      MODEL: "older-model",
      MODEL_ID: "legacy-model",
      OPENAI_API_BASE_URL: "https://legacy.example/v1",
      OPENAI_API_KEY: "sk-test",
    });

    expect(config.modelId).toBe("deepseek-v3.1");
    expect(config.baseUrl).toBeUndefined();
  });

  it("only enables next api oauth from the active provider id", () => {
    expect(
      readCliRuntimeConfig({
        DIMCODE_PROVIDER_ID: "next-api-oauth",
        OPENAI_API_KEY: "sk-test",
      }).nextApiOAuth,
    ).toBe(true);

    expect(
      readCliRuntimeConfig({
        DIMCODE_USE_NEXT_API_OAUTH: "1",
        OPENAI_API_KEY: "sk-test",
      }).nextApiOAuth,
    ).toBeUndefined();
  });

  it("re-evaluates web-search capability from the current CLI tool settings", async () => {
    let apiKey = "";
    let apiEndpoint = "https://example.test/search";

    const options = buildCliCreateAgentRuntimeOptions({
      context: {
        env: {},
        system: "",
      } as never,
      stateDir: "/tmp/best-agent-runtime-host-test",
      tools: {
        websearch: {
          apiEndpoint: () => apiEndpoint,
          apiKey: () => apiKey,
          numResults: () => 7,
        },
      },
    }) as {
      webSearch?: (input: {
        domains?: string[];
        limit: number;
        query: string;
        recencyDays?: number;
      }) => Promise<string>;
      webSearchAvailability?: () => boolean;
    };

    expect(options.webSearchAvailability?.()).toBe(false);

    apiKey = "serper-key";
    expect(options.webSearchAvailability?.()).toBe(true);

    const fetchMock = vi.fn(async () => ({
      json: async () => ({
        organic: [
          {
            title: "Best Agent Docs",
            link: "https://example.test/docs",
            snippet: "Grounded docs result",
          },
        ],
      }),
      ok: true,
      status: 200,
      statusText: "OK",
      text: async () => "",
    }));
    Object.defineProperty(globalThis, "fetch", {
      configurable: true,
      value: fetchMock,
    });

    const output = await options.webSearch?.({
      domains: ["example.test"],
      limit: 5,
      query: "best agent",
    });

    expect(fetchMock).toHaveBeenCalledWith(
      "https://example.test/search",
      expect.objectContaining({
        body: JSON.stringify({
          num: 5,
          q: "best agent site:example.test",
        }),
        headers: {
          "Content-Type": "application/json",
          "X-API-KEY": "serper-key",
        },
        method: "POST",
      }),
    );
    expect(output).toContain('Search results for "best agent" (1 found):');
    expect(output).toContain("1. Best Agent Docs");
    expect(output).toContain("URL: https://example.test/docs");

    apiEndpoint = "https://example.test/updated-search";
    await options.webSearch?.({
      limit: 3,
      query: "best agent runtime",
    });

    expect(fetchMock).toHaveBeenLastCalledWith(
      "https://example.test/updated-search",
      expect.objectContaining({
        body: JSON.stringify({
          num: 3,
          q: "best agent runtime",
        }),
      }),
    );
  });
});
