import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { Scoreboard } from '../../components/Scoreboard';
import { Player } from '../../types';

vi.mock('framer-motion', () => ({
  motion: {
    div: ({ children, ...props }: React.PropsWithChildren<Record<string, unknown>>) => <div {...props}>{children}</div>,
  },
  AnimatePresence: ({ children }: React.PropsWithChildren) => <>{children}</>,
  useSpring: () => ({ set: vi.fn(), on: () => vi.fn() }),
  useTransform: () => ({ on: () => vi.fn() }),
  LayoutGroup: ({ children }: React.PropsWithChildren) => <>{children}</>,
}));

const createPlayer = (overrides: Partial<Player> = {}): Player => ({
  id: 'player-1',
  name: 'Test Player',
  score: 100,
  previousScore: 50,
  streak: 2,
  lastAnswerCorrect: true,
  selectedShape: 'circle',
  pointsBreakdown: {
    basePoints: 80,
    streakBonus: 10,
    comebackBonus: 0,
    firstCorrectBonus: 0,
    penalty: 0,
    total: 90,
  },
  isBot: false,
  avatarSeed: 0.5,
  color: '#ff0000',
  ...overrides,
});

describe('Scoreboard', () => {
  const defaultProps = {
    players: [
      createPlayer({ id: 'player-1', name: 'Alice', score: 200 }),
      createPlayer({ id: 'player-2', name: 'Bob', score: 150 }),
    ],
    onNext: vi.fn(),
    isHost: true,
    currentPlayerId: 'player-1',
  };

  beforeEach(() => {
    vi.clearAllMocks();
  });

  describe('host controls', () => {
    it('shows Next button for host', () => {
      render(<Scoreboard {...defaultProps} />);
      
      expect(screen.getByRole('button', { name: /Next/i })).toBeInTheDocument();
    });

    it('calls onNext when host clicks Next', async () => {
      const user = userEvent.setup();
      render(<Scoreboard {...defaultProps} />);
      
      await user.click(screen.getByRole('button', { name: /Next/i }));
      
      expect(defaultProps.onNext).toHaveBeenCalled();
    });

    it('shows waiting message for non-host non-presenter', () => {
      render(<Scoreboard {...defaultProps} isHost={false} currentPlayerId="player-2" />);
      
      expect(screen.getByText('Waiting for host...')).toBeInTheDocument();
      expect(screen.queryByRole('button', { name: /Next/i })).not.toBeInTheDocument();
    });
  });

  describe('presenter controls', () => {
    it('shows Next button for presenter (non-host)', () => {
      render(
        <Scoreboard 
          {...defaultProps} 
          isHost={false} 
          currentPlayerId="player-2"
          isPresenter={true}
          onPresenterAdvance={vi.fn()}
        />
      );
      
      expect(screen.getByRole('button', { name: /Next/i })).toBeInTheDocument();
    });

    it('calls onPresenterAdvance when presenter clicks Next', async () => {
      const user = userEvent.setup();
      const onPresenterAdvance = vi.fn();
      
      render(
        <Scoreboard 
          {...defaultProps} 
          isHost={false} 
          currentPlayerId="player-2"
          isPresenter={true}
          onPresenterAdvance={onPresenterAdvance}
        />
      );
      
      await user.click(screen.getByRole('button', { name: /Next/i }));
      
      expect(onPresenterAdvance).toHaveBeenCalled();
    });

    it('does not call onNext when presenter clicks (uses onPresenterAdvance)', async () => {
      const user = userEvent.setup();
      const onNext = vi.fn();
      const onPresenterAdvance = vi.fn();
      
      render(
        <Scoreboard 
          {...defaultProps} 
          onNext={onNext}
          isHost={false} 
          currentPlayerId="player-2"
          isPresenter={true}
          onPresenterAdvance={onPresenterAdvance}
        />
      );
      
      await user.click(screen.getByRole('button', { name: /Next/i }));
      
      expect(onPresenterAdvance).toHaveBeenCalled();
      expect(onNext).not.toHaveBeenCalled();
    });

    it('host uses onNext, not onPresenterAdvance', async () => {
      const user = userEvent.setup();
      const onNext = vi.fn();
      const onPresenterAdvance = vi.fn();
      
      render(
        <Scoreboard 
          {...defaultProps} 
          onNext={onNext}
          isHost={true} 
          isPresenter={false}
          onPresenterAdvance={onPresenterAdvance}
        />
      );
      
      await user.click(screen.getByRole('button', { name: /Next/i }));
      
      expect(onNext).toHaveBeenCalled();
      expect(onPresenterAdvance).not.toHaveBeenCalled();
    });
  });

  describe('presenter edge cases', () => {
    it('shows waiting message when isPresenter is false', () => {
      render(
        <Scoreboard 
          {...defaultProps} 
          isHost={false} 
          currentPlayerId="player-2"
          isPresenter={false}
        />
      );
      
      expect(screen.getByText('Waiting for host...')).toBeInTheDocument();
    });

    it('shows waiting message when isPresenter is undefined', () => {
      render(
        <Scoreboard 
          {...defaultProps} 
          isHost={false} 
          currentPlayerId="player-2"
        />
      );
      
      expect(screen.getByText('Waiting for host...')).toBeInTheDocument();
    });

    it('handles missing onPresenterAdvance gracefully', async () => {
      const user = userEvent.setup();
      
      render(
        <Scoreboard 
          {...defaultProps} 
          isHost={false} 
          currentPlayerId="player-2"
          isPresenter={true}
        />
      );
      
      const button = screen.getByRole('button', { name: /Next/i });
      await user.click(button);
    });

    it('both host and presenter see button, but only host uses onNext', async () => {
      const user = userEvent.setup();
      const onNext = vi.fn();
      const onPresenterAdvance = vi.fn();
      
      render(
        <Scoreboard 
          {...defaultProps} 
          onNext={onNext}
          isHost={true} 
          isPresenter={true}
          onPresenterAdvance={onPresenterAdvance}
        />
      );
      
      await user.click(screen.getByRole('button', { name: /Next/i }));
      
      expect(onNext).toHaveBeenCalled();
      expect(onPresenterAdvance).not.toHaveBeenCalled();
    });
  });

  describe('display', () => {
    it('shows Scoreboard title', () => {
      render(<Scoreboard {...defaultProps} />);
      
      expect(screen.getByText('Scoreboard')).toBeInTheDocument();
    });

    it('shows player names', () => {
      render(<Scoreboard {...defaultProps} />);
      
      expect(screen.getByText('Alice (You)')).toBeInTheDocument();
      expect(screen.getByText('Bob')).toBeInTheDocument();
    });

    it('marks current player with (You) suffix', () => {
      render(<Scoreboard {...defaultProps} currentPlayerId="player-2" />);
      
      expect(screen.getByText('Bob (You)')).toBeInTheDocument();
      expect(screen.getByText('Alice')).toBeInTheDocument();
    });
  });
});
