import React from 'react';
import {render, screen} from '@testing-library/react';

jest.mock('next-intl', () => ({
  NextIntlClientProvider: ({children}: {children: React.ReactNode}) => <>{children}</>,
  useTranslations: () => (key: string) => key,
}));

jest.mock('@/i18n', () =>
  jest.fn().mockResolvedValue({messages: {GroupePage: {}}})
);

jest.mock('@/services/groupeService', () => ({
  getGroupe: jest.fn(),
}));
jest.mock('@/services/entreeRelationsService', () => ({
  getEntreeRelations: jest.fn().mockResolvedValue({meres: [], filles: [], federations: []}),
  galerieEntrees: jest.fn((_locale: string, entrees: {aenId: number; aenLibelle: string}[]) =>
    Promise.resolve(entrees.map(e => ({aenId: e.aenId, aenLibelle: e.aenLibelle, photoUrl: null, href: `/fr/groupes/${e.aenId}`})))),
}));
jest.mock('@/services/mediaService', () => ({
  getMediaPrincipalUrl: jest.fn((_t: string, id: number) => Promise.resolve(id === 1 ? 'https://media.test/anna.jpg' : null)),
}));
jest.mock('@/components/shared/AnimateursGallery/AnimateursGallery', () => ({
  __esModule: true,
  default: ({animateurs, titleKey}: {animateurs: {aenId: number; photoUrl: string | null; href?: string}[]; titleKey: string}) => (
    <div data-testid={`galerie-${titleKey}`} data-count={animateurs.length} data-photos={animateurs.map(a => a.photoUrl ?? '').join('|')} data-hrefs={animateurs.map(a => a.href ?? '').join('|')} />
  ),
}));

jest.mock('@/components/Epci/EpciLogoDisplay', () => ({
  __esModule: true,
  default: ({suaId, suaNom, suaArticlePartenaire}: {suaId: number; suaNom: string; suaArticlePartenaire?: string}) => (
    <div data-testid="epci-logo" data-sua-id={suaId} data-article={suaArticlePartenaire}>{suaNom}</div>
  ),
}));
jest.mock('@/components/shared/UniversSection/UniversSection', () => ({
  __esModule: true,
  default: ({listes, locale}: {listes?: unknown[]; locale: string}) => (
    <div data-testid="univers" data-count={listes?.length ?? 0} data-locale={locale} />
  ),
}));

jest.mock('@/components/Groupes/ContactSection/ContactSection', () => ({
  __esModule: true,
  default: () => <div />,
}));
jest.mock('@/components/Groupes/Discographie/Discographie', () => ({
  __esModule: true,
  default: () => <div />,
}));
jest.mock('@/components/Groupes/EventGroupeSection/EventGroupeSection', () => ({
  __esModule: true,
  default: () => <div />,
}));
jest.mock('@/components/Groupes/HistorySection/HistorySection', () => ({
  __esModule: true,
  default: () => <div />,
}));
jest.mock('@/components/Groupes/MemberCard/MemberCard', () => ({
  __esModule: true,
  default: () => <div />,
}));
jest.mock('@/components/Groupes/GroupeHeroImage', () => ({
  __esModule: true,
  default: () => <div />,
}));
jest.mock('@/components/community/FavoriteButton', () => ({
  __esModule: true,
  default: ({libelle}: {libelle: string}) => <div data-testid="favorite-button" data-libelle={libelle} />,
}));
jest.mock('@/components/shared/VisitCounter/VisitCounter', () => ({
  __esModule: true,
  default: ({tableCible, cibleId}: {tableCible: string; cibleId: number}) => (
    <div data-testid="visit-counter" data-table={tableCible} data-cible={cibleId} />
  ),
}));


