/**
 * Primitive schemas shared by every message: ids, keys, board positions, raw text inputs and the
 * engine's string-union enums (kept as runtime tuples so the UI can iterate them).
 */
import { z } from 'zod';
import { BOARD_SIZE, LINES } from '@pintrush/engine';

// ───────────────────────────── Ids & keys ─────────────────────────────

/** RFC 9562 UUID. Every database id is one (Prisma `@default(uuid()) @db.Uuid`). */
export const UuidSchema = z.uuid();
export type Uuid = z.output<typeof UuidSchema>;

/**
 * Ids inside engine-produced views. The engine treats ids as opaque strings, so views only require
 * them to be non-empty; client *inputs* use `UuidSchema` because they are looked up in the database.
 */
export const IdSchema = z.string().min(1);

/**
 * Client-generated key that makes a mutation safe to retry. A UUID (36 chars of hex and `-`) already
 * satisfies the pattern, so `crypto.randomUUID()` is the recommended generator.
 */
export const IdempotencyKeySchema = z
  .string()
  .regex(/^[A-Za-z0-9_-]{8,64}$/, 'Idempotency key must be a UUID or 8-64 characters of A-Z a-z 0-9 _ -');
export type IdempotencyKey = z.output<typeof IdempotencyKeySchema>;

/** Per-room message sequence number (ARCHITECTURE §4 "Messaging"). */
export const SeqSchema = z.int().min(0);

/** Epoch milliseconds from the server clock. Plain number: only the server produces these. */
export const TimestampSchema = z.number().min(0);

/** Server-measured duration in milliseconds. */
export const DurationMsSchema = z.number().min(0);

// ───────────────────────────── Game primitives ─────────────────────────────

/** Board cell, row-major 0..8. */
export const PositionSchema = z.int().min(0).max(BOARD_SIZE - 1);
export type Position = z.output<typeof PositionSchema>;

/** Line index 0..7 (index into the engine's `LINES`). */
export const LineIndexSchema = z.int().min(0).max(LINES.length - 1);

/** Answer option id as stored with the question (`a`..`d`, `true`/`false`, ...). */
export const OptionIdSchema = z.string().min(1).max(8);

/** Venue join code printed on QR posters; the server matches it case-insensitively. */
export const VenueCodeSchema = z.string().regex(/^[A-Za-z0-9]{2,12}$/, 'Venue code must be 2-12 letters or digits');

/**
 * Raw text caps. They only bound what the server is willing to normalise; the real rules
 * (NFKC, 2-16 chars, allowed characters, profanity) run server-side via the engine's validators.
 */
export const NICKNAME_INPUT_MAX_LENGTH = 40;
export const TEAM_NAME_INPUT_MAX_LENGTH = 40;

export const NicknameInputSchema = z.string().min(1).max(NICKNAME_INPUT_MAX_LENGTH);
export type NicknameInput = z.output<typeof NicknameInputSchema>;

/**
 * Raw team name. `null` = no team. An empty/blank string is accepted here and treated as "no team"
 * by server normalisation, so a cleared form field never fails the whole request.
 */
export const TeamNameInputSchema = z.string().max(TEAM_NAME_INPUT_MAX_LENGTH).nullable();
export type TeamNameInput = z.output<typeof TeamNameInputSchema>;

// ───────────────────────────── Engine enums ─────────────────────────────

export const EVENT_MODES = ['ALWAYS_ON', 'CHAMPIONSHIP'] as const;
export const SESSION_STATUSES = ['WAITING', 'RUNNING', 'PAUSED', 'COMPLETED'] as const;
export const ROUND_KINDS = ['RUSH', 'MUSIC_MAYHEM', 'TABLE_WARS', 'POWER_ROUND', 'FINAL_RUSH'] as const;
export const DIFFICULTIES = ['STANDARD', 'DIFFICULT'] as const;
export const QUESTION_TYPES = ['MULTIPLE_CHOICE', 'TRUE_FALSE'] as const;
export const POWER_UP_TYPES = ['DOUBLE_DOWN', 'SECOND_CHANCE', 'CATEGORY_SWAP'] as const;
export const PLAYER_STATUSES = ['ACTIVE', 'KICKED', 'LEFT'] as const;
export const TILE_SOURCES = ['QUESTION', 'WILDCARD'] as const;
export const ROUND_PHASES = ['INTRO', 'PENDING', 'OPEN', 'LOCKED', 'REVEALED', 'ROUND_OVER'] as const;

export const EventModeSchema = z.enum(EVENT_MODES);
export const SessionStatusSchema = z.enum(SESSION_STATUSES);
export const RoundKindSchema = z.enum(ROUND_KINDS);
export const DifficultySchema = z.enum(DIFFICULTIES);
export const QuestionTypeSchema = z.enum(QUESTION_TYPES);
export const PowerUpTypeSchema = z.enum(POWER_UP_TYPES);
export const PlayerStatusSchema = z.enum(PLAYER_STATUSES);
export const TileSourceSchema = z.enum(TILE_SOURCES);
export const RoundPhaseSchema = z.enum(ROUND_PHASES);
