import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { DEFAULT_OPENAI_MODEL, SystemRole } from "@capakraken/shared";

import { createToolContext, executeTool } from "./assistant-tools-settings-test-helpers.js";

describe("assistant settings tools runtime settings", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  afterEach(() => {
    vi.unstubAllGlobals();
    vi.unstubAllEnvs();
  });

  it("returns system settings with runtime secret flags through the real settings router path", async () => {
    vi.stubEnv("OPENAI_API_KEY", "env-openai-key");
    vi.stubEnv("SMTP_PASSWORD", "env-smtp-password");
    vi.stubEnv("GEMINI_API_KEY", "env-gemini-key");

    const ctx = createToolContext({
      systemSettings: {
        findUnique: vi.fn().mockResolvedValue({
          aiProvider: "openai",
          azureOpenAiApiKey: null,
          smtpPassword: null,
          geminiApiKey: null,
        }),
      },
    });

    const result = await executeTool("get_system_settings", JSON.stringify({}), ctx);
    const parsed = JSON.parse(result.content) as {
      hasApiKey: boolean;
      hasSmtpPassword: boolean;
      hasGeminiApiKey: boolean;
      runtimeSecrets: {
        azureOpenAiApiKey: { activeSource: string };
        smtpPassword: { activeSource: string };
      };
      legacyStoredSecretFields: string[];
    };

    expect(parsed.hasApiKey).toBe(true);
    expect(parsed.hasSmtpPassword).toBe(true);
    expect(parsed.hasGeminiApiKey).toBe(true);
    expect(parsed.runtimeSecrets.azureOpenAiApiKey.activeSource).toBe("environment");
    expect(parsed.runtimeSecrets.smtpPassword.activeSource).toBe("environment");
    expect(parsed.legacyStoredSecretFields).toEqual([]);
  });

  it("updates system settings without persisting incoming secret fields", async () => {
    const findUnique = vi.fn().mockResolvedValue(null);
    const upsert = vi.fn().mockResolvedValue({});
    const ctx = createToolContext({
      systemSettings: {
        findUnique,
        upsert,
      },
    });

    const result = await executeTool(
      "update_system_settings",
      JSON.stringify({
        azureOpenAiApiKey: "sk-should-not-store",
        smtpPassword: "smtp-should-not-store",
        geminiApiKey: "gemini-should-not-store",
        azureDalleApiKey: "dalle-should-not-store",
        anonymizationSeed: "seed-should-not-store",
        aiProvider: "openai",
        azureOpenAiDeployment: DEFAULT_OPENAI_MODEL,
      }),
      ctx,
    );

    expect(JSON.parse(result.content)).toEqual({
      ok: true,
      ignoredSecretFields: [
        "azureOpenAiApiKey",
        "smtpPassword",
        "anonymizationSeed",
        "azureDalleApiKey",
        "geminiApiKey",
      ],
      secretStorageMode: "environment-only",
    });
    expect(findUnique).toHaveBeenCalledWith({ where: { id: "singleton" } });
    expect(upsert).toHaveBeenCalledWith({
      where: { id: "singleton" },
      create: {
        id: "singleton",
        aiProvider: "openai",
        azureOpenAiDeployment: DEFAULT_OPENAI_MODEL,
      },
      update: {
        aiProvider: "openai",
        azureOpenAiDeployment: DEFAULT_OPENAI_MODEL,
      },
    });
  });

  it("clears legacy runtime secrets through the real settings router path", async () => {
    const findUnique = vi.fn().mockResolvedValue({
      azureOpenAiApiKey: "db-openai",
      azureDalleApiKey: null,
      geminiApiKey: "db-gemini",
      smtpPassword: null,
      anonymizationSeed: "db-seed",
    });
    const update = vi.fn().mockResolvedValue({ id: "singleton" });
    const auditCreate = vi.fn().mockResolvedValue(undefined);
    const ctx = createToolContext({
      systemSettings: {
        findUnique,
        update,
      },
      auditLog: {
        create: auditCreate,
      },
    });

    const result = await executeTool("clear_stored_runtime_secrets", "{}", ctx);

    expect(JSON.parse(result.content)).toEqual({
      ok: true,
      clearedFields: ["azureOpenAiApiKey", "geminiApiKey", "anonymizationSeed"],
    });
    expect(update).toHaveBeenCalledWith({
      where: { id: "singleton" },
      data: {
        azureOpenAiApiKey: null,
        geminiApiKey: null,
        anonymizationSeed: null,
      },
    });
    expect(auditCreate).toHaveBeenCalled();
  });

  it("rejects admin-only runtime settings tools for non-admin assistant users", async () => {
    const ctx = createToolContext(
      {
        systemSettings: {
          findUnique: vi.fn(),
          upsert: vi.fn(),
          update: vi.fn(),
        },
      },
      SystemRole.MANAGER,
    );

    for (const [toolName, payload] of [
      ["get_system_settings", {}],
      ["update_system_settings", { aiProvider: "openai" }],
      ["clear_stored_runtime_secrets", {}],
    ] as const) {
      const result = await executeTool(toolName, JSON.stringify(payload), ctx);
      expect(JSON.parse(result.content)).toEqual({
        error: "You do not have permission to perform this action.",
      });
    }
  });
});