jest.mock('@/services/articleLienService', () => ({
  getArticlesLies: jest.fn().mockResolvedValue([]),
}));
jest.mock('@/components/shared/ArticlesLiesSection/ArticlesLiesSection', () => ({
  __esModule: true,
  default: ({articles, locale}: {articles?: unknown[]; locale: string}) => (
    <div data-testid="articles-lies" data-count={articles?.length ?? 0} data-locale={locale} />
  ),
}));
jest.mock('@/services/mediaAnnuaireService', () => ({
  getSons: jest.fn().mockResolvedValue([]),
  getVideos: jest.fn().mockResolvedValue([]),
}));
jest.mock('@/components/shared/SonsSection/SonsSection', () => ({
  __esModule: true,
  default: ({sons}: {sons?: unknown[]}) => <div data-testid="sons" data-count={sons?.length ?? 0} />,
}));
jest.mock('@/components/Annuaire/VideosSection/VideosSection', () => ({
  __esModule: true,
  default: ({videos}: {videos?: unknown[]}) => <div data-testid="videos" data-count={videos?.length ?? 0} />,
}));
jest.mock('@/services/logoService', () => ({
  getAenLogo: jest.fn(),
}));
jest.mock('@/components/global/CarteLeafletSingleClient', () => ({
  __esModule: true,
  default: () => <div data-testid="carte" />,
}));
import Page, {generateMetadata} from '../page';
import {getAenLogo} from '@/services/logoService';

const mockedGetAenLogo = getAenLogo as jest.Mock;
import {getSons, getVideos} from '@/services/mediaAnnuaireService';

const mockedGetSons = getSons as jest.Mock;
const mockedGetVideos = getVideos as jest.Mock;
import {getArticlesLies} from '@/services/articleLienService';

const mockedGetArticlesLies = getArticlesLies as jest.Mock;

/** Le groupe avec (ou sans) ville sur son entrée, pour les tests de carte. */
function withVille(groupe: ReturnType<typeof groupeWithSubAutres>, ville: unknown) {
  return {...groupe, fmuAen: {...groupe.fmuAen, aenVil: ville}};
}

import {getGroupe} from '@/services/groupeService';

const mockedGetGroupe = getGroupe as jest.Mock;

function groupeWithSubAutres(subAutres: unknown[]) {
  return {
    fmuAen: {
      aenId: 12,
      aenLibelle: 'Bagad Kemper',
      aenImg: '',
      aenVil: {vilId: 5, vilNom: 'Quimper', subAutres},
    },
    fmuLfa: [],
  };
}

async function renderPage() {
  const jsx = await (Page as any)({
    params: Promise.resolve({locale: 'fr', groupeId: '12'}),
  });
  render(jsx);
}

describe('Groupe page — bloc EPCI', () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  it('shouldDisplayEpciLogoWhenVilleHasPartnerEpci', async () => {
    mockedGetGroupe.mockResolvedValue(
      groupeWithSubAutres([
        {suaId: 3, suaNom: 'Quimper Bretagne Occidentale', suaLogoPartenaire: 1},
      ])
    );

    await renderPage();

    expect(screen.getByTestId('epci-logo')).toHaveAttribute('data-sua-id', '3');
  });

  it('shouldNotDisplayEpciLogoWhenNoPartnerEpci', async () => {
    mockedGetGroupe.mockResolvedValue(
      groupeWithSubAutres([
        {suaId: 3, suaNom: 'Quimper Bretagne Occidentale', suaLogoPartenaire: 0},
      ])
    );

    await renderPage();

    expect(screen.queryByTestId('epci-logo')).not.toBeInTheDocument();
  });

  it('shouldNotDisplayEpciLogoWhenGroupeHasNoVille', async () => {
    mockedGetGroupe.mockResolvedValue({
      fmuAen: {aenId: 12, aenLibelle: 'Bagad Kemper', aenImg: ''},
      fmuLfa: [],
    });

    await renderPage();

    expect(screen.queryByTestId('epci-logo')).not.toBeInTheDocument();
  });
});

describe('Groupe page — balise title', () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  it('shouldBuildTheDocumentTitleFromTheLabel', async () => {
    mockedGetGroupe.mockResolvedValue(groupeWithSubAutres([]));

    expect(await generateMetadata({params: Promise.resolve({locale: 'fr', groupeId: '12'})}))
      .toEqual({title: 'Bagad Kemper - Tamm-Kreiz'});
  });

  it('shouldFallBackToTheSiteNameWhenTheGroupeCannotBeLoaded', async () => {
    mockedGetGroupe.mockRejectedValue(new Error('not found'));

    expect(await generateMetadata({params: Promise.resolve({locale: 'fr', groupeId: '12'})}))
      .toEqual({title: 'Tamm-Kreiz'});
  });
});

