// RED: reslot must fire on ALL 4 participant-mutation paths.
// Path 1 add, path 2 edit modal, path 3 drag (already correct), path 4 inline field (already correct).
// Tests add + edit modal reslot. Drag + inline already covered.
import React from 'react';
import { screen, waitFor, within, fireEvent } from '@testing-library/react';
import '@testing-library/jest-dom';
import { renderApp, createCampaignViaUI, selectCampaignByName, createEncounterViaUI, selectEncounterByName, getParticipantForm, addMonsterViaUI } from './testHelpers';
import { getCalls } from '../__mocks__/firebase/_mock-db';

function lastParticipantsUpdate() {
  const calls = getCalls().filter(c => c.fn === 'updateDoc' && c.path.includes('/encounters/'));
  const last = calls[calls.length - 1];
  return last && last.data.participants;
}

async function addOne(form, name, hp, mod, init) {
  fireEvent.change(form.getByPlaceholderText('e.g., Dire Wolf'), { target: { value: name } });
  fireEvent.change(form.getByLabelText(/Init Mod/i), { target: { value: String(mod) } });
  fireEvent.change(document.getElementById('monsterMaxHp'), { target: { value: String(hp) } });
  fireEvent.change(form.getByPlaceholderText('auto'), { target: { value: String(init) } });
  fireEvent.click(form.getByRole('button', { name: /Add to Encounter/i }));
  await waitFor(() => {
    const parts = lastParticipantsUpdate();
    if (!parts || !parts.some(p => p.name === name)) throw new Error('not added');
  });
}

describe('reslot on all mutation paths', () => {
  test('add inserts at correct init position (not append)', async () => {
    await renderApp();
    await createCampaignViaUI('Camp');
    await selectCampaignByName('Camp');
    await createEncounterViaUI('Enc');
    await selectEncounterByName('Enc');

    const form = within(getParticipantForm());
    // add Orc(5) first, then Goblin(8) — Goblin should slot ABOVE Orc, not append below
    await addOne(form, 'Orc', 15, 0, 5);
    await addOne(form, 'Goblin', 7, 2, 8);

    const parts = lastParticipantsUpdate();
    expect(parts.map(p => p.name)).toEqual(['Goblin', 'Orc']);
  });

  test('edit modal init change reslots participant', async () => {
    await renderApp();
    await createCampaignViaUI('Camp2');
    await selectCampaignByName('Camp2');
    await createEncounterViaUI('Enc2');
    await selectEncounterByName('Enc2');

    const form = within(getParticipantForm());
    await addOne(form, 'Orc', 15, 0, 5);
    await addOne(form, 'Goblin', 7, 2, 3);

    // pre: Orc(5) before Goblin(3)
    expect(lastParticipantsUpdate().map(p => p.name)).toEqual(['Orc', 'Goblin']);

    // open edit modal for Goblin, bump init to 8
    const editBtns = screen.getAllByRole('button', { name: 'Edit participant' });
    const goblinEdit = editBtns.find(b => b.closest('li')?.textContent.includes('Goblin'));
    fireEvent.click(goblinEdit);

    await waitFor(() => screen.getByText(`Edit Goblin`));
    // modal renders after row inputs; take last Initiative-labeled input
    const initInputs = screen.getAllByLabelText('Initiative');
    fireEvent.change(initInputs[initInputs.length - 1], { target: { value: '8' } });
    const saveBtns = screen.getAllByRole('button', { name: /Save/i });
    fireEvent.click(saveBtns[saveBtns.length - 1]);

    await waitFor(() => {
      const parts = lastParticipantsUpdate();
      expect(parts.map(p => p.name)).toEqual(['Goblin', 'Orc']);
    });
  });
});
