/**
 * Carry-forward persistence test (T011b).
 *
 * Regression guard for the bug where the v2 EventEngine's cooldown map
 * (`eventLastFired`) and choice flags (`flags`) were written at runtime but
 * dropped on save/load, so cooldowns reset (and staged arcs lost their branch)
 * after every restart. Player.toJSON() must now serialize both, and the
 * constructor must rehydrate them.
 */
import { describe, it, expect } from 'vitest';
import { Player } from '../../src/models/Player.js';
import { Person } from '../../src/models/Person.js';

function makePlayer(): Player {
  return new Player({
    userId: 'user-persist',
    character: new Person({ id: 'char-1', firstname: 'Persist', ageYears: 70 }),
    status: 'playing',
  });
}

describe('Player carry-forward persistence: eventLastFired + flags', () => {
  it('defaults eventLastFired to an empty object and flags to an empty Set', () => {
    const player = makePlayer();
    expect(player.eventLastFired).toEqual({});
    expect(player.flags).toBeInstanceOf(Set);
    expect(player.flags.size).toBe(0);
  });

  it('round-trips the cooldown map through save/load', () => {
    const player = makePlayer();
    // Simulate the EventEngine recording firings.
    player.eventLastFired['lateLife.peersFuneral'] = 1200;
    player.eventLastFired['performanceReview'] = 800;

    const json = player.toJSON();
    expect(json.eventLastFired).toEqual({
      'lateLife.peersFuneral': 1200,
      performanceReview: 800,
    });

    // Reload from the serialized blob (JSON.parse mimics the DB round-trip).
    const reloaded = new Player(JSON.parse(JSON.stringify(json)) as any);
    expect(reloaded.eventLastFired).toEqual({
      'lateLife.peersFuneral': 1200,
      performanceReview: 800,
    });
  });

  it('round-trips persistent choice flags (Set -> array -> Set) through save/load', () => {
    const player = makePlayer();
    player.flags.add('lateLife.retired');
    player.flags.add('career.startedBusiness');

    const json = player.toJSON();
    // Serialized as an array (like askedQuestions), not an empty {}.
    expect(Array.isArray(json.flags)).toBe(true);
    expect(new Set(json.flags as string[])).toEqual(
      new Set(['lateLife.retired', 'career.startedBusiness'])
    );

    const reloaded = new Player(JSON.parse(JSON.stringify(json)) as any);
    expect(reloaded.flags).toBeInstanceOf(Set);
    expect(reloaded.flags.has('lateLife.retired')).toBe(true);
    expect(reloaded.flags.has('career.startedBusiness')).toBe(true);
  });

  it('keeps a fired cooldown effective across a restart (the original bug)', () => {
    const player = makePlayer();
    player.eventLastFired['lateLife.reflection'] = 5000;

    // Restart: serialize and rehydrate.
    const reloaded = new Player(JSON.parse(JSON.stringify(player.toJSON())) as any);

    // The last-fired day survives, so the selector can still enforce the
    // cooldown rather than treating the event as never-fired.
    expect(reloaded.eventLastFired['lateLife.reflection']).toBe(5000);
  });
});
