import React from 'react';
import { act, cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react';
import DeathwatchRoller from '../components/DeathwatchRoller';

const mockRoster = [
  { name: 'player1' },
  { name: 'player2' },
];

const mockPlayersByName = {
  player1: {
    name: 'player1',
    tabInfo: {
      characteristics: { ag: 40, ws: 55, bs: 30, t: 45 },
      wounds: { total: 18, current: 13 },
      weapons: [
        { name: 'Thunder Hammer', damage: '2d10+8 + Strength Bonus', special: 'Concussive' },
        { name: 'Bolt Pistol', class: 'Pistol', damage: '2d10+5', pen: 5 },
        { name: 'Krak Grenade', class: 'Thrown', damage: '3d10+4 Explosive', pen: 6 },
      ],
    },
  },
  player2: {
    name: 'player2',
    tabInfo: {
      characteristics: { ag: 35, ws: 40, bs: 45, t: 40 },
      wounds: { total: 16, current: 16 },
      weapons: [
        { name: 'Bolter', class: 'Basic', damage: '2d10+5', pen: 5 },
      ],
    },
  },
};

const mockHordes = [
  { name: 'Test Horde', horde: true, magnitude: 12, wounds: 12, tb: 4, ag: 25, ws: 30, bs: 25, damage: '1d10+3' },
];

function mockFetch(url) {
  if (url === '/api/players') {
    return Promise.resolve({ ok: true, status: 200, json: () => Promise.resolve(mockRoster) });
  }
  if (url === '/api/bestiary/enemies') {
    return Promise.resolve({ ok: true, status: 200, json: () => Promise.resolve(mockHordes) });
  }
  if (url === '/api/missions/active/player') {
    return Promise.resolve({ ok: false, status: 404, json: () => Promise.resolve({}) });
  }
  if (url === '/api/weapons') {
    return Promise.resolve({ ok: true, status: 200, json: () => Promise.resolve([]) });
  }
  if (typeof url === 'string' && url.startsWith('/api/players/')) {
    const name = decodeURIComponent(url.split('/').pop() || '');
    return Promise.resolve({ ok: true, status: 200, json: () => Promise.resolve(mockPlayersByName[name] || { name }) });
  }
  return Promise.resolve({ ok: false, status: 404, json: () => Promise.resolve({}) });
}

function makeRandomSequence() {
  const seq = [];
  // startCombat: 2 player init dice + 1 enemy init die
  seq.push(0.90, 0.70, 0.10);
  // Roll 1: player1 attacks (d100 + damage dice + uid)
  seq.push(0.30, 0.50, 0.50, 0.50);
  for (let i = seq.length; i < 100; i++) seq.push(0.50);
  return seq;
}

describe('DeathwatchRoller horde combat player main weapon handling', () => {
  beforeEach(() => {
    localStorage.clear();
    fetch.mockImplementation(mockFetch);
    jest.useFakeTimers();
  });

  afterEach(() => {
    cleanup();
    jest.useRealTimers();
    jest.restoreAllMocks();
  });

  test('uses the player main weapon with sanitized damage and working roll progression', async () => {
    const randomValues = makeRandomSequence();
    jest.spyOn(Math, 'random').mockImplementation(() => (randomValues.length ? randomValues.shift() : 0.5));

    render(<DeathwatchRoller authedPlayer="player1" />);

    fireEvent.click(await screen.findByRole('button', { name: 'Horde Combat' }));

    const getHordeEnemySelect = () => screen.getByText('Horde Enemy').parentElement.querySelector('select');
    await waitFor(() => {
      const select = getHordeEnemySelect();
      expect(select).not.toBeNull();
      expect(Array.from(select.querySelectorAll('option')).some(option => option.value === 'Test Horde')).toBe(true);
    });

    fireEvent.change(getHordeEnemySelect(), { target: { value: 'Test Horde' } });
    await waitFor(() => expect(getHordeEnemySelect().value).toBe('Test Horde'));
    await waitFor(() => expect(screen.getByText('2 player(s) selected')).toBeInTheDocument());

    fireEvent.click(screen.getByRole('button', { name: 'Start Combat' }));

    await waitFor(() => expect(screen.getByText('Horde Combat: Test Horde')).toBeInTheDocument());
    expect(screen.getByText('Thunder Hammer')).toBeInTheDocument();
    expect(screen.getByText('2d10+8')).toBeInTheDocument();

    await act(async () => {
      fireEvent.click(screen.getByRole('button', { name: 'Roll' }));
      jest.runAllTimers();
    });

    await waitFor(() => {
      expect(screen.getAllByText(/player2's turn/i).length).toBeGreaterThan(0);
      expect(screen.getByText(/Attack \d+ vs \d+ (WS|BS)/i)).toBeInTheDocument();
    });
  });
});