import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { afterEach, describe, expect, it } from "vitest";
import type { GoatChainAgent as DimSdkAgent } from "../src/dimsdk/core/acp.ts";
import { createDimSdkPersistence } from "../src/dimsdk/cli/persistence.ts";
import { buildUserConfigFromStore } from "../src/dimsdk/cli/persistence/user-cache.ts";
import { createDimSdkStore } from "../src/dimsdk/core/store.ts";

const tempDirs: string[] = [];

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

function createTempDir(prefix: string): string {
  const dir = mkdtempSync(`${tmpdir()}/${prefix}`);
  tempDirs.push(dir);
  return dir;
}

describe("provider cache persistence", () => {
  it("persists provider state into cache settings", () => {
    const agent: DimSdkAgent = { async *receiveMessage() {} };
    const store = createDimSdkStore({
      toolRunner: async () => ({ id: "t", status: "success", output: "ok" }),
      agent: agent as any,
      context: { system: "test", cwd: ".", env: {} },
    });

    store.state.provider.activeId = "custom";
    store.state.provider.custom = {
      baseUrl: "https://example.com/v1",
      apiKey: "key-123",
      models: [{ id: "m1" }],
    };
    store.state.provider.activeModelByProvider = { custom: "m1" };
    store.state.provider.connections = {
      deepseek: { apiKey: "k2", baseUrl: "https://deepseek.example/v1" },
    };

    const config = buildUserConfigFromStore({ prev: { version: 1, updatedAt: 0 }, store });
    expect(config.settings?.providerId).toBe("custom");
    expect(config.settings?.customProvider?.models?.[0]?.id).toBe("m1");
    expect(config.settings?.providerConnections?.deepseek?.apiKey).toBe("k2");
  });

  it("rehydrates openai-responses custom providers from persisted config", () => {
    const dir = createTempDir("best-agent-provider-cache-");
    const agent: DimSdkAgent = { async *receiveMessage() {} };
    const store = createDimSdkStore({
      toolRunner: async () => ({ id: "t", status: "success", output: "ok" }),
      agent: agent as any,
      context: { system: "test", cwd: ".", env: {} },
    });

    const persistence = createDimSdkPersistence({
      cacheFile: `${dir}/cache.json`,
      cache: {
        version: 1,
        updatedAt: 0,
        settings: {
          model: "gpt-5.4",
        },
      } as any,
      configFile: `${dir}/config.json`,
      config: {
        version: 1,
        updatedAt: 0,
        settings: {
          providerId: "cp_openai_responses",
          activeModelByProvider: {
            cp_openai_responses: "gpt-5.4",
          },
          customProviders: [
            {
              id: "cp_openai_responses",
              name: "OpenAI Responses Custom",
              adapter: "openai-responses",
              baseUrl: "https://example.com/v1",
              apiKey: "sk-test",
              models: [{ id: "gpt-5.4", name: "GPT-5.4" }],
            },
          ],
        },
      } as any,
      toolsFile: `${dir}/tools.json`,
      tools: { version: 1, updatedAt: 0 } as any,
      deferPersist: true,
    });

    persistence.onStoreCreated(store);

    expect(store.state.provider.customProviders).toEqual([
      {
        id: "cp_openai_responses",
        name: "OpenAI Responses Custom",
        adapter: "openai-responses",
        baseUrl: "https://example.com/v1",
        apiKey: "sk-test",
        models: [{ id: "gpt-5.4", name: "GPT-5.4" }],
      },
    ]);
    expect(store.state.provider.activeId).toBe("cp_openai_responses");
    expect(store.state.provider.activeModelByProvider.cp_openai_responses).toBe("gpt-5.4");
    expect(store.state.config.model).toBe("gpt-5.4");
  });

  it("normalizes persisted provider config and workspace selections during hydration", () => {
    const dir = createTempDir("best-agent-provider-cache-normalize-");
    const agent: DimSdkAgent = { async *receiveMessage() {} };
    const store = createDimSdkStore({
      toolRunner: async () => ({ id: "t", status: "success", output: "ok" }),
      agent: agent as any,
      context: { system: "test", cwd: ".", env: {} },
    });

    const persistence = createDimSdkPersistence({
      cacheFile: `${dir}/cache.json`,
      cache: {
        version: 1,
        updatedAt: 0,
        settings: {
          workspaceSelectionByCwd: {
            " /repo/project ": {
              modelId: " demo-model ",
              providerId: " cp_demo ",
            },
            "/repo/invalid": {
              providerId: " ",
            },
          },
        },
      } as any,
      configFile: `${dir}/config.json`,
      config: {
        version: 1,
        updatedAt: 0,
        settings: {
          providerId: " cp_demo ",
          activeModelByProvider: {
            " cp_demo ": " demo-model ",
            "": "missing",
            openai: " ",
          },
          providerConnections: {
            empty: {},
            openai: {
              apiKey: " sk-openai ",
              models: [
                {
                  id: " gpt-5 ",
                  reasoning: { default: true, supported: true },
                  vision: true,
                },
                {
                  name: "missing-id",
                },
              ],
            },
          },
          customProviders: [
            {
              adapter: "openai-responses",
              apiKey: " sk-demo ",
              id: " cp_demo ",
              models: [
                {
                  id: " demo-model ",
                  name: " Demo Model ",
                },
                {
                  name: "missing-id",
                },
              ],
              name: " Demo ",
            },
            {
              adapter: "openai",
              id: "nope",
              models: [{ id: "bad" }],
              name: "Bad",
            },
          ],
        },
      } as any,
      toolsFile: `${dir}/tools.json`,
      tools: { version: 1, updatedAt: 0 } as any,
      deferPersist: true,
    });

    persistence.onStoreCreated(store);

    expect(store.state.provider.connections).toEqual({
      openai: {
        apiKey: "sk-openai",
        models: [
          {
            id: "gpt-5",
            reasoning: { default: true, supported: true },
            vision: true,
          },
        ],
      },
    });
    expect(store.state.provider.customProviders[0]).toEqual({
      adapter: "openai-responses",
      apiKey: "sk-demo",
      id: "cp_demo",
      models: [
        {
          id: "demo-model",
          name: "Demo Model",
        },
      ],
      name: "Demo",
    });
    expect(store.state.provider.customProviders[1]).toMatchObject({
      adapter: "openai",
      models: [{ id: "bad" }],
      name: "Bad",
    });
    expect(store.state.provider.customProviders[1]?.id).toMatch(/^cp_/);
    expect(store.state.provider.activeId).toBe("cp_demo");
    expect(store.state.provider.activeModelByProvider).toEqual({
      cp_demo: "demo-model",
    });
    expect(store.state.ui.workspaceSelectionByCwd).toEqual({
      "/repo/project": {
        modelId: "demo-model",
        providerId: "cp_demo",
      },
    });
    expect(store.state.config.model).toBe("demo-model");
  });
});
