import { describe, expect, it } from 'vitest';
import { extractPayload } from '../../src/contracts/extract-payload.js';
import { WEBSOCKET_COMMANDS } from '../../src/contracts/websocket-commands.js';

describe('envelope extraction', () => {
  it('extracts message-field payloads', () => {
    const envelope = { type: 'quitHabit', message: 'smoking' };
    expect(extractPayload(envelope)).toEqual({
      commandType: 'quitHabit',
      payload: 'smoking',
    });
  });

  it('extracts command alias for start/stop/restart', () => {
    expect(extractPayload({ type: 'command', message: 'restart' })).toEqual({
      commandType: 'restart',
      payload: { type: 'command', message: 'restart' },
    });
  });

  it('extracts nested command envelopes', () => {
    const envelope = {
      type: 'command',
      message: {
        type: 'eventResponse',
        message: { eventId: 'e1', choiceId: 'c1' },
      },
    };
    expect(extractPayload(envelope)).toEqual({
      commandType: 'eventResponse',
      payload: { eventId: 'e1', choiceId: 'c1' },
    });
  });

  it('passes through top-level envelopes unchanged as payload root', () => {
    const envelope = { type: 'exportData', userId: 'user-123' };
    expect(extractPayload(envelope)).toEqual({
      commandType: 'exportData',
      payload: envelope,
    });
  });

  it('handles type-only commands with empty message', () => {
    expect(extractPayload({ type: 'getAchievements' })).toEqual({
      commandType: 'getAchievements',
      payload: { type: 'getAchievements' },
    });
  });

  it('handles speed numeric message', () => {
    expect(extractPayload({ type: 'speed', message: 500 })).toEqual({
      commandType: 'speed',
      payload: 500,
    });
  });

  it('covers manifest envelope types with at least one fixture each', () => {
    const covered = new Set<string>();

    for (const [name, contract] of Object.entries(WEBSOCKET_COMMANDS)) {
      if (contract.envelope === 'init-only') {
        covered.add('init-only');
        expect(extractPayload({ type: 'init', userID: 'abc' }).commandType).toBe('init');
        continue;
      }
      if (contract.envelope === 'command-alias') {
        covered.add('command-alias');
        expect(extractPayload({ type: 'command', message: name }).commandType).toBe(name);
        continue;
      }
      if (contract.envelope === 'empty') {
        covered.add('empty');
        expect(extractPayload({ type: name }).commandType).toBe(name);
        continue;
      }
      if (contract.envelope === 'top-level') {
        covered.add('top-level');
        continue;
      }
      if (contract.envelope === 'message-field') {
        covered.add('message-field');
      }
    }

    expect(covered.has('message-field')).toBe(true);
    expect(covered.has('command-alias')).toBe(true);
    expect(covered.has('empty')).toBe(true);
    expect(covered.has('init-only')).toBe(true);
  });
});
