import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { AutodraftSettings } from '~/components/AutodraftSettings';

// Mock fetch
global.fetch = vi.fn();

describe('AutodraftSettings Component', () => {
  const defaultProps = {
    seasonId: 'season-123',
    teamId: 'team-456',
    isEnabled: false,
    mode: 'next_pick' as const,
    isMyTurn: false,
    queueOnly: false,
    onUpdate: vi.fn(),
  };

  beforeEach(() => {
    vi.clearAllMocks();
    (global.fetch as any).mockResolvedValue({
      ok: true,
      json: async () => ({ success: true }),
    });
  });

  describe('Rendering', () => {
    it('should render three autodraft state buttons', () => {
      render(<AutodraftSettings {...defaultProps} />);

      expect(screen.getByRole('button', { name: 'Off' })).toBeInTheDocument();
      expect(screen.getByRole('button', { name: 'Next Pick' })).toBeInTheDocument();
      expect(screen.getByRole('button', { name: 'All Picks' })).toBeInTheDocument();
    });

    it('should not show the queue-only toggle when autodraft is Off', () => {
      render(<AutodraftSettings {...defaultProps} isEnabled={false} />);

      expect(screen.queryByRole('switch')).not.toBeInTheDocument();
      expect(screen.queryByText('Only autodraft from queue')).not.toBeInTheDocument();
    });

    it('should show the queue-only toggle when autodraft is active', () => {
      render(<AutodraftSettings {...defaultProps} isEnabled={true} />);

      expect(screen.getByRole('switch')).toBeInTheDocument();
      expect(screen.getByText('Only autodraft from queue')).toBeInTheDocument();
    });

    it('should show disabled message when it is the user\'s turn', () => {
      render(<AutodraftSettings {...defaultProps} isMyTurn={true} />);

      expect(screen.getByText(/Autodraft settings are disabled during your pick/i)).toBeInTheDocument();
    });

    it('should mark Off as active when isEnabled=false', () => {
      render(<AutodraftSettings {...defaultProps} isEnabled={false} />);

      const offButton = screen.getByRole('button', { name: 'Off' });
      expect(offButton.className).toContain('bg-electric');
    });

    it('should mark Next Pick as active when isEnabled=true and mode=next_pick', () => {
      render(<AutodraftSettings {...defaultProps} isEnabled={true} mode="next_pick" />);

      const nextPickButton = screen.getByRole('button', { name: 'Next Pick' });
      expect(nextPickButton.className).toContain('bg-electric');
    });

    it('should mark All Picks as active when isEnabled=true and mode=while_on', () => {
      render(<AutodraftSettings {...defaultProps} isEnabled={true} mode="while_on" />);

      const allPicksButton = screen.getByRole('button', { name: 'All Picks' });
      expect(allPicksButton.className).toContain('bg-electric');
    });
  });

  describe('Button Group Interaction', () => {
    it('should switch to Next Pick when that button is clicked', async () => {
      const onUpdate = vi.fn();
      render(<AutodraftSettings {...defaultProps} isEnabled={false} onUpdate={onUpdate} />);

      fireEvent.click(screen.getByRole('button', { name: 'Next Pick' }));

      await waitFor(() => {
        expect(global.fetch).toHaveBeenCalledWith(
          '/api/autodraft/update',
          expect.objectContaining({ method: 'POST' })
        );
      });

      await waitFor(() => {
        expect(onUpdate).toHaveBeenCalledWith(true, 'next_pick', false);
      });
    });

    it('should switch to All Picks when that button is clicked', async () => {
      const onUpdate = vi.fn();
      render(<AutodraftSettings {...defaultProps} isEnabled={false} onUpdate={onUpdate} />);

      fireEvent.click(screen.getByRole('button', { name: 'All Picks' }));

      await waitFor(() => {
        expect(onUpdate).toHaveBeenCalledWith(true, 'while_on', false);
      });
    });

    it('should switch to Off when that button is clicked from an active state', async () => {
      const onUpdate = vi.fn();
      render(<AutodraftSettings {...defaultProps} isEnabled={true} onUpdate={onUpdate} />);

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

      await waitFor(() => {
        expect(onUpdate).toHaveBeenCalledWith(false, 'next_pick', false);
      });
    });

    it('should disable all buttons when it is the user\'s turn', () => {
      render(<AutodraftSettings {...defaultProps} isMyTurn={true} />);

      expect(screen.getByRole('button', { name: 'Off' })).toBeDisabled();
      expect(screen.getByRole('button', { name: 'Next Pick' })).toBeDisabled();
      expect(screen.getByRole('button', { name: 'All Picks' })).toBeDisabled();
    });

    it('should not fire API call when a button is clicked during user\'s turn', () => {
      render(<AutodraftSettings {...defaultProps} isMyTurn={true} />);

      fireEvent.click(screen.getByRole('button', { name: 'Next Pick' }));

      expect(global.fetch).not.toHaveBeenCalled();
    });

    it('should handle API errors by reverting state', async () => {
      const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
      (global.fetch as any).mockResolvedValueOnce({
        ok: false,
        json: async () => ({ error: 'Server error' }),
      });

      render(<AutodraftSettings {...defaultProps} isEnabled={false} />);

      fireEvent.click(screen.getByRole('button', { name: 'Next Pick' }));

      await waitFor(() => {
        expect(consoleSpy).toHaveBeenCalled();
      });

      // Off button should still be active (reverted)
      const offButton = screen.getByRole('button', { name: 'Off' });
      expect(offButton.className).toContain('bg-electric');

      consoleSpy.mockRestore();
    });

    it('should handle network errors by reverting state', async () => {
      const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
      (global.fetch as any).mockRejectedValueOnce(new Error('Network error'));

      render(<AutodraftSettings {...defaultProps} />);

      fireEvent.click(screen.getByRole('button', { name: 'Next Pick' }));

      await waitFor(() => {
        expect(consoleSpy).toHaveBeenCalled();
      });

      consoleSpy.mockRestore();
    });
  });

  describe('Queue-Only Toggle', () => {
    it('should send queueOnly=true when the toggle is switched on', async () => {
      const onUpdate = vi.fn();
      render(<AutodraftSettings {...defaultProps} isEnabled={true} queueOnly={false} onUpdate={onUpdate} />);

      fireEvent.click(screen.getByRole('switch'));

      await waitFor(() => {
        expect(onUpdate).toHaveBeenCalledWith(true, 'next_pick', true);
      });
    });

    it('should send queueOnly=false when the toggle is switched off', async () => {
      const onUpdate = vi.fn();
      render(<AutodraftSettings {...defaultProps} isEnabled={true} queueOnly={true} onUpdate={onUpdate} />);

      fireEvent.click(screen.getByRole('switch'));

      await waitFor(() => {
        expect(onUpdate).toHaveBeenCalledWith(true, 'next_pick', false);
      });
    });

    it('should disable the queue-only toggle when it is the user\'s turn', () => {
      render(<AutodraftSettings {...defaultProps} isEnabled={true} isMyTurn={true} />);

      expect(screen.getByRole('switch')).toBeDisabled();
    });
  });

  describe('API Integration', () => {
    it('should post correct formData when switching to Next Pick', async () => {
      render(<AutodraftSettings {...defaultProps} isEnabled={false} />);

      fireEvent.click(screen.getByRole('button', { name: 'Next Pick' }));

      await waitFor(() => {
        expect(global.fetch).toHaveBeenCalledWith(
          '/api/autodraft/update',
          expect.objectContaining({ method: 'POST', body: expect.any(FormData) })
        );
      });

      const formData = (global.fetch as any).mock.calls[0][1].body as FormData;
      expect(formData.get('seasonId')).toBe('season-123');
      expect(formData.get('teamId')).toBe('team-456');
      expect(formData.get('isEnabled')).toBe('true');
      expect(formData.get('mode')).toBe('next_pick');
      expect(formData.get('queueOnly')).toBe('false');
    });

    it('should post mode=while_on when switching to All Picks', async () => {
      render(<AutodraftSettings {...defaultProps} isEnabled={false} />);

      fireEvent.click(screen.getByRole('button', { name: 'All Picks' }));

      await waitFor(() => {
        expect(global.fetch).toHaveBeenCalled();
      });

      const formData = (global.fetch as any).mock.calls[0][1].body as FormData;
      expect(formData.get('mode')).toBe('while_on');
      expect(formData.get('isEnabled')).toBe('true');
    });

    it('should post isEnabled=false when switching to Off', async () => {
      render(<AutodraftSettings {...defaultProps} isEnabled={true} />);

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

      await waitFor(() => {
        expect(global.fetch).toHaveBeenCalled();
      });

      const formData = (global.fetch as any).mock.calls[0][1].body as FormData;
      expect(formData.get('isEnabled')).toBe('false');
    });

    it('should disable buttons during an in-flight API call', async () => {
      let resolve: any;
      (global.fetch as any).mockReturnValueOnce(new Promise((r) => { resolve = r; }));

      render(<AutodraftSettings {...defaultProps} />);

      fireEvent.click(screen.getByRole('button', { name: 'Next Pick' }));

      await waitFor(() => {
        expect(screen.getByRole('button', { name: 'Off' })).toBeDisabled();
      });

      resolve({ ok: true, json: async () => ({ success: true }) });

      await waitFor(() => {
        expect(screen.getByRole('button', { name: 'Off' })).not.toBeDisabled();
      });
    });

    it('should only process the first click when buttons are clicked rapidly', async () => {
      render(<AutodraftSettings {...defaultProps} />);

      fireEvent.click(screen.getByRole('button', { name: 'Next Pick' }));
      fireEvent.click(screen.getByRole('button', { name: 'All Picks' }));
      fireEvent.click(screen.getByRole('button', { name: 'Off' }));

      await waitFor(() => {
        expect(global.fetch).toHaveBeenCalledTimes(1);
      });
    });
  });
});
