// BUG-10: deact+reactivate same round double-acts participant.
// OLD bug: reactivation re-inserted by initiative (front of pointer) →
// participant acted again before round end.
//
// 1-list model: toggleActive keeps slot position. Reactivation does NOT
// grant second turn. Each participant acts at most once per round.
//
// Test: walk rounds, count visits. Deactivate+reactivate mid-round must
// not cause any participant to act twice in same round.
//
// New API: mutating funcs are async, take ctx, return newEnc.

'use strict';

const {
  makeParticipant,
  startEncounter, nextTurn, toggleParticipantActive,
} = require('@ttrpg/shared');
const { mockCtx } = require('./_helpers');

function p(id, init) {
  return makeParticipant({ id, name: id, type: 'monster',
    initiative: init, maxHp: 100, currentHp: 100 });
}
function enc(ps) {
  return { name:'t', participants:ps, isStarted:false, isPaused:false,
    round:0, currentTurnParticipantId:null, turnOrderIds:[] };
}

describe('BUG-10: deact+reactivate same round', () => {
  test('no participant acts twice in a round after deact+reactivate', async () => {
    const { ctx } = mockCtx();
    // [a(10), b(7), c(3)]
    let e = enc([p('a',10),p('b',7),p('c',3)]);
    e = await startEncounter(e, ctx); // a current, r1

    const r1 = [];
    r1.push(e.currentTurnParticipantId); // a acts
    e = await nextTurn(e, ctx); r1.push(e.currentTurnParticipantId); // b acts

    // b already acted and is still current. Deactivate b: status edit only,
    // no turn advance. DM clicks Next Turn explicitly; nextTurn skips inactive b.
    e = await toggleParticipantActive(e, 'b', ctx); // b off, current still b
    expect(e.currentTurnParticipantId).toBe('b');
    e = await nextTurn(e, ctx); // skips inactive b → c
    r1.push(e.currentTurnParticipantId);
    // reactivate b same round; b must not re-act before round wraps.
    e = await toggleParticipantActive(e, 'b', ctx); // b on

    // nextTurn from c → round 2 (a). b must NOT re-act in round 1.
    e = await nextTurn(e, ctx);
    expect(e.round).toBe(2);
    expect(e.currentTurnParticipantId).toBe('a');

    // b acted once in r1, must act once in r2
    e = await nextTurn(e, ctx);
    expect(e.currentTurnParticipantId).toBe('b');
    e = await nextTurn(e, ctx);
    expect(e.currentTurnParticipantId).toBe('c');

    // per-round visit count
    const bCountR1 = r1.filter(id => id === 'b').length;
    expect(bCountR1).toBe(1);
  });

  test('deactivate+reactivate non-current who already acted: no re-act', async () => {
    const { ctx } = mockCtx();
    // [a(10), b(7), c(3)]. a acts, b acts, c acts (round 1 done).
    // Then deactivate a (already acted, not current since c is current).
    // Reactivate a. a must not act again until round 2.
    let e = enc([p('a',10),p('b',7),p('c',3)]);
    e = await startEncounter(e, ctx); // a
    e = await nextTurn(e, ctx); // b
    e = await nextTurn(e, ctx); // c (r1 full: a,b,c)
    // c is current. deactivate a (not current, already acted).
    e = await toggleParticipantActive(e, 'a', ctx); // a off, pointer stays c
    expect(e.currentTurnParticipantId).toBe('c');
    e = await toggleParticipantActive(e, 'a', ctx); // a on
    expect(e.currentTurnParticipantId).toBe('c');

    // nextTurn from c → a (round 2). a acts in r2, once.
    e = await nextTurn(e, ctx);
    expect(e.round).toBe(2);
    expect(e.currentTurnParticipantId).toBe('a');
  });
});
