import React from 'react';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import axios from 'axios';
import MissionTab from '../components/MissionTab';

jest.mock('axios');

const mission = {
  id: 9,
  name: 'The Hunt for Fabius Bile',
  theme: 'tyranid',
  threat_level: 'High',
  player_count: 4,
  enemy_count: 59,
  gm_player: 'gm',
  current_scene: 0,
  scenes: [
    {
      title: 'Arrival at the Dead Station',
      description: 'The kill-team translates into a silent system.',
      endingText: 'The kill-team clears the dock and prepares for the next scene.',
      type: 'briefing',
      objectives: ['Secure the landing zone'],
      checks: [
        { name: 'Spot movement', skill: 'Awareness', characteristic: 'Per', target: 45, modifier: 0, reward: 'Act before the ambush.' },
      ],
      revealed: true,
      reveal: { checks: { 'Spot movement': true } },
      combat: { enemy: 'Hormagaunt', bs: 45, ws: 45, modifier: 0, damage: '1d10+5', targetTB: 3, targetArmour: 3 },
      enemies: [{ name: 'Hidden threat' }],
    },
    {
      title: 'Future Ambush',
      description: 'This scene should stay hidden until the GM activates it.',
      type: 'combat',
    },
  ],
};

describe('MissionTab player view', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    axios.get.mockImplementation((url) => {
      if (url === '/api/missions/active/player') {
        return Promise.resolve({
          data: {
            id: mission.id,
            name: mission.name,
            current_scene: 0,
            scenes: [mission.scenes[0]],
          },
        });
      }
      if (url === '/api/missions/active/rolls/feed?limit=50') return Promise.resolve({ data: [] });
      if (url === '/api/players') return Promise.resolve({ data: [{ name: 'anders' }] });
      if (url === '/api/players/anders') {
        return Promise.resolve({
          data: {
            name: 'anders',
            tabInfo: {
              characteristics: { Per: 40 },
              skills: { 'Awareness (Per)': { trained: true } },
              wounds: { current: 20, total: 20 },
            },
          },
        });
      }
      return Promise.resolve({ data: null });
    });
  });

  test('shows only the active scene to players', async () => {
    render(<MissionTab authedPlayer="anders" />);

    await waitFor(() => {
      expect(screen.getByText('Arrival at the Dead Station')).toBeInTheDocument();
    });

    expect(screen.getByText('The kill-team translates into a silent system.')).toBeInTheDocument();
    expect(screen.getByText('Secure the landing zone')).toBeInTheDocument();
    expect(screen.getAllByText('Spot movement').length).toBeGreaterThan(0);
    expect(screen.getByText('Open in Dice Roller')).toBeInTheDocument();
    expect(screen.queryByText('Table State')).not.toBeInTheDocument();
    expect(screen.queryByText('GM')).not.toBeInTheDocument();
    expect(screen.queryByText(/Enemy pressure/i)).not.toBeInTheDocument();
    expect(screen.queryByText(/Mission Scenes/i)).not.toBeInTheDocument();
    expect(screen.queryByText('Future Ambush')).not.toBeInTheDocument();
    expect(screen.queryByText(/This scene should stay hidden/i)).not.toBeInTheDocument();
    expect(screen.queryByText(/GM enemies/i)).not.toBeInTheDocument();
    expect(screen.queryByText('Hele historien til oplæsning')).not.toBeInTheDocument();
    expect(screen.queryByText('The kill-team clears the dock and prepares for the next scene.')).not.toBeInTheDocument();
    expect(axios.get).toHaveBeenCalledWith('/api/missions/active/player');
    expect(axios.get).not.toHaveBeenCalledWith('/api/missions');
    expect(axios.get).not.toHaveBeenCalledWith('/api/missions/active/current');
  });

  test('does not show GM skill condition controls unless conditions are unlocked', async () => {
    render(<MissionTab authedPlayer="anders" />);

    await waitFor(() => expect(screen.getByText('Arrival at the Dead Station')).toBeInTheDocument());
    await waitFor(() => expect(screen.getAllByText('Mini Roller').length).toBeGreaterThan(0));

    expect(screen.queryByLabelText('Skill difficulty')).not.toBeInTheDocument();
    expect(screen.queryByLabelText('Skill custom modifier')).not.toBeInTheDocument();
    expect(screen.queryByText('Show Conditions')).not.toBeInTheDocument();
    expect(screen.queryByText('Conditions Visible')).not.toBeInTheDocument();
    expect(screen.getAllByTestId('skill-target-number')[0]).toHaveTextContent('40');
    expect(screen.getByText('Conditions hidden by GM.')).toBeInTheDocument();
  });
});

describe('MissionTab mini skill modifiers', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    const activeMission = {
      ...mission,
      scenes: [{
        ...mission.scenes[0],
        checks: [
          { name: 'Spot movement', skill: 'Awareness', characteristic: 'Per', target: 45, modifier: 0, reward: 'Act before the ambush.' },
        ],
      }],
    };

    axios.get.mockImplementation((url) => {
      if (url === '/api/missions') return Promise.resolve({ data: [activeMission] });
      if (url === '/api/missions/active/current') return Promise.resolve({ data: activeMission });
      if (url === '/api/missions/active/rolls/feed?limit=50') return Promise.resolve({ data: [] });
      if (url === '/api/players') return Promise.resolve({ data: [{ name: 'anders' }] });
      if (url === '/api/players/anders') {
        return Promise.resolve({
          data: {
            name: 'anders',
            tabInfo: {
              characteristics: { Per: 40 },
              skills: { 'Awareness (Per)': { trained: true } },
              wounds: { current: 20, total: 20 },
            },
          },
        });
      }
      return Promise.resolve({ data: null });
    });
    axios.put.mockResolvedValue({ data: { mission: activeMission } });
  });

  test('uses skill difficulty and skill condition modifiers for a mission skill check target', async () => {
    render(<MissionTab authedPlayer="gm" />);

    await waitFor(() => expect(screen.getAllByText('Mini Roller').length).toBeGreaterThan(0));
    await waitFor(() => expect(screen.getAllByTestId('skill-target-number')[0]).toHaveTextContent('40'));

    fireEvent.change(screen.getAllByLabelText('Skill difficulty')[0], { target: { value: '30' } });
    expect(screen.getAllByTestId('skill-target-number')[0]).toHaveTextContent('70');

    fireEvent.click(screen.getAllByText('Poor/no tools -10')[0]);
    expect(screen.getAllByTestId('skill-target-number')[0]).toHaveTextContent('60');

    fireEvent.change(screen.getAllByLabelText('Skill custom modifier')[0], { target: { value: '-5' } });
    expect(screen.getAllByTestId('skill-target-number')[0]).toHaveTextContent('55');
  });

  test('lets the GM unlock skill conditions for players', async () => {
    render(<MissionTab authedPlayer="gm" />);

    await waitFor(() => expect(screen.getAllByText('Mini Roller').length).toBeGreaterThan(0));

    fireEvent.click(screen.getAllByText('Show Conditions')[0]);

    await waitFor(() => {
      expect(axios.put).toHaveBeenCalledWith('/api/missions/9/progress', expect.objectContaining({
        currentScene: 0,
        scenes: expect.arrayContaining([
          expect.objectContaining({ skillConditionsUnlocked: true }),
        ]),
      }));
    });
  });
});
