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

import { SessionAsyncUtil } from "@/utils";

import { NavigationStorage } from "../navigation_storage";

describe("NavigationStorage", () => {
  beforeEach(() => {
    SessionAsyncUtil.setStorage(createStorage({ driver: memoryDriver() }));
    vi.useRealTimers();
  });

  it("saves, peeks, and consumes pending chat unlock sessions", async () => {
    await NavigationStorage.savePendingChatUnlock({
      messageId: "msg_1",
      kind: "image",
      returnUrl: "/chat?image=msg_1",
      stage: "payment",
    });

    await expect(NavigationStorage.peekPendingChatUnlock()).resolves.toMatchObject({
      messageId: "msg_1",
      kind: "image",
      returnUrl: "/chat?image=msg_1",
      stage: "payment",
    });

    await expect(
      NavigationStorage.consumePendingChatUnlock(),
    ).resolves.toMatchObject({
      messageId: "msg_1",
      kind: "image",
    });
    await expect(NavigationStorage.peekPendingChatUnlock()).resolves.toBeNull();
  });

  it("drops expired pending chat unlock sessions", async () => {
    vi.useFakeTimers();
    vi.setSystemTime(new Date("2026-07-03T00:00:00.000Z"));

    await NavigationStorage.savePendingChatUnlock({
      messageId: "msg_1",
      kind: "private",
      returnUrl: "/chat",
      stage: "auth",
    });

    vi.setSystemTime(new Date("2026-07-03T00:31:00.000Z"));

    await expect(NavigationStorage.peekPendingChatUnlock()).resolves.toBeNull();
  });

  it("saves and consumes pending chat image return sessions", async () => {
    await NavigationStorage.savePendingChatImageReturn({
      messageId: "msg_1",
      returnUrl: "/chat?image=msg_1",
    });

    await expect(
      NavigationStorage.consumePendingChatImageReturn(),
    ).resolves.toMatchObject({
      messageId: "msg_1",
      returnUrl: "/chat?image=msg_1",
    });
    await expect(
      NavigationStorage.consumePendingChatImageReturn(),
    ).resolves.toBeNull();
  });
});