describe('Groupe page — bloc Bio', () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  it('shouldDisplayTheBioWhenItIsFilled', async () => {
    const groupe = groupeWithSubAutres([]);
    mockedGetGroupe.mockResolvedValue({...groupe, fmuAen: {...groupe.fmuAen, aenBio: '<p>Bagad fondé en <b>1949</b>.</p>'}});

    await renderPage();

    expect(screen.getByTestId('bio-section')).toHaveTextContent('Bagad fondé en 1949.');
  });

  it('shouldNotDisplayTheBioWhenItIsEmpty', async () => {
    mockedGetGroupe.mockResolvedValue(groupeWithSubAutres([]));

    await renderPage();

    expect(screen.queryByTestId('bio-section')).not.toBeInTheDocument();
  });
});

describe('Groupe page — logo et carte', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetAenLogo.mockResolvedValue(null);
  });

  it('shouldDisplayTheLogoWhenItIsConfigured', async () => {
    mockedGetAenLogo.mockResolvedValue('https://media.tamm-kreiz.bzh/logo.png');
    mockedGetGroupe.mockResolvedValue(groupeWithSubAutres([]));

    await renderPage();

    expect(screen.getByTestId('aen-logo')).toHaveAttribute('src', 'https://media.tamm-kreiz.bzh/logo.png');
  });

  it('shouldNotDisplayTheLogoWithoutOne', async () => {
    mockedGetGroupe.mockResolvedValue(groupeWithSubAutres([]));

    await renderPage();

    expect(screen.queryByTestId('aen-logo')).not.toBeInTheDocument();
  });

  it('shouldDisplayTheMapWhenTheVilleIsKnown', async () => {
    mockedGetGroupe.mockResolvedValue(withVille(groupeWithSubAutres([]), {vilId: 5, vilNom: 'Quimper', vilGeoX: 47.996, vilGeoY: -4.102, vilGeoZoom: 12}));

    await renderPage();

    expect(screen.getByTestId('map-section')).toBeInTheDocument();
    expect(screen.getByTestId('carte')).toBeInTheDocument();
  });

  it('shouldNotDisplayTheMapWithoutVille', async () => {
    mockedGetGroupe.mockResolvedValue(withVille(groupeWithSubAutres([]), undefined));

    await renderPage();

    expect(screen.queryByTestId('map-section')).not.toBeInTheDocument();
  });
});

describe('Groupe page — favoris et compteur de visites', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetAenLogo.mockResolvedValue(null);
    mockedGetGroupe.mockResolvedValue(groupeWithSubAutres([]));
  });

  it('shouldNameTheGroupeInTheFavoriteLoginLink', async () => {
    await renderPage();

    expect(screen.getByTestId('favorite-button')).toHaveAttribute('data-libelle', 'Bagad Kemper');
  });

  it('shouldCountTheVisitsOfTheEntry', async () => {
    await renderPage();

    const counter = screen.getByTestId('visit-counter');
    expect(counter).toHaveAttribute('data-table', 'annuaire_entree');
    expect(counter).toHaveAttribute('data-cible', '12');
  });
});

describe('Groupe page — lien article EPCI et univers', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetAenLogo.mockResolvedValue(null);
  });

  it('shouldPassTheArticleLinkToThePartnerEpciBlock', async () => {
    mockedGetGroupe.mockResolvedValue(
      groupeWithSubAutres([{suaId: 3, suaNom: 'QBO', suaLogoPartenaire: 1, suaArticlePartenaire: 'https://www.tamm-kreiz.bzh/mag/territoires'}])
    );

    await renderPage();

    expect(screen.getByTestId('epci-logo')).toHaveAttribute('data-article', 'https://www.tamm-kreiz.bzh/mag/territoires');
  });

  it('shouldOfferTheUniversOfTheGroupe', async () => {
    const groupe = groupeWithSubAutres([]);
    mockedGetGroupe.mockResolvedValue({
      ...groupe,
      fmuAen: {...groupe.fmuAen, socleListeEntrees: [{lieId: 12, lieNom: 'Bagadoù', lieDpr: {dprId: 1, dprNom: 'Musique traditionnelle'}}]},
    });

    await renderPage();

    const univers = screen.getByTestId('univers');
    expect(univers).toHaveAttribute('data-count', '1');
    expect(univers).toHaveAttribute('data-locale', 'fr');
  });
});

