import React from 'react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';

import ProtestReviewPage from './page';

// Mocks for Next.js navigation
const mockPush = vi.fn();

vi.mock('next/navigation', () => ({
  useRouter: () => ({
    push: mockPush,
  }),
  useParams: () => ({ id: 'league-1', protestId: 'protest-1' }),
}));

// Mock effective driver id hook
vi.mock('@/hooks/useEffectiveDriverId', () => ({
  useEffectiveDriverId: () => 'driver-1',
}));

const mockGetProtestDetailViewModel = vi.fn();
const mockFetchLeagueMemberships = vi.fn();
const mockGetMembership = vi.fn();

vi.mock('@/lib/services/ServiceProvider', () => ({
  useServices: () => ({
    leagueStewardingService: {
      getProtestDetailViewModel: mockGetProtestDetailViewModel,
    },
    protestService: {
      applyPenalty: vi.fn(),
      requestDefense: vi.fn(),
    },
    leagueMembershipService: {
      fetchLeagueMemberships: mockFetchLeagueMemberships,
      getMembership: mockGetMembership,
    },
  }),
}));

const mockIsLeagueAdminOrHigherRole = vi.fn();

vi.mock('@/lib/utilities/LeagueRoleUtility', () => ({
  LeagueRoleUtility: {
    isLeagueAdminOrHigherRole: (...args: unknown[]) => mockIsLeagueAdminOrHigherRole(...args),
  },
}));

describe('ProtestReviewPage', () => {
  beforeEach(() => {
    mockPush.mockReset();
    mockGetProtestDetailViewModel.mockReset();
    mockFetchLeagueMemberships.mockReset();
    mockGetMembership.mockReset();
    mockIsLeagueAdminOrHigherRole.mockReset();

    mockFetchLeagueMemberships.mockResolvedValue(undefined);
    mockGetMembership.mockReturnValue({ role: 'admin' });
    mockIsLeagueAdminOrHigherRole.mockReturnValue(true);
  });

  it('loads protest detail via LeagueStewardingService view model method', async () => {
    mockGetProtestDetailViewModel.mockResolvedValue({
      protest: {
        id: 'protest-1',
        raceId: 'race-1',
        protestingDriverId: 'driver-1',
        accusedDriverId: 'driver-2',
        description: 'desc',
        submittedAt: '2023-10-01T10:00:00Z',
        status: 'pending',
        incident: { lap: 1 },
      },
      race: {
        id: 'race-1',
        name: 'Test Race',
        formattedDate: '10/1/2023',
      },
      protestingDriver: { id: 'driver-1', name: 'Driver 1' },
      accusedDriver: { id: 'driver-2', name: 'Driver 2' },
      penaltyTypes: [
        {
          type: 'time_penalty',
          label: 'Time Penalty',
          description: 'Add seconds to race result',
          requiresValue: true,
          valueLabel: 'seconds',
          defaultValue: 5,
        },
      ],
      defaultReasons: { upheld: 'Upheld reason', dismissed: 'Dismissed reason' },
      initialPenaltyType: 'time_penalty',
      initialPenaltyValue: 5,
    });

    render(<ProtestReviewPage />);

    await waitFor(() => {
      expect(mockGetProtestDetailViewModel).toHaveBeenCalledWith('league-1', 'protest-1');
    });

    expect(await screen.findByText('Protest Review')).toBeInTheDocument();
  });
});