import { describe, it, expect, beforeEach } from "vitest";
import { InMemoryGameSessionStore } from "./InMemoryGameSessionStore.js";

describe("InMemoryGameSessionStore", () => {
  let store: InMemoryGameSessionStore;

  beforeEach(() => {
    store = new InMemoryGameSessionStore();
  });

  it("returns null for a non-existent session", async () => {
    const result = await store.get("00000000-0000-0000-0000-000000000000");
    expect(result).toBeNull();
  });

  it("returns session data after creation", async () => {
    const data = { answers: new Map([["q1", 2]]), userId: "user-1" };
    await store.create("session-1", data, 60_000);
    const result = await store.get("session-1");
    expect(result).toEqual(data);
  });

  it("returns null after the session is deleted", async () => {
    const data = { answers: new Map([["q1", 2]]), userId: "user-1" };
    await store.create("session-1", data, 60_000);
    await store.delete("session-1");
    const result = await store.get("session-1");
    expect(result).toBeNull();
  });

  it("returns null after TTL expires", async () => {
    const data = { answers: new Map([["q1", 2]]), userId: "user-1" };
    await store.create("session-1", data, 1);
    await new Promise((resolve) => setTimeout(resolve, 10));
    const result = await store.get("session-1");
    expect(result).toBeNull();
  });

  it("returns session data before TTL expires", async () => {
    const data = { answers: new Map([["q1", 2]]), userId: "user-1" };
    await store.create("session-1", data, 60_000);
    const result = await store.get("session-1");
    expect(result).not.toBeNull();
  });

  it("update persists modified session data", async () => {
    const data = {
      answers: new Map([
        ["q1", 2],
        ["q2", 1],
      ]),
      userId: "user-1",
    };
    await store.create("session-1", data, 60_000);

    const updated = { answers: new Map([["q2", 1]]), userId: "user-1" };
    await store.update("session-1", updated);

    const result = await store.get("session-1");
    expect(result).toEqual(updated);
  });
});
