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

import UserPill from './UserPill';
import type { DriverDTO } from '@/lib/types/generated/DriverDTO';

// Mock useAuth to control session state
vi.mock('@/lib/auth/AuthContext', () => {
  return {
    useAuth: () => mockedAuthValue,
  };
});

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

// Mock services hook to inject stub driverService
const mockFindById = vi.fn();

vi.mock('@/lib/services/ServiceProvider', () => {
  return {
    useServices: () => ({
      driverService: {
        findById: mockFindById,
      },
      mediaService: {
        getDriverAvatar: vi.fn(),
      },
    }),
  };
});

interface MockSessionUser {
  id: string;
}

interface MockSession {
  user: MockSessionUser | null;
}

let mockedAuthValue: { session: MockSession | null } = { session: null };
let mockedDriverId: string | null = null;

// Provide global stats helpers used by UserPill's rating/rank computation
// They are UI-level helpers, so a minimal stub is sufficient for these tests.
(globalThis as any).getDriverStats = (driverId: string) => ({
  driverId,
  rating: 2000,
  overallRank: 10,
  wins: 5,
});

(globalThis as any).getAllDriverRankings = () => [
  { driverId: 'driver-1', rating: 2100 },
  { driverId: 'driver-2', rating: 2000 },
];

describe('UserPill', () => {
  beforeEach(() => {
    mockedAuthValue = { session: null };
    mockedDriverId = null;
    mockFindById.mockReset();
  });

  it('renders auth links when there is no session', () => {
    mockedAuthValue = { session: null };

    const { container } = render(<UserPill />);

    expect(screen.getByText('Sign In')).toBeInTheDocument();
    expect(screen.getByText('Get Started')).toBeInTheDocument();
    expect(mockFindById).not.toHaveBeenCalled();
    expect(container).toMatchSnapshot();
  });

  it('does not load driver when there is no primary driver id', async () => {
    mockedAuthValue = { session: { user: { id: 'user-1' } } };
    mockedDriverId = null;

    const { container } = render(<UserPill />);

    await waitFor(() => {
      // component should render nothing in this state
      expect(container.firstChild).toBeNull();
    });

    expect(mockFindById).not.toHaveBeenCalled();
  });

  it('loads driver via driverService and uses driver avatarUrl', async () => {
    const driver: DriverDTO = {
      id: 'driver-1',
      iracingId: 'ir-123',
      name: 'Test Driver',
      country: 'DE',
      avatarUrl: '/api/media/avatar/driver-1',
    };

    mockedAuthValue = { session: { user: { id: 'user-1' } } };
    mockedDriverId = driver.id;

    mockFindById.mockResolvedValue(driver);

    render(<UserPill />);

    await waitFor(() => {
      expect(screen.getByText('Test Driver')).toBeInTheDocument();
    });

    expect(mockFindById).toHaveBeenCalledWith('driver-1');
  });
});
