import React from 'react';
import {render, screen, waitFor} from '@testing-library/react';
import UpcomingEventsSection from '../UpcomingEventsSection';
import {getUpcomingEvents} from '@/services/evenementService';

jest.mock('next/link', () => {
  return ({children, href, ...props}: {children: React.ReactNode; href: string; [key: string]: unknown}) => (
    <a href={href} {...props}>{children}</a>
  );
});

jest.mock('@/services/evenementService', () => ({
  getUpcomingEvents: jest.fn(),
}));

const mockEvents = [
  {
    eveId: 1,
    eveDate: '2026-07-18',
    eveHeure: '20h30',
    eveLibelle: 'Fest-noz de Carhaix',
    eveTev: {tevLibelle: 'Fest-noz'},
    eveVil: {vilNom: 'Carhaix-Plouguer'},
    aenOrganisateurs: [{aenLibelle: 'Loened Fall'}],
  },
  {
    eveId: 2,
    eveDate: '2026-07-19',
    eveHeure: '21h',
    eveLibelle: 'Concert Barzaz',
    eveTev: {tevLibelle: 'Concert'},
    eveVil: {vilNom: 'Perros-Guirec'},
    aenOrganisateurs: [],
  },
];

describe('UpcomingEventsSection', () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  it('shouldRenderRealEventsFromService', async () => {
    (getUpcomingEvents as jest.Mock).mockResolvedValue(mockEvents);
    render(<UpcomingEventsSection locale="fr" />);

    await waitFor(() => {
      expect(screen.getByText('Fest-noz de Carhaix')).toBeInTheDocument();
      expect(screen.getByText('Concert Barzaz')).toBeInTheDocument();
    });
    expect(getUpcomingEvents).toHaveBeenCalledWith({itemsPerPage: 6});
  });

  it('shouldRenderTypePillsAndCountBadge', async () => {
    (getUpcomingEvents as jest.Mock).mockResolvedValue(mockEvents);
    render(<UpcomingEventsSection locale="fr" />);

    await waitFor(() => {
      expect(screen.getByText('Fest-noz')).toBeInTheDocument();
      expect(screen.getByText('Concert')).toBeInTheDocument();
      expect(screen.getByText('2')).toBeInTheDocument();
    });
  });

  it('shouldRenderSeeAllLinkToAgenda', async () => {
    (getUpcomingEvents as jest.Mock).mockResolvedValue(mockEvents);
    render(<UpcomingEventsSection locale="fr" />);

    await waitFor(() => {
      const link = screen.getByText(/upcoming_see_all/);
      expect(link.closest('a')).toHaveAttribute('href', '/fr/evenements');
    });
  });

  it('shouldShowEmptyStateWhenNoEvents', async () => {
    (getUpcomingEvents as jest.Mock).mockResolvedValue([]);
    render(<UpcomingEventsSection locale="fr" />);

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

  it('shouldShowEmptyStateWhenServiceFails', async () => {
    (getUpcomingEvents as jest.Mock).mockRejectedValue(new Error('boom'));
    render(<UpcomingEventsSection locale="fr" />);

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

  it('shouldFilterOnTheDomainAndLinkToItsAgenda', async () => {
    (getUpcomingEvents as jest.Mock).mockResolvedValue(mockEvents);

    render(<UpcomingEventsSection locale="fr" domaineId={2} seeAllHref="/fr/evenements?tev=2" title="Prochains événements Musique" />);

    await waitFor(() => expect(screen.getByText('Fest-noz de Carhaix')).toBeInTheDocument());
    expect(getUpcomingEvents).toHaveBeenCalledWith(expect.objectContaining({domaine: 2}));
    expect(screen.getByRole('heading', {level: 2})).toHaveTextContent('Prochains événements Musique');
    expect(screen.getByText(/upcoming_see_all/).closest('a')).toHaveAttribute('href', '/fr/evenements?tev=2');
  });
});
