import { describe, expect, it, vi } from "vitest";
import { createAuditApi } from "../auditApi";

const log = {
  id: "101",
  username: "auditor",
  realName: "审计员",
  organizationName: "审计处",
  actionType: "LOGIN",
  targetType: "AUTH",
  targetId: null,
  targetName: null,
  operationResult: "SUCCESS",
  failureReason: null,
  clientIp: "127.0.0.1",
  requestId: "2de77077-4c7b-4cb0-801a-bdc5e11bea40",
  createdAt: "2026-07-23T03:00:00.000Z",
};
const page = {
  items: [log],
  page: 1,
  pageSize: 20,
  total: 1,
  totalPages: 1,
};
const result = (data: unknown) => ({
  data,
  message: "success",
  requestId: "bd78e456-a3fc-4b21-b22a-21553695ad3d",
  httpStatus: 200,
  headers: new Headers(),
});

describe("auditApi", () => {
  it("GET audit/logs 原样发送正式筛选、半开时间区间和分页参数", async () => {
    const client = { get: vi.fn().mockResolvedValue(result(page)) };
    const api = createAuditApi(client);
    const signal = new AbortController().signal;
    const query = {
      keyword: "登录",
      createdFrom: "2026-07-01T00:00:00.000Z",
      createdTo: "2026-08-01T00:00:00.000Z",
      userId: "2",
      organizationId: "3",
      actionType: "LOGIN" as const,
      operationResult: "SUCCESS" as const,
      targetType: "AUTH" as const,
      targetId: "9",
      page: 2,
      pageSize: 50,
      sortDirection: "asc" as const,
    };

    await api.logs(query, signal);

    expect(client.get).toHaveBeenCalledWith("audit/logs", {
      query,
      signal,
    });
    expect(client.get.mock.calls[0][0]).not.toContain("/api/v1");
  });

  it("GET 三个审计统计接口只发送OpenAPI定义参数", async () => {
    const client = {
      get: vi
        .fn()
        .mockResolvedValueOnce(
          result({ items: [{ period: "2026-07-23", operationCount: 4 }] }),
        )
        .mockResolvedValueOnce(
          result({ items: [{ actionType: "LOGIN", count: 3 }] }),
        )
        .mockResolvedValueOnce(
          result({
            items: [
              {
                userId: "2",
                realName: null,
                organizationName: null,
                operationCount: 5,
              },
            ],
          }),
        ),
    };
    const api = createAuditApi(client);
    const range = {
      createdFrom: "2026-07-01T00:00:00.000Z",
      createdTo: "2026-08-01T00:00:00.000Z",
    };

    await api.trend({ ...range, granularity: "WEEK" });
    await api.actions(range);
    await api.users({ ...range, limit: 6 });

    expect(client.get.mock.calls).toEqual([
      [
        "audit/statistics/trend",
        { query: { ...range, granularity: "WEEK" }, signal: undefined },
      ],
      [
        "audit/statistics/actions",
        { query: range, signal: undefined },
      ],
      [
        "audit/statistics/users",
        { query: { ...range, limit: 6 }, signal: undefined },
      ],
    ]);
  });

  it.each(["DAY", "WEEK", "MONTH"] as const)(
    "趋势支持%s粒度并直接保留后端period",
    async (granularity) => {
      const item = { period: "2026-07-21", operationCount: 2 };
      const client = {
        get: vi.fn().mockResolvedValue(result({ items: [item] })),
      };
      await expect(
        createAuditApi(client).trend({ granularity }),
      ).resolves.toEqual([item]);
    },
  );

  it("动作分布保持后端顺序且不从当前日志页汇总", async () => {
    const items = [
      { actionType: "DOWNLOAD_DOCUMENT", count: 8 },
      { actionType: "LOGIN", count: 3 },
    ];
    const client = {
      get: vi.fn().mockResolvedValue(result({ items })),
    };
    await expect(createAuditApi(client).actions({})).resolves.toEqual(items);
    expect(client.get).toHaveBeenCalledTimes(1);
  });

  it("活跃用户仅调用统计接口一次，不产生人员或组织N+1请求", async () => {
    const items = [
      {
        userId: "2",
        realName: "审计员",
        organizationName: "审计处",
        operationCount: 12,
      },
      {
        userId: "3",
        realName: null,
        organizationName: null,
        operationCount: 1,
      },
    ];
    const client = {
      get: vi.fn().mockResolvedValue(result({ items })),
    };
    await createAuditApi(client).users({ limit: 10 });
    expect(client.get).toHaveBeenCalledTimes(1);
    expect(client.get).toHaveBeenCalledWith("audit/statistics/users", {
      query: { limit: 10 },
      signal: undefined,
    });
  });
});

