import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { afterEach, describe, expect, it } from "vitest";
import {
  createCliRuntime,
  hydrateDimSdkProviderSelection,
  resolveProviderConfigFromDimSdkState,
  writeCliPersistedState,
} from "../src/runtime.ts";

const storageRoots: string[] = [];

afterEach(() => {
  while (storageRoots.length > 0) {
    rmSync(storageRoots.pop() as string, { force: true, recursive: true });
  }
});

describe("cli runtime provider persistence", () => {
  it("loads persisted provider state into the runtime and round-trips updated selections", async () => {
    const storageRoot = mkdtempSync(`${tmpdir()}/best-agent-cli-provider-`);
    storageRoots.push(storageRoot);

    writeCliPersistedState(storageRoot, {
      dimsdk: {
        providerState: {
          activeId: "openai",
          activeModelByProvider: {
            openai: "gpt-5",
          },
          connections: {
            openai: {
              apiKey: "sk-old",
              baseUrl: "https://api.openai.com/v1",
            },
          },
          custom: {
            apiKey: undefined,
            baseUrl: undefined,
            models: [],
          },
          customProviders: [],
        },
      },
      providerConfig: {
        apiKey: "sk-old",
        baseURL: "https://api.openai.com/v1",
        kind: "openai",
        model: "gpt-5",
      },
    });

    const runtime = await createCliRuntime({ storageRoot });
    expect(runtime.getProviderConfig()).toMatchObject({
      apiKey: "sk-old",
      baseURL: "https://api.openai.com/v1",
      kind: "openai",
      model: "gpt-5",
    });

    const state = {
      config: { model: "" },
      provider: {},
    };

    hydrateDimSdkProviderSelection(state, {
      persistedProviderState: {
        activeId: "openai",
        activeModelByProvider: {
          openai: "gpt-5",
        },
        connections: {
          openai: {
            apiKey: "sk-old",
            baseUrl: "https://api.openai.com/v1",
          },
        },
        custom: {
          apiKey: undefined,
          baseUrl: undefined,
          models: [],
        },
        customProviders: [],
      },
      providerConfig: runtime.getProviderConfig(),
    });

    expect(state.provider).toMatchObject({
      activeId: "openai",
    });
    expect(state.config.model).toBe("gpt-5");

    state.config.model = "gpt-5.1";
    state.provider = {
      ...state.provider,
      connections: {
        openai: {
          apiKey: "sk-new",
          baseUrl: "https://api.openai.com/v1",
        },
      },
    };

    expect(resolveProviderConfigFromDimSdkState(state, runtime.getProviderConfig())).toMatchObject({
      apiKey: "sk-new",
      baseURL: "https://api.openai.com/v1",
      kind: "openai",
      model: "gpt-5.1",
    });
  });

  it("round-trips custom provider adapters into the runtime provider config", async () => {
    const storageRoot = mkdtempSync(`${tmpdir()}/best-agent-cli-provider-custom-`);
    storageRoots.push(storageRoot);

    writeCliPersistedState(storageRoot, {
      dimsdk: {
        providerState: {
          activeId: "cp_proxy",
          activeModelByProvider: {
            cp_proxy: "gpt-4.1-mini",
          },
          connections: {},
          custom: {
            apiKey: undefined,
            baseUrl: undefined,
            models: [],
          },
          customProviders: [
            {
              adapter: "openai",
              apiKey: "sk-proxy",
              baseUrl: "https://proxy.example.com/v1",
              id: "cp_proxy",
              models: [{ id: "gpt-4.1-mini" }],
              name: "OpenAI Proxy",
            },
          ],
        },
      },
      providerConfig: {
        apiKey: "sk-proxy",
        baseURL: "https://proxy.example.com/v1",
        kind: "customProvider",
        model: "gpt-4.1-mini",
      },
    });

    const runtime = await createCliRuntime({ storageRoot });
    expect(runtime.getProviderConfig()).toMatchObject({
      apiKey: "sk-proxy",
      baseURL: "https://proxy.example.com/v1",
      kind: "customProvider",
      model: "gpt-4.1-mini",
    });

    const state = {
      config: { model: "" },
      provider: {},
    };

    hydrateDimSdkProviderSelection(state, {
      persistedProviderState: {
        activeId: "cp_proxy",
        activeModelByProvider: {
          cp_proxy: "gpt-4.1-mini",
        },
        connections: {},
        custom: {
          apiKey: undefined,
          baseUrl: undefined,
          models: [],
        },
        customProviders: [
          {
            adapter: "openai",
            apiKey: "sk-proxy",
            baseUrl: "https://proxy.example.com/v1",
            id: "cp_proxy",
            models: [{ id: "gpt-4.1-mini" }],
            name: "OpenAI Proxy",
          },
        ],
      },
      providerConfig: runtime.getProviderConfig(),
    });

    expect(state.provider).toMatchObject({
      activeId: "cp_proxy",
    });
    expect(state.config.model).toBe("gpt-4.1-mini");

    expect(resolveProviderConfigFromDimSdkState(state, runtime.getProviderConfig())).toMatchObject({
      apiKey: "sk-proxy",
      baseURL: "https://proxy.example.com/v1",
      kind: "openai",
      model: "gpt-4.1-mini",
    });
  });
});
