import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import { resolveAuthStatePath, resolveAuthStorePath } from "../agents/auth-profiles/paths.js";
import { writeCachedAuthProfileStore } from "../agents/auth-profiles/store-cache.js";
import { loadAuthProfileStoreForRuntime } from "../agents/auth-profiles/store.js";
import type { AuthProfileStore } from "../agents/auth-profiles/types.js";
import {
  activateSecretsRuntimeSnapshotState,
  clearSecretsRuntimeSnapshot,
  getActiveSecretsRuntimeConfigSnapshot,
  getActiveSecretsRuntimeSnapshot,
  type PreparedSecretsRuntimeSnapshot,
} from "./runtime-state.js";

function authStore(key: string): AuthProfileStore {
  return {
    version: 1,
    profiles: {
      "openai:default": {
        type: "api_key",
        provider: "openai",
        key,
      },
    },
  };
}

describe("secrets runtime state", () => {
  const previousStateDir = process.env.OPENCLAW_STATE_DIR;

  afterEach(() => {
    clearSecretsRuntimeSnapshot();
    if (previousStateDir === undefined) {
      delete process.env.OPENCLAW_STATE_DIR;
    } else {
      process.env.OPENCLAW_STATE_DIR = previousStateDir;
    }
  });

  it("clears loaded auth-profile cache without importing the full secrets runtime", () => {
    const root = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-runtime-state-cache-"));
    process.env.OPENCLAW_STATE_DIR = root;
    const agentDir = path.join(root, "agents", "default", "agent");

    try {
      fs.mkdirSync(agentDir, { recursive: true });
      const authPath = resolveAuthStorePath(agentDir);
      const statePath = resolveAuthStatePath(agentDir);
      fs.writeFileSync(authPath, `${JSON.stringify(authStore("sk-new"))}\n`);
      const stat = fs.statSync(authPath);
      writeCachedAuthProfileStore({
        authPath,
        authMtimeMs: stat.mtimeMs,
        stateMtimeMs: fs.existsSync(statePath) ? fs.statSync(statePath).mtimeMs : null,
        store: authStore("sk-old"),
      });

      expect(
        loadAuthProfileStoreForRuntime(agentDir, { syncExternalCli: false }).profiles[
          "openai:default"
        ],
      ).toMatchObject({ key: "sk-old" });

      clearSecretsRuntimeSnapshot();

      expect(
        loadAuthProfileStoreForRuntime(agentDir, { syncExternalCli: false }).profiles[
          "openai:default"
        ],
      ).toMatchObject({ key: "sk-new" });
    } finally {
      fs.rmSync(root, { recursive: true, force: true });
    }
  });

  it("exposes the active config pair for hot paths without requiring the full snapshot", () => {
    const snapshot: PreparedSecretsRuntimeSnapshot = {
      sourceConfig: { agents: { list: [{ id: "source" }] } },
      config: { agents: { list: [{ id: "runtime" }] } },
      authStores: [],
      warnings: [],
      webTools: {
        search: { providerSource: "none", diagnostics: [] },
        fetch: { providerSource: "none", diagnostics: [] },
        diagnostics: [],
      },
    };

    activateSecretsRuntimeSnapshotState({
      snapshot,
      refreshContext: null,
      refreshHandler: null,
    });

    const configSnapshot = getActiveSecretsRuntimeConfigSnapshot();
    const fullSnapshot = getActiveSecretsRuntimeSnapshot();

    expect(configSnapshot?.config).not.toBe(fullSnapshot?.config);
    expect(configSnapshot?.sourceConfig).not.toBe(fullSnapshot?.sourceConfig);
    expect(configSnapshot?.config).toEqual(snapshot.config);
    expect(configSnapshot?.sourceConfig).toEqual(snapshot.sourceConfig);
  });
});
