import { describe, it, expect, vi, beforeEach } from "vitest";
import { NextRequest, NextResponse } from "next/server";

const mockAdminSession = { user: { id: "admin-1", role: "admin" } };

vi.mock("@/lib/api-auth", () => ({
  requireAdmin: vi.fn(),
}));

vi.mock("@/lib/site-settings", () => ({
  setSiteSetting: vi.fn().mockResolvedValue(undefined),
}));

const { mockInsertValues } = vi.hoisted(() => ({
  mockInsertValues: vi.fn().mockResolvedValue(undefined),
}));

vi.mock("@epicure/db", () => ({
  db: {
    insert: vi.fn(() => ({ values: mockInsertValues })),
  },
  auditLogs: {},
}));

const { requireAdmin } = await import("@/lib/api-auth");
const { setSiteSetting } = await import("@/lib/site-settings");
import { PUT } from "../route";

function makeRequest(body: unknown) {
  return new NextRequest("http://localhost/api/v1/admin/settings", {
    method: "PUT",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });
}

beforeEach(() => {
  vi.clearAllMocks();
  vi.mocked(requireAdmin).mockResolvedValue({ session: mockAdminSession as never, response: null });
});

describe("PUT /api/v1/admin/settings", () => {
  it("returns 403 when caller is not an admin", async () => {
    vi.mocked(requireAdmin).mockResolvedValue({
      session: null,
      response: NextResponse.json({ error: "Forbidden" }, { status: 403 }),
    } as never);
    const res = await PUT(makeRequest({ OPENAI_API_KEY: "sk-1" }));
    expect(res.status).toBe(403);
  });

  it("returns 401 when there is no session", async () => {
    vi.mocked(requireAdmin).mockResolvedValue({
      session: null,
      response: NextResponse.json({ error: "Unauthorized" }, { status: 401 }),
    } as never);
    const res = await PUT(makeRequest({ OPENAI_API_KEY: "sk-1" }));
    expect(res.status).toBe(401);
  });

  it("updates allowed keys and writes an audit log", async () => {
    const res = await PUT(makeRequest({ OPENAI_API_KEY: "sk-1" }));
    expect(res.status).toBe(200);
    expect(vi.mocked(setSiteSetting)).toHaveBeenCalledWith("OPENAI_API_KEY", "sk-1", "admin-1");
    expect(mockInsertValues).toHaveBeenCalled();
  });

  it("silently ignores keys not in the allow-list", async () => {
    const res = await PUT(makeRequest({ NOT_A_REAL_KEY: "x" }));
    expect(res.status).toBe(200);
    expect(vi.mocked(setSiteSetting)).not.toHaveBeenCalled();
    expect(mockInsertValues).not.toHaveBeenCalled();
  });
});
