import { render, screen, waitFor } from '@testing-library/react';
import { Dashboard } from '../dashboard';
import { useAuth } from '@/lib/auth-context';
import { api } from '@/lib/api';

// Mock the auth context and API
jest.mock('@/lib/auth-context', () => ({
  useAuth: jest.fn(),
}));

jest.mock('@/lib/api', () => ({
  api: {
    getOrganizerDashboard: jest.fn(),
    getParticipantDashboard: jest.fn(),
  },
}));

describe('Dashboard', () => {
  const mockOrganizerData = {
    totalEvents: 10,
    publishedEvents: 5,
    draftEvents: 3,
    totalRegistrations: 50,
    totalRevenue: 2500.00,
    upcomingEvents: [
      { id: '1', name: 'Marathon', eventDate: '2024-06-15', registrationCount: 45 },
    ],
  };

  const mockParticipantData = {
    totalRegistrations: 5,
    upcomingEvents: 2,
    completedEvents: 3,
    cancelledRegistrations: 0,
    myRegistrations: [
      { id: '1', eventId: '1', eventName: 'Marathon', eventDate: '2024-06-15', status: 'Confirmed' },
    ],
  };

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

  describe('Organizer Dashboard', () => {
    it('renders loading state initially', () => {
      (useAuth as jest.Mock).mockReturnValue({ user: { role: 'Organizer' } });
      (api.getOrganizerDashboard as jest.Mock).mockImplementation(() => new Promise(() => {}));
      
      render(<Dashboard />);
      
      expect(screen.getByText(/loading dashboard/i)).toBeInTheDocument();
    });

    it('renders organizer dashboard with data', async () => {
      (useAuth as jest.Mock).mockReturnValue({ user: { role: 'Organizer' } });
      (api.getOrganizerDashboard as jest.Mock).mockResolvedValue(mockOrganizerData);
      
      render(<Dashboard />);
      
      await waitFor(() => {
        expect(screen.getByText('Total Events')).toBeInTheDocument();
      });
      
      expect(screen.getByText('10')).toBeInTheDocument(); // totalEvents
      expect(screen.getByText('5')).toBeInTheDocument(); // publishedEvents
      expect(screen.getByText('3')).toBeInTheDocument(); // draftEvents
      expect(screen.getByText('50')).toBeInTheDocument(); // totalRegistrations
    });

    it('displays quick action buttons for organizer', async () => {
      (useAuth as jest.Mock).mockReturnValue({ user: { role: 'Organizer' } });
      (api.getOrganizerDashboard as jest.Mock).mockResolvedValue(mockOrganizerData);
      
      render(<Dashboard />);
      
      await waitFor(() => {
        expect(screen.getByText('Create Event')).toBeInTheDocument();
      });
      
      expect(screen.getByText('Manage Events')).toBeInTheDocument();
    });

    it('shows upcoming events section', async () => {
      (useAuth as jest.Mock).mockReturnValue({ user: { role: 'Organizer' } });
      (api.getOrganizerDashboard as jest.Mock).mockResolvedValue(mockOrganizerData);
      
      render(<Dashboard />);
      
      await waitFor(() => {
        expect(screen.getByText('Upcoming Events')).toBeInTheDocument();
      });
      
      expect(screen.getByText('Marathon')).toBeInTheDocument();
    });

    it('displays revenue information', async () => {
      (useAuth as jest.Mock).mockReturnValue({ user: { role: 'Organizer' } });
      (api.getOrganizerDashboard as jest.Mock).mockResolvedValue(mockOrganizerData);
      
      render(<Dashboard />);
      
      await waitFor(() => {
        expect(screen.getByText('Revenue')).toBeInTheDocument();
      });
      
      expect(screen.getByText('$2,500.00')).toBeInTheDocument();
    });
  });

  describe('Participant Dashboard', () => {
    it('renders participant dashboard with data', async () => {
      (useAuth as jest.Mock).mockReturnValue({ user: { role: 'Participant' } });
      (api.getParticipantDashboard as jest.Mock).mockResolvedValue(mockParticipantData);
      
      render(<Dashboard />);
      
      await waitFor(() => {
        expect(screen.getByText('Total Registrations')).toBeInTheDocument();
      });
      
      expect(screen.getByText('5')).toBeInTheDocument(); // totalRegistrations
      expect(screen.getByText('2')).toBeInTheDocument(); // upcomingEvents
      expect(screen.getByText('3')).toBeInTheDocument(); // completedEvents
    });

    it('displays quick action buttons for participant', async () => {
      (useAuth as jest.Mock).mockReturnValue({ user: { role: 'Participant' } });
      (api.getParticipantDashboard as jest.Mock).mockResolvedValue(mockParticipantData);
      
      render(<Dashboard />);
      
      await waitFor(() => {
        expect(screen.getByText('Browse Events')).toBeInTheDocument();
      });
      
      expect(screen.getByText('My Registrations')).toBeInTheDocument();
    });

    it('shows my recent registrations', async () => {
      (useAuth as jest.Mock).mockReturnValue({ user: { role: 'Participant' } });
      (api.getParticipantDashboard as jest.Mock).mockResolvedValue(mockParticipantData);
      
      render(<Dashboard />);
      
      await waitFor(() => {
        expect(screen.getByText('My Recent Registrations')).toBeInTheDocument();
      });
      
      expect(screen.getByText('Marathon')).toBeInTheDocument();
      expect(screen.getByText('Confirmed')).toBeInTheDocument();
    });
  });

  describe('Negative Tests', () => {
    it('displays error when API fails', async () => {
      (useAuth as jest.Mock).mockReturnValue({ user: { role: 'Organizer' } });
      (api.getOrganizerDashboard as jest.Mock).mockRejectedValue(new Error('Network error'));
      
      render(<Dashboard />);
      
      await waitFor(() => {
        expect(screen.getByText(/failed to load dashboard/i)).toBeInTheDocument();
      });
    });

    it('handles organizer dashboard API failure', async () => {
      (useAuth as jest.Mock).mockReturnValue({ user: { role: 'Organizer' } });
      (api.getOrganizerDashboard as jest.Mock).mockRejectedValue(new Error('API Error'));
      
      render(<Dashboard />);
      
      await waitFor(() => {
        expect(screen.getByText(/api error/i)).toBeInTheDocument();
      });
    });

    it('handles participant dashboard API failure', async () => {
      (useAuth as jest.Mock).mockReturnValue({ user: { role: 'Participant' } });
      (api.getParticipantDashboard as jest.Mock).mockRejectedValue(new Error('API Error'));
      
      render(<Dashboard />);
      
      await waitFor(() => {
        expect(screen.getByText(/api error/i)).toBeInTheDocument();
      });
    });

    it('shows no data available when dashboard is null', async () => {
      (useAuth as jest.Mock).mockReturnValue({ user: { role: 'Organizer' } });
      (api.getOrganizerDashboard as jest.Mock).mockResolvedValue(null);
      
      render(<Dashboard />);
      
      await waitFor(() => {
        expect(screen.getByText(/no data available/i)).toBeInTheDocument();
      });
    });
  });
});