describe('Groupe page — articles du Mag', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetAenLogo.mockResolvedValue(null);
    mockedGetGroupe.mockResolvedValue(groupeWithSubAutres([]));
    mockedGetArticlesLies.mockResolvedValue([{id: 1, title: 'Les sonneurs de couple', slug: 'sonneurs-de-couple'}]);
  });

  it('shouldListTheArticlesLinkedToTheGroupe', async () => {
    await renderPage();

    expect(mockedGetArticlesLies).toHaveBeenCalledWith('annuaire_entree', 12);
    const section = screen.getByTestId('articles-lies');
    expect(section).toHaveAttribute('data-count', '1');
    expect(section).toHaveAttribute('data-locale', 'fr');
  });
});

describe('Groupe page — sons et vidéos', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetAenLogo.mockResolvedValue(null);
    mockedGetGroupe.mockResolvedValue(groupeWithSubAutres([]));
    mockedGetSons.mockResolvedValue([{asoId: 1, titre: 'Gavotte', taille: 10, ordre: 0, url: 'https://media.tamm-kreiz.bzh/gavotte.mp3'}]);
    mockedGetVideos.mockResolvedValue([{aviId: 1, titre: 'Fest-noz', sousTitre: null, credit: null, youtubeId: 'abc', url: 'u', embedUrl: 'e', ordre: 0}]);
  });

  it('shouldOfferTheSoundsAndVideosOfTheGroupe', async () => {
    await renderPage();

    expect(mockedGetSons).toHaveBeenCalledWith(12);
    expect(mockedGetVideos).toHaveBeenCalledWith(12);
    expect(screen.getByTestId('sons')).toHaveAttribute('data-count', '1');
    expect(screen.getByTestId('videos')).toHaveAttribute('data-count', '1');
  });
});

describe('Groupe page — membres, photos et voir aussi', () => {
  const membre = (aenId: number, aenLibelle: string, lfaJusqua: string) => ({lfaAen: {aenId, aenLibelle}, lfaDepuis: '2010', lfaJusqua, lfaIns: []});

  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetArticlesLies.mockResolvedValue([]);
    mockedGetSons.mockResolvedValue([]);
    mockedGetVideos.mockResolvedValue([]);
  });

  it('shouldTreatAFutureEndDateAsACurrentMemberAndShowTheirPhotos', async () => {
    mockedGetGroupe.mockResolvedValue({...groupeWithSubAutres([]), fmuLfa: [membre(1, 'Anna', '2030'), membre(2, 'Yann', '2010')]});

    await renderPage();

    const galerie = screen.getByTestId('galerie-membres_actuels_title');
    expect(galerie).toHaveAttribute('data-count', '1');
    expect(galerie).toHaveAttribute('data-photos', 'https://media.test/anna.jpg');
  });

  it('shouldShowParentAndChildStructures', async () => {
    const {getEntreeRelations} = jest.requireMock('@/services/entreeRelationsService');
    getEntreeRelations.mockResolvedValue({meres: [{aenId: 3, aenLibelle: 'Kevrenn', aenMorale: 1}], filles: [{aenId: 4, aenLibelle: 'Bagadig', aenMorale: 1}], federations: []});
    mockedGetGroupe.mockResolvedValue(groupeWithSubAutres([]));

    await renderPage();

    expect(screen.getByTestId('galerie-voir_aussi_parents_title')).toHaveAttribute('data-hrefs', '/fr/groupes/3');
    expect(screen.getByTestId('galerie-voir_aussi_enfants_title')).toHaveAttribute('data-hrefs', '/fr/groupes/4');
  });
});
