import { beforeEach, describe, expect, it } from "vitest";
import { createStorage } from "unstorage";
import memoryDriver from "unstorage/drivers/memory";

import { StorageKeys } from "@/data/storage/storage_keys";
import { UserStorage } from "@/data/storage/user/user_storage";
import { SpAsyncUtil } from "@/utils/storage";

describe("UserStorage", () => {
  beforeEach(() => {
    SpAsyncUtil.setStorage(createStorage({ driver: memoryDriver() }));
    UserStorage._resetForTests();
  });

  const expectedPersistedUser = {
    id: "user-1",
    username: "Elio",
    countryCode: "HK",
    dailyFreeChatLimit: 30,
    dailyFreeChatRemaining: 26,
    dailyFreePrivateLimit: 2,
    dailyFreePrivateRemaining: 1,
  };

  it("persists only the user fields used by the app", async () => {
    const fullUser = {
      id: "user-1",
      username: "Elio",
      email: "elio@example.com",
      platform: "web",
      country: "Hong Kong",
      countryCode: "HK",
      intimacy: 42,
      dolBalance: 12,
      creditBalance: 120,
      dailyFreeChatLimit: 30,
      dailyFreeChatUsed: 4,
      dailyFreeChatRemaining: 26,
      dailyFreePrivateLimit: 2,
      dailyFreePrivateUsed: 1,
      dailyFreePrivateRemaining: 1,
      personalityTraits: {
        caring: 0.5,
        playful: 0.5,
        serious: 0.5,
        cheerful: 0.5,
        romantic: 0.5,
      },
      preferredLanguage: "zh",
      createdAt: "2026-06-12T08:08:27.378706+00:00",
      lastMessageAt: "2026-06-24T11:00:23.156561+00:00",
    };

    const result = await UserStorage.getInstance().setUser(fullUser);
    expect(result.success).toBe(true);

    const raw = await SpAsyncUtil.getRawStorage().getItem<unknown>(
      StorageKeys.user,
    );
    const stored = typeof raw === "string" ? JSON.parse(raw) : raw;
    expect(stored).toEqual(expectedPersistedUser);
    expect(stored).not.toHaveProperty("email");
    expect(stored).not.toHaveProperty("platform");
    expect(stored).not.toHaveProperty("country");
    expect(stored).not.toHaveProperty("personalityTraits");
    expect(stored).not.toHaveProperty("createdAt");
    expect(stored).not.toHaveProperty("lastMessageAt");
  });

  it("reads old full user caches as compact persisted users", async () => {
    await SpAsyncUtil.getRawStorage().setItem(
      StorageKeys.user,
      JSON.stringify({
        ...expectedPersistedUser,
        email: "elio@example.com",
        platform: "web",
        country: "Hong Kong",
        personalityTraits: {
          caring: 0.5,
          playful: 0.5,
          serious: 0.5,
          cheerful: 0.5,
          romantic: 0.5,
        },
        preferredLanguage: "zh",
        createdAt: "2026-06-12T08:08:27.378706+00:00",
        lastMessageAt: "2026-06-24T11:00:23.156561+00:00",
      }),
    );

    const result = await UserStorage.getInstance().getUser();
    if (!result.success) {
      throw result.error;
    }
    expect(result.data).toEqual(expectedPersistedUser);
  });
});
