/**
 * Tests shipped parseDebugKey — simulates real browser KeyboardEvent shapes.
 * Shift+1 emits key='!' code='Digit1' (not key='1').
 */
import { describe, it, expect, beforeEach } from 'vitest';
import { parseDebugKey } from './debugKeys';
import { DEBUG_TELEPORT_SCENES, SCENE_KEYS } from '../data/constants';
import { Director } from './CorruptionDirector';

describe('parseDebugKey (shipped Debug key map)', () => {
  it('Shift+Digit1–7 sets day via code even when key is symbol', () => {
    // Real browser: Shift+1 → key '!', code 'Digit1'
    expect(
      parseDebugKey({ key: '!', code: 'Digit1', shiftKey: true }),
    ).toEqual({ type: 'setDay', day: 1 });
    expect(
      parseDebugKey({ key: '@', code: 'Digit2', shiftKey: true }),
    ).toEqual({ type: 'setDay', day: 2 });
    expect(
      parseDebugKey({ key: '#', code: 'Digit3', shiftKey: true }),
    ).toEqual({ type: 'setDay', day: 3 });
    expect(
      parseDebugKey({ key: '$', code: 'Digit4', shiftKey: true }),
    ).toEqual({ type: 'setDay', day: 4 });
    expect(
      parseDebugKey({ key: '%', code: 'Digit5', shiftKey: true }),
    ).toEqual({ type: 'setDay', day: 5 });
    expect(
      parseDebugKey({ key: '^', code: 'Digit6', shiftKey: true }),
    ).toEqual({ type: 'setDay', day: 6 });
    expect(
      parseDebugKey({ key: '&', code: 'Digit7', shiftKey: true }),
    ).toEqual({ type: 'setDay', day: 7 });
  });

  it('broken old path (shift+key 1-7) would fail — we do not use key for day', () => {
    // Demonstrates why key-based check is wrong; our code uses Digit*
    const broken = (ev: { key: string; shiftKey: boolean }) =>
      ev.shiftKey && ev.key >= '1' && ev.key <= '7';
    expect(broken({ key: '!', shiftKey: true })).toBe(false);
    // Our parser still works
    expect(parseDebugKey({ key: '!', code: 'Digit1', shiftKey: true }).type).toBe('setDay');
  });

  it('plain Digit0–9 teleports to all 10 scenes', () => {
    for (let i = 0; i <= 9; i++) {
      const a = parseDebugKey({
        key: String(i),
        code: `Digit${i}`,
        shiftKey: false,
      });
      expect(a).toEqual({
        type: 'teleport',
        sceneIndex: i,
        scene: DEBUG_TELEPORT_SCENES[i],
      });
    }
  });

  it('Shift+Digit does not teleport (day takes precedence)', () => {
    const a = parseDebugKey({ key: '!', code: 'Digit1', shiftKey: true });
    expect(a.type).toBe('setDay');
    expect(a).not.toMatchObject({ type: 'teleport' });
  });

  it('H/J/K/L/C/N/P/V/F1–F4', () => {
    expect(parseDebugKey({ key: 'h', code: 'KeyH', shiftKey: false })).toEqual({
      type: 'happiness',
      delta: 10,
    });
    expect(parseDebugKey({ key: 'J', code: 'KeyJ', shiftKey: true })).toEqual({
      type: 'happiness',
      delta: -10,
    });
    expect(parseDebugKey({ key: 'k', code: 'KeyK', shiftKey: false })).toEqual({
      type: 'awareness',
      delta: 10,
    });
    expect(parseDebugKey({ key: 'c', code: 'KeyC', shiftKey: false }).type).toBe('grantClues');
    expect(parseDebugKey({ key: 'n', code: 'KeyN', shiftKey: false }).type).toBe('negativeFlash');
    expect(parseDebugKey({ key: 'p', code: 'KeyP', shiftKey: false }).type).toBe(
      'forcedCelebration',
    );
    expect(parseDebugKey({ key: 'v', code: 'KeyV', shiftKey: false }).type).toBe('teleportCycle');
    expect(parseDebugKey({ key: 'F1', code: 'F1', shiftKey: false })).toEqual({
      type: 'forceEnding',
      id: 'E1',
    });
    expect(parseDebugKey({ key: 'F4', code: 'F4', shiftKey: false })).toEqual({
      type: 'forceEnding',
      id: 'E4',
    });
  });
});

describe('parseDebugKey → Director.setDay real path', () => {
  beforeEach(() => {
    Director.resetSession('调试');
  });

  it('applies setDay from Shift+Digit codes into Director', () => {
    for (let day = 1; day <= 7; day++) {
      const action = parseDebugKey({
        key: '!', // wrong symbol-like key as browser would
        code: `Digit${day}`,
        shiftKey: true,
      });
      expect(action.type).toBe('setDay');
      if (action.type === 'setDay') {
        Director.setDay(action.day);
        expect(Director.day).toBe(day);
      }
    }
  });

  it('teleport indices map to real scene keys', () => {
    const a = parseDebugKey({ key: '0', code: 'Digit0', shiftKey: false });
    expect(a.type).toBe('teleport');
    if (a.type === 'teleport') {
      expect(a.scene).toBe(SCENE_KEYS.HOUSE);
    }
    const b = parseDebugKey({ key: '1', code: 'Digit1', shiftKey: false });
    if (b.type === 'teleport') {
      expect(b.scene).toBe(SCENE_KEYS.PLAZA);
    }
  });
});
