/**
 * Valid sample messages, typed against the engine contract so fixtures themselves can't drift.
 */
import type { HostState, PrivateState, PublicState, Standing, TileState } from '@pintrush/engine';
import type { RoomSnapshot } from '../src';

/** Deterministic RFC 9562 v4 UUIDs. */
export const uuid = (n: number): string => `00000000-0000-4000-8000-${n.toString(16).padStart(12, '0')}`;

export const IDS = {
  venue: uuid(1),
  room: uuid(2),
  event: uuid(3),
  session: uuid(4),
  round: uuid(5),
  question: uuid(6),
  alice: uuid(7),
  bob: uuid(8),
  team: uuid(9),
  device: uuid(10),
  venueUser: uuid(11),
  nextEvent: uuid(12),
} as const;

export const NOW = 1_761_750_000_000;
export const KEY = 'k_0123456789';

export const standing = (rank: number, playerId: string, nickname: string): Standing => ({
  rank,
  playerId,
  nickname,
  teamId: null,
  points: 1000 - rank * 100,
  correct: 5,
  correctTimeMs: 21_000,
  lastCorrectAt: NOW - 5_000,
  lines: 1,
});

const CATEGORIES = [
  'pop-culture',
  'history',
  'sports',
  'science',
  'geography',
  'music',
  'food-drink',
  'movies-tv',
  'general',
];

export const tiles = (): TileState[] =>
  CATEGORIES.map((category, position) => ({
    position,
    category,
    activated: position === 4,
    source: position === 4 ? 'QUESTION' : null,
    questionId: position === 4 ? IDS.question : null,
  }));

/** OPEN phase of question 3 in a RUSH round: prompt + options visible, no answer anywhere. */
export const publicOpen = (): PublicState => ({
  sessionId: IDS.session,
  eventId: IDS.event,
  mode: 'ALWAYS_ON',
  status: 'RUNNING',
  round: {
    id: IDS.round,
    index: 0,
    kind: 'RUSH',
    label: 'The Rush',
    categories: CATEGORIES.map((key) => ({ key, label: key.toUpperCase() })),
    hasBoard: true,
    questionCount: 10,
    qIndex: 2,
    phase: 'OPEN',
    phaseEndsAt: NOW + 15_000,
    finalists: null,
    estimatedEndAt: NOW + 200_000,
  },
  question: {
    id: IDS.question,
    index: 2,
    category: 'history',
    categoryLabel: 'History',
    difficulty: 'STANDARD',
    type: 'MULTIPLE_CHOICE',
    isWildcard: false,
    prompt: 'In what year did Columbus first reach the Americas?',
    options: [
      { id: 'a', text: '1498' },
      { id: 'b', text: '1507' },
      { id: 'c', text: '1492' },
      { id: 'd', text: '1519' },
    ],
    opensAt: NOW - 1_000,
    openedAt: NOW - 1_000,
    closesAt: NOW + 14_000,
  },
  reveal: null,
  answeredCount: 1,
  participantCount: 2,
  playerCount: 2,
  leaderboard: [standing(1, IDS.alice, 'Alice'), standing(2, IDS.bob, 'Bob')],
  teamLeaderboard: [],
  soloLeaderboard: [
    { rank: 1, teamId: IDS.alice, name: 'Alice', score: 900, members: 1, activeMembers: 1, isSolo: true },
  ],
  recentJoins: ['Alice', 'Bob'],
  nextRoundAt: null,
  plan: null,
  lastRound: null,
  pausedAt: null,
  predictions: null,
});

/** Same question after reveal: the correct answer is allowed now. */
export const publicRevealed = (): PublicState => {
  const s = publicOpen();
  return {
    ...s,
    round: s.round && { ...s.round, phase: 'REVEALED' },
    reveal: {
      questionId: IDS.question,
      correctOptionId: 'c',
      distribution: { a: 0, b: 1, c: 1, d: 0 },
      answeredCount: 2,
      correctCount: 1,
      fastest: [{ playerId: IDS.alice, nickname: 'Alice', elapsedMs: 3_200 }],
    },
  };
};

export const privateState = (): PrivateState => ({
  playerId: IDS.alice,
  nickname: 'Alice',
  status: 'ACTIVE',
  teamId: null,
  teamName: null,
  totals: {
    points: 900,
    correct: 5,
    answered: 6,
    correctTimeMs: 21_000,
    lastCorrectAt: NOW - 5_000,
    lines: 1,
    fullBoards: 0,
    rank: 1,
  },
  inRound: true,
  waitingForNextRound: false,
  board: {
    symmetry: 3,
    baseLayoutRow: 7,
    tiles: tiles(),
    lines: [],
    fullBoard: false,
    categoryLabels: Object.fromEntries(CATEGORIES.map((k) => [k, k.toUpperCase()])),
  },
  currentAnswer: { questionId: IDS.question, optionId: 'c', wildcardPosition: null },
  lastResult: null,
  roundPoints: 250,
  powerUps: {
    enabled: true,
    tokens: 1,
    used: [],
    available: ['SECOND_CHANCE'],
    doubleDownOn: null,
    removedOptionId: null,
  },
  isFinalist: false,
  prediction: null,
});

export const hostState = (): HostState => ({
  public: publicOpen(),
  players: [
    {
      playerId: IDS.alice,
      nickname: 'Alice',
      teamName: null,
      status: 'ACTIVE',
      points: 900,
      answered: 6,
      correct: 5,
      joinedAt: NOW - 60_000,
      isBot: false,
    },
  ],
  teams: [{ teamId: IDS.team, name: 'Quizzly Bears', members: 0 }],
  roundsCompleted: 0,
  planIndex: 0,
  planLength: null,
});

export const snapshot = (): RoomSnapshot => ({
  roomId: IDS.room,
  venue: { id: IDS.venue, name: 'The Crooked Tap', joinCode: 'DEMO' },
  room: { id: IDS.room, name: 'Main Bar' },
  activeSessionId: IDS.session,
  activeEventKind: 'ALWAYS_ON',
  activeEventName: 'Tonight at The Crooked Tap',
  activeEventScheduledAt: null,
  activeSessionStatus: 'RUNNING',
  public: publicOpen(),
  me: privateState(),
  mySessionId: IDS.alice,
  mySessionActive: true,
  attract: {
    nightlyTop: [standing(1, IDS.alice, 'Alice')],
    nextChampionship: { eventId: IDS.nextEvent, name: 'Thursday Championship', scheduledAt: NOW + 86_400_000 },
    nextRoundAt: null,
  },
  seq: 42,
  serverNow: NOW,
});
