import { describe, expect, it } from "vitest";
import { calculateBlackjackDeck, blackjackValue, verifyBlackjack, type BlackjackCard } from "@/server/casino/blackjack";
import { sha256 } from "@/server/casino/dice";

describe("blackjack game engine", () => {
  it("scores blackjacks, soft aces and busts", () => {
    expect(
      blackjackValue([
        { suit: "spades", rank: "A", code: "AS" },
        { suit: "hearts", rank: "K", code: "KH" }
      ]).blackjack
    ).toBe(true);

    expect(
      blackjackValue([
        { suit: "spades", rank: "A", code: "AS" },
        { suit: "hearts", rank: "7", code: "7H" },
        { suit: "clubs", rank: "3", code: "3C" }
      ])
    ).toMatchObject({ total: 21, soft: true, bust: false });

    expect(
      blackjackValue([
        { suit: "spades", rank: "K", code: "KS" },
        { suit: "hearts", rank: "9", code: "9H" },
        { suit: "clubs", rank: "5", code: "5C" }
      ])
    ).toMatchObject({ total: 24, bust: true });
  });

  it("uses a deterministic provably fair 52-card deck", () => {
    const input = {
      serverSeed: "server-seed-for-test-0000000000000001",
      clientSeed: "client-seed-for-test",
      nonce: 42
    };
    const deck = calculateBlackjackDeck(input);

    expect(deck).toHaveLength(52);
    expect(new Set(deck.map((card) => card.code)).size).toBe(52);
    expect(calculateBlackjackDeck(input)).toEqual(deck);
    expect(verifyBlackjack(input)).toEqual({
      serverSeedHash: sha256(input.serverSeed),
      openingDeal: {
        player: [deck[0], deck[2]],
        dealer: [deck[1], deck[3]]
      },
      deck
    });
  });

  it("counts face cards as 10", () => {
    const cards: BlackjackCard[] = [
      { suit: "spades", rank: "Q", code: "QS" },
      { suit: "diamonds", rank: "J", code: "JD" }
    ];

    expect(blackjackValue(cards)).toMatchObject({ total: 20, blackjack: false });
  });
});
