import {getUpcomingEvents, getEventImageUrl, getAffichesAdherents} from './evenementService';
import http from '@/http';
import type {Evenement} from '@/types/stage';

const mockedHttp = http as jest.Mocked<typeof http>;

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

  describe('getUpcomingEvents', () => {
    it('shouldReturnEventsListWhenEventsExist', async () => {
      const mockEvents: Evenement[] = [
        {
          eveId: 1,
          eveDate: '2026-03-15',
          eveHeure: '20h30',
          eveLibelle: 'Fest-noz de Quimper',
          eveTev: {tevLibelle: 'Fest-noz'},
          eveVil: {vilNom: 'Quimper', vilCodepostal: '29000', vilGeoX: -4.1, vilGeoY: 48.0, vilGeoZoom: 12},
          evePla: null,
          aenOrganisateurs: [{aenId: 10, aenLibelle: 'Kevrenn Brest'}]
        },
        {
          eveId: 2,
          eveDate: '2026-03-20',
          eveHeure: '21h00',
          eveLibelle: 'Concert Rennes',
          eveTev: {tevLibelle: 'Concert'},
          eveVil: {vilNom: 'Rennes', vilCodepostal: '35000', vilGeoX: -1.67, vilGeoY: 48.11, vilGeoZoom: 12},
          evePla: null,
          aenOrganisateurs: []
        }
      ];

      mockedHttp.get.mockResolvedValue({ status: 200,
        data: {'hydra:member': mockEvents}
      });

      const result = await getUpcomingEvents();

      expect(result).toBeDefined();
      expect(result.length).toBe(2);
      expect(result[0].eveLibelle).toBe('Fest-noz de Quimper');
      expect(result[1].eveLibelle).toBe('Concert Rennes');
      expect(mockedHttp.get).toHaveBeenCalledWith(
        expect.stringContaining('/evenements')
      );
      // Should filter by date after today
      expect(mockedHttp.get).toHaveBeenCalledWith(
        expect.stringContaining('eveDate')
      );
    });

    it('shouldReturnEmptyArrayWhenNoEventsExist', async () => {
      mockedHttp.get.mockResolvedValue({ status: 200,
        data: {'hydra:member': []}
      });

      const result = await getUpcomingEvents();

      expect(result).toBeDefined();
      expect(result).toEqual([]);
      expect(result.length).toBe(0);
    });

    it('shouldFilterByOrganisateurs', async () => {
      mockedHttp.get.mockResolvedValue({ status: 200,
        data: {'hydra:member': []}
      });

      await getUpcomingEvents({organisateurs: [10, 20]});

      expect(mockedHttp.get).toHaveBeenCalledWith(
        expect.stringContaining('aenOrganisateurs')
      );
    });

    it('shouldFilterByEventType', async () => {
      mockedHttp.get.mockResolvedValue({ status: 200,
        data: {'hydra:member': []}
      });

      await getUpcomingEvents({eveTev: 5});

      expect(mockedHttp.get).toHaveBeenCalledWith(
        expect.stringContaining('eveTev=5')
      );
    });

    it('shouldCombineEventTypeWithOtherFilters', async () => {
      mockedHttp.get.mockResolvedValue({ status: 200,
        data: {'hydra:member': []}
      });

      await getUpcomingEvents({eveTev: 5, itemsPerPage: 3});

      const calledUrl = mockedHttp.get.mock.calls[0][0];
      expect(calledUrl).toContain('eveTev=5');
      expect(calledUrl).toContain('itemsPerPage=3');
    });

    it('shouldAcceptItemsPerPageParam', async () => {
      mockedHttp.get.mockResolvedValue({ status: 200,
        data: {'hydra:member': []}
      });

      await getUpcomingEvents({itemsPerPage: 3});

      expect(mockedHttp.get).toHaveBeenCalledWith(
        expect.stringContaining('itemsPerPage=3')
      );
    });
  });

  describe('getEventImageUrl', () => {
    it('shouldReturnEventImageUrl', async () => {
      mockedHttp.get.mockResolvedValue({ status: 200,
        data: 'https://api.tamm-kreiz.bzh/media/evenement/123/affiche.jpg'
      });

      const result = await getEventImageUrl(123);

      expect(result).toBe('https://api.tamm-kreiz.bzh/media/evenement/123/affiche.jpg');
      expect(mockedHttp.get).toHaveBeenCalledWith(
        '/media/evenement/123/affiche'
      );
    });

    it('shouldReturnNullWhenEventImageNotFound', async () => {
      mockedHttp.get.mockRejectedValue({
        response: {status: 404}
      });

      const result = await getEventImageUrl(999);

      expect(result).toBeNull();
    });
  });

  describe('getUpcomingEvents — filtre domaine (spec L77)', () => {
    it('shouldFilterTheUpcomingEventsOnTheDomain', async () => {
      mockedHttp.get.mockResolvedValueOnce({status: 200, data: {'hydra:member': []}});

      await getUpcomingEvents({domaine: 2, itemsPerPage: 6});

      const url = mockedHttp.get.mock.calls[0][0] as string;
      expect(url).toContain('eveTev.tevDpr=2');
      expect(url).toContain('itemsPerPage=6');
    });
  });

  describe('getAffichesAdherents', () => {
    it('shouldFetchThePostersOfUpcomingMemberEvents', async () => {
      const affiches = [{eveId: 12, libelle: 'Fest-noz de Carhaix', date: '2026-11-07', vilNom: 'Carhaix', afficheUrl: 'https://pimcore.test/12.jpg'}];
      mockedHttp.get.mockResolvedValueOnce({status: 200, data: affiches});

      expect(await getAffichesAdherents(8)).toEqual(affiches);
      expect(mockedHttp.get).toHaveBeenCalledWith('/agenda/affiches-adherents?limit=8');
    });

    it('shouldReturnNoPosterWhenTheApiFails', async () => {
      mockedHttp.get.mockRejectedValueOnce(new Error('boom'));

      expect(await getAffichesAdherents()).toEqual([]);
    });
  });
});
