/**
 * Proves the compile-time drift guards in src/alignment.ts actually bite: each `@ts-expect-error`
 * below must be an error, or `pnpm --filter @pintrush/protocol typecheck` fails ("unused directive").
 */
import { describe, expect, it } from 'vitest';
import type { PrivateState, PublicState, QuestionResult, Standing } from '@pintrush/engine';
import type { ClientToServerEvents, PublicStateSchema, PrivateStateSchema, QuestionResultSchema, ServerToClientEvents, StandingSchema } from '../src';
import type { Equal, Expect, SchemaMatches } from '../src/type-utils';

type Drift = [
  // Engine adds a required field the schema lacks.
  // @ts-expect-error
  Expect<SchemaMatches<typeof StandingSchema, Standing & { badge: string }>>,
  // Engine adds an optional field: strict parsing would reject it, so this must fail too.
  // @ts-expect-error
  Expect<SchemaMatches<typeof PublicStateSchema, PublicState & { spotlight?: string }>>,
  // Engine removes a field the schema still has.
  // @ts-expect-error
  Expect<SchemaMatches<typeof StandingSchema, Omit<Standing, 'lines'>>>,
  // Nullability change.
  // @ts-expect-error
  Expect<SchemaMatches<typeof StandingSchema, Omit<Standing, 'teamId'> & { teamId: string }>>,
  // Optional → required.
  // @ts-expect-error
  Expect<SchemaMatches<typeof QuestionResultSchema, Omit<QuestionResult, 'challengeWinners'> & { challengeWinners: string[] }>>,
  // Nested change deep inside PrivateState.
  // @ts-expect-error
  Expect<SchemaMatches<typeof PrivateStateSchema, Omit<PrivateState, 'powerUps'> & { powerUps: PrivateState['powerUps'] & { keys: string[] } }>>,
];

// The real alignments hold (also enforced in src/alignment.ts).
type Holds = [
  Expect<SchemaMatches<typeof PublicStateSchema, PublicState>>,
  Expect<SchemaMatches<typeof PrivateStateSchema, PrivateState>>,
  // Intersections and their flattened form are the same type after normalisation.
  Expect<SchemaMatches<typeof StandingSchema, Pick<Standing, 'rank' | 'playerId'> & Omit<Standing, 'rank' | 'playerId'>>>,
  // Socket maps: payload and ack types line up with the schemas.
  Expect<Equal<Parameters<ClientToServerEvents['powerup.activate']>[0]['type'], 'DOUBLE_DOWN' | 'SECOND_CHANCE' | 'CATEGORY_SWAP'>>,
  Expect<Equal<Parameters<ServerToClientEvents['session.token']>[0]['data']['expiresAt'], number>>,
];

describe('alignment guards', () => {
  it('are type-level only (checked by tsc)', () => {
    const drift: Drift['length'] = 6;
    const holds: Holds['length'] = 5;
    expect(drift + holds).toBe(11);
  });
});
