import { describe, expect, it } from "vitest";

import { matchFromOrders } from "./match";
import { matchFromSeed } from "./random";
import { parseSavedGame } from "./persistence";

const { deckOrders, coinFlips } = matchFromSeed("abc");
const match = matchFromOrders(deckOrders, coinFlips, 3);

function savedGame(overrides: Record<string, unknown> = {}) {
  return {
    version: 2,
    seed: "abc",
    mode: 3,
    frames: [{ state: match, selection: { handSlot: null, placeType: null } }],
    cursor: 0,
    resultOpen: true,
    ...overrides,
  };
}

describe("saved game parsing", () => {
  it("accepts a complete saved timeline", () => {
    const saved = savedGame();
    expect(parseSavedGame(JSON.stringify(saved))).toEqual(saved);
  });

  it("accepts a one-deal game", () => {
    const saved = savedGame({
      mode: 1,
      frames: [
        { state: matchFromOrders(deckOrders, coinFlips, 1), selection: { handSlot: null, placeType: null } },
      ],
    });
    expect(parseSavedGame(JSON.stringify(saved))).toEqual(saved);
  });

  it("rejects corrupt and incompatible data", () => {
    expect(parseSavedGame("not json")).toBeNull();
    expect(parseSavedGame(JSON.stringify({ version: 2 }))).toBeNull();
    expect(parseSavedGame(JSON.stringify(savedGame({ frames: [] })))).toBeNull();
    expect(parseSavedGame(JSON.stringify(savedGame({ mode: 2 })))).toBeNull();
  });

  it("refuses a v1 save rather than guessing what it meant", () => {
    // A v1 save is one round: no carry, no deals for rounds two and three, no
    // coin flips. There is nothing honest to migrate it into, so it is dropped
    // and a fresh game is dealt.
    const v1 = { version: 1, seed: "abc", frames: [{ state: match.round, selection: {} }], cursor: 0, resultOpen: true };
    expect(parseSavedGame(JSON.stringify(v1))).toBeNull();
  });
});
