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';

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

// 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();

// Mock useLeagueAdminStatus hook
vi.mock('@/hooks/league/useLeagueAdminStatus', () => ({
  useLeagueAdminStatus: (leagueId: string, driverId: string) => ({
    data: mockGetMembership.mock.results[0]?.value ?
      (mockGetMembership.mock.results[0].value.role === 'admin' || mockGetMembership.mock.results[0].value.role === 'owner') : false,
    isLoading: false,
    isError: false,
    isSuccess: true,
    refetch: vi.fn(),
  }),
}));

// Mock useProtestDetail hook
vi.mock('@/hooks/league/useProtestDetail', () => ({
  useProtestDetail: (leagueId: string, protestId: string, enabled: boolean = true) => ({
    data: mockGetProtestDetailViewModel.mock.results[0]?.value || null,
    isLoading: false,
    isError: false,
    isSuccess: !!mockGetProtestDetailViewModel.mock.results[0]?.value,
    refetch: vi.fn(),
    retry: vi.fn(),
  }),
}));

// Mock useInject for protest service
vi.mock('@/lib/di/hooks/useInject', () => ({
  useInject: (token: symbol) => {
    if (token.toString().includes('PROTEST_SERVICE_TOKEN')) {
      return {
        applyPenalty: vi.fn(),
        requestDefense: vi.fn(),
      };
    }
    return {};
  },
}));

// Mock the static LeagueMembershipService for LeagueRoleUtility
vi.mock('@/lib/services/leagues/LeagueMembershipService', () => ({
  LeagueMembershipService: {
    getMembership: mockGetMembership,
    fetchLeagueMemberships: mockFetchLeagueMemberships,
    setLeagueMemberships: vi.fn(),
    clearLeagueMemberships: vi.fn(),
    getCachedMembershipsIterator: vi.fn(() => [][Symbol.iterator]()),
    getAllMembershipsForDriver: vi.fn(() => []),
    getLeagueMembers: vi.fn(() => []),
  },
}));

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();

    // Set up default mock implementations
    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();
  });
});