/**
 * Full room snapshot: what a phone/TV needs to render from scratch after joining, reconnecting or
 * detecting a `seq` gap. Sent as the `state.request` ack and in `room.state` envelopes.
 */
import { z } from 'zod';
import { EventModeSchema, SeqSchema, SessionStatusSchema, TimestampSchema, UuidSchema } from './common';
import { PrivateStateSchema, PublicStateSchema, StandingSchema, PUBLIC_LEADERBOARD_SIZE } from './views';

export const AttractSchema = z.strictObject({
  /** Tonight's always-on top 10 for the TV attract loop. */
  nightlyTop: z.array(StandingSchema).max(PUBLIC_LEADERBOARD_SIZE),
  nextChampionship: z
    .strictObject({ eventId: UuidSchema, name: z.string().min(1), scheduledAt: TimestampSchema })
    .nullable(),
  nextRoundAt: TimestampSchema.nullable(),
});

export const RoomSnapshotSchema = z
  .strictObject({
    roomId: UuidSchema,
    venue: z.strictObject({ id: UuidSchema, name: z.string().min(1), joinCode: z.string().min(1) }),
    room: z.strictObject({ id: UuidSchema, name: z.string().min(1) }),
    /** The room's active GameSession (at most one; ARCHITECTURE §2.8). */
    activeSessionId: UuidSchema.nullable(),
    activeEventKind: EventModeSchema.nullable(),
    activeEventName: z.string().nullable(),
    /** Scheduled start of the active event (championships), for the lobby countdown; null if unscheduled. */
    activeEventScheduledAt: TimestampSchema.nullable(),
    /** Status of the active session (a championship lobby is WAITING until the host starts it). */
    activeSessionStatus: SessionStatusSchema.nullable(),
    /** Public view of the active session; null when the room is idle (attract mode only). */
    public: PublicStateSchema.nullable(),
    /** The caller's private view in *their* session; null for TVs and players without a session. */
    me: PrivateStateSchema.nullable(),
    mySessionId: UuidSchema.nullable(),
    /** False when the caller's session is not the active one → UI offers "Join the Championship". */
    mySessionActive: z.boolean(),
    attract: AttractSchema,
    seq: SeqSchema,
    serverNow: TimestampSchema,
  })
  .superRefine((s, ctx) => {
    if (s.roomId !== s.room.id) {
      ctx.addIssue({ code: 'custom', message: 'roomId must equal room.id', path: ['roomId'] });
    }
  });

export type Attract = z.output<typeof AttractSchema>;
export type RoomSnapshot = z.output<typeof RoomSnapshotSchema>;
