import { describe, expect, it } from "vitest";
import { ConflictError } from "@/server/errors";
import { assertBoostedCumulativeStakeLimit, assertNoCorrelatedSelections, betPlacementSchema } from "@/server/sportsbook/bet-placement";

describe("bet placement validation", () => {
  it("requires a positive stake and at least one selection", () => {
    expect(() =>
      betPlacementSchema.parse({
        currency: "EUR",
        stake: 10,
        selections: [{ selectionId: crypto.randomUUID(), odds: 1.92, oddsVersion: 1 }]
      })
    ).not.toThrow();

    expect(() => betPlacementSchema.parse({ currency: "EUR", stake: 0, selections: [] })).toThrow();
  });

  it("blocks correlated selections from the same event", () => {
    expect(() =>
      assertNoCorrelatedSelections([
        { id: crypto.randomUUID(), marketId: crypto.randomUUID(), market: { eventId: "event-a" } },
        { id: crypto.randomUUID(), marketId: crypto.randomUUID(), market: { eventId: "event-a" } }
      ])
    ).toThrow(ConflictError);
  });

  it("allows selections from different events", () => {
    expect(() =>
      assertNoCorrelatedSelections([
        { id: crypto.randomUUID(), marketId: crypto.randomUUID(), market: { eventId: "event-a" } },
        { id: crypto.randomUUID(), marketId: crypto.randomUUID(), market: { eventId: "event-b" } }
      ])
    ).not.toThrow();
  });

  it("allows same-game selections from different markets when explicitly requested", () => {
    expect(() =>
      assertNoCorrelatedSelections(
        [
          { id: crypto.randomUUID(), marketId: crypto.randomUUID(), market: { eventId: "event-a" } },
          { id: crypto.randomUUID(), marketId: crypto.randomUUID(), market: { eventId: "event-a" } }
        ],
        { sameGame: true }
      )
    ).not.toThrow();
  });

  it("blocks same-game tickets that mix events or duplicate markets", () => {
    const duplicatedMarketId = crypto.randomUUID();

    expect(() =>
      assertNoCorrelatedSelections(
        [
          { id: crypto.randomUUID(), marketId: crypto.randomUUID(), market: { eventId: "event-a" } },
          { id: crypto.randomUUID(), marketId: crypto.randomUUID(), market: { eventId: "event-b" } }
        ],
        { sameGame: true }
      )
    ).toThrow(ConflictError);

    expect(() =>
      assertNoCorrelatedSelections(
        [
          { id: crypto.randomUUID(), marketId: duplicatedMarketId, market: { eventId: "event-a" } },
          { id: crypto.randomUUID(), marketId: duplicatedMarketId, market: { eventId: "event-a" } }
        ],
        { sameGame: true }
      )
    ).toThrow(ConflictError);
  });

  it("enforces the boosted-odd max stake cumulatively per player", () => {
    expect(() =>
      assertBoostedCumulativeStakeLimit({
        selectionId: crypto.randomUUID(),
        boostedOddId: crypto.randomUUID(),
        existingStake: 25,
        requestedStake: 25,
        maxStake: 50
      })
    ).not.toThrow();

    expect(() =>
      assertBoostedCumulativeStakeLimit({
        selectionId: crypto.randomUUID(),
        boostedOddId: crypto.randomUUID(),
        existingStake: 40,
        requestedStake: 20,
        maxStake: 50
      })
    ).toThrow(ConflictError);
  });
});
