import { describe, expect, it, vi } from "vitest";
import { HttpError } from "../../../shared/api/errors";
import { DictionarySessionStore } from "../dictionaryState";
import { dictionaryFixture } from "./fixtures";

describe("dictionary session state", () => {
  it("同一登录会话并发及StrictMode式重复加载只请求一次", async () => {
    let resolve!: (value: ReturnType<typeof dictionaryFixture>) => void;
    const pending = new Promise<ReturnType<typeof dictionaryFixture>>((done) => {
      resolve = done;
    });
    const getUiDictionaries = vi.fn(() => pending);
    const store = new DictionarySessionStore({ getUiDictionaries });
    const first = store.load("admin");
    const second = store.load("admin");
    expect(getUiDictionaries).toHaveBeenCalledTimes(1);
    resolve(dictionaryFixture());
    await Promise.all([first, second]);
    await store.load("admin");
    expect(getUiDictionaries).toHaveBeenCalledTimes(1);
  });

  it.each(["admin", "auditor", "user"])("%s会话均可加载且登出清理内存", async (sessionKey) => {
    const store = new DictionarySessionStore({
      getUiDictionaries: vi.fn().mockResolvedValue(dictionaryFixture()),
    });
    await store.load(sessionKey);
    expect(store.getSnapshot().status).toBe("success");
    store.clear();
    expect(store.getSnapshot()).toMatchObject({
      status: "idle",
      data: null,
      sessionKey: null,
    });
  });

  it("失败状态保留requestId且允许重试", async () => {
    const getUiDictionaries = vi.fn()
      .mockRejectedValueOnce(new HttpError({
        httpStatus: 503,
        code: "INTERNAL_ERROR",
        message: "服务不可用",
        details: null,
        requestId: "dict-failed",
      }))
      .mockResolvedValueOnce(dictionaryFixture());
    const store = new DictionarySessionStore({ getUiDictionaries });
    await expect(store.load("admin")).rejects.toBeInstanceOf(HttpError);
    expect(store.getSnapshot().error?.requestId).toBe("dict-failed");
    await store.retry("admin");
    expect(store.getSnapshot().status).toBe("success");
  });

  it("401原样抛出供统一登录失效机制处理", async () => {
    const unauthorized = new HttpError({
      httpStatus: 401,
      code: "UNAUTHORIZED",
      message: "登录失效",
      details: null,
      requestId: "dict-401",
    });
    const store = new DictionarySessionStore({
      getUiDictionaries: vi.fn().mockRejectedValue(unauthorized),
    });
    await expect(store.load("user")).rejects.toBe(unauthorized);
    expect(store.getSnapshot().error).toMatchObject({
      httpStatus: 401,
      requestId: "dict-401",
    });
  });
});
