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: {ArtistesDetailsPage: {instru_and_disciplines: 'x', share_on: 'y'}}})
);

jest.mock('@/services/artisteService', () => ({
  getArtiste: jest.fn(),
  getLfa: jest.fn(),
  getImg: jest.fn(),
}));

jest.mock('@/components/Artistes/ArtisteEventSection/ArtisteEventSection', () => ({
  __esModule: true,
  default: ({aenIds, formateurAenId}: {aenIds: number[]; formateurAenId?: number}) => (
    <div data-testid="agenda" data-aens={aenIds.join('|')} data-formateur={formateurAenId ?? ''} />
  ),
}));
jest.mock('@/services/mediaService', () => ({
  getMediaPrincipalUrl: jest.fn((_t: string, id: number | string) => Promise.resolve(String(id) === '500' ? 'https://media.test/startijenn.jpg' : null)),
}));
jest.mock('@/components/shared/AnimateursGallery/AnimateursGallery', () => ({
  __esModule: true,
  default: ({animateurs, titleKey}: {animateurs: {aenLibelle: string; photoUrl: string | null; href?: string}[]; titleKey: string}) => (
    <div data-testid={`galerie-${titleKey}`} data-count={animateurs.length} data-noms={animateurs.map(a => a.aenLibelle).join('|')} data-photos={animateurs.map(a => a.photoUrl ?? '').join('|')} data-hrefs={animateurs.map(a => a.href ?? '').join('|')} />
  ),
}));
jest.mock('@/components/Artistes/ParcoursArtistique/ParcoursArtistique', () => ({
  __esModule: true,
  default: () => <div />,
}));
jest.mock('@/components/Groupes/ContactSection/ContactSection', () => ({
  __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('@/components/Epci/EpciLogoDisplay', () => ({
  __esModule: true,
  default: ({suaNom, suaArticlePartenaire}: {suaNom: string; suaArticlePartenaire?: string}) => (
    <div data-testid="epci-logo" 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('@/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;

/** L'entrée avec (ou sans) ville, pour les tests de carte. */
function withVille<T extends object>(entry: T, ville: unknown) {
  return {...entry, aenVil: ville};
}

import {getArtiste, getLfa, getImg} from '@/services/artisteService';

const mockedGetArtiste = getArtiste as jest.Mock;
const mockedGetLfa = getLfa as jest.Mock;
const mockedGetImg = getImg as jest.Mock;

const props = {params: Promise.resolve({locale: 'fr', artisteId: '2025'})};

const barou = {
  aenId: 2025,
  aenLibelle: 'BAROU Sylvain',
  aenPrenom: 'Sylvain',
  aenPatronyme: 'BAROU',
  socleListeEntrees: [],
};

describe('Page artiste', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetLfa.mockResolvedValue({aenLfa: [], filtersInstru: [], filtersGpe: [], filtersGpeActif: []});
    mockedGetImg.mockResolvedValue('');
  });

  it('shouldBuildTheDocumentTitleFromFirstNameAndLastName', async () => {
    mockedGetArtiste.mockResolvedValue(barou);

    expect(await generateMetadata(props)).toEqual({title: 'Sylvain BAROU - Tamm-Kreiz'});
  });

  it('shouldFallBackToTheSiteNameWhenTheArtisteCannotBeLoaded', async () => {
    mockedGetArtiste.mockRejectedValue(new Error('Network error'));

    expect(await generateMetadata(props)).toEqual({title: 'Tamm-Kreiz'});
  });

  it('shouldStillRenderTheArtisteHeading', async () => {
    mockedGetArtiste.mockResolvedValue(barou);

    render(await (Page as any)(props));

    expect(screen.getByRole('heading', {level: 1})).toHaveTextContent('Sylvain BAROU');
  });
});

describe('Page artiste — bloc Bio', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetLfa.mockResolvedValue({aenLfa: [], filtersInstru: [], filtersGpe: [], filtersGpeActif: []});
    mockedGetImg.mockResolvedValue('');
  });

  it('shouldDisplayTheBioWhenItIsFilled', async () => {
    mockedGetArtiste.mockResolvedValue({...barou, aenBio: '<p>Sonneur de <b>bombarde</b>.</p>'});

    render(await (Page as any)(props));

    expect(screen.getByTestId('bio-section')).toHaveTextContent('Sonneur de bombarde.');
  });

  it('shouldNotDisplayTheBioWhenItIsEmpty', async () => {
    mockedGetArtiste.mockResolvedValue({...barou, aenBio: null});

    render(await (Page as any)(props));

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

describe('Page artiste — logo et carte', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetAenLogo.mockResolvedValue(null);
    mockedGetLfa.mockResolvedValue({aenLfa: [], filtersInstru: [], filtersGpe: [], filtersGpeActif: []});
    mockedGetImg.mockResolvedValue('');
  });

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

    render(await (Page as any)(props));

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

  it('shouldNotDisplayTheLogoWithoutOne', async () => {
    mockedGetArtiste.mockResolvedValue(barou);

    render(await (Page as any)(props));

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

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

    render(await (Page as any)(props));

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

  it('shouldNotDisplayTheMapWithoutVille', async () => {
    mockedGetArtiste.mockResolvedValue(withVille(barou, undefined));

    render(await (Page as any)(props));

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

describe('Page artiste — favoris et compteur de visites', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetAenLogo.mockResolvedValue(null);
    mockedGetLfa.mockResolvedValue({aenLfa: [], filtersInstru: [], filtersGpe: [], filtersGpeActif: []});
    mockedGetImg.mockResolvedValue('');
    mockedGetArtiste.mockResolvedValue(barou);
  });

  it('shouldNameTheArtisteInTheFavoriteLoginLink', async () => {
    render(await (Page as any)(props));

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

  it('shouldCountTheVisitsOfTheEntry', async () => {
    render(await (Page as any)(props));

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

describe('Page artiste — bloc EPCI et univers', () => {
  const qbo = {suaId: 3, suaNom: 'Quimper Bretagne Occidentale', suaLogoPartenaire: 1, suaArticlePartenaire: 'https://www.tamm-kreiz.bzh/mag/territoires'};

  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetAenLogo.mockResolvedValue(null);
    mockedGetLfa.mockResolvedValue({aenLfa: [], filtersInstru: [], filtersGpe: [], filtersGpeActif: []});
    mockedGetImg.mockResolvedValue('');
  });

  it('shouldDisplayThePartnerEpciOfTheVilleWithItsArticleLink', async () => {
    mockedGetArtiste.mockResolvedValue(withVille(barou, {vilId: 5, vilNom: 'Quimper', subAutres: [qbo]}));

    render(await (Page as any)(props));

    expect(screen.getByTestId('epci-logo')).toHaveAttribute('data-article', qbo.suaArticlePartenaire);
  });

  it('shouldNotDisplayTheEpciBlockWithoutPartnerEpci', async () => {
    mockedGetArtiste.mockResolvedValue(withVille(barou, {vilId: 5, vilNom: 'Quimper', subAutres: [{...qbo, suaLogoPartenaire: 0}]}));

    render(await (Page as any)(props));

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

  it('shouldOfferTheUniversOfTheArtiste', async () => {
    mockedGetArtiste.mockResolvedValue({
      ...barou,
      socleListeEntrees: [{lieId: 12, lieNom: 'Bagadoù', lieDpr: {dprId: 1, dprNom: 'Musique traditionnelle'}}],
    });

    render(await (Page as any)(props));

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

describe('Page artiste — articles du Mag', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetAenLogo.mockResolvedValue(null);
    mockedGetLfa.mockResolvedValue({aenLfa: [], filtersInstru: [], filtersGpe: [], filtersGpeActif: []});
    mockedGetImg.mockResolvedValue('');
    mockedGetArtiste.mockResolvedValue(barou);
    mockedGetArticlesLies.mockResolvedValue([{id: 1, title: 'Les sonneurs de couple', slug: 'sonneurs-de-couple'}]);
  });

  it('shouldListTheArticlesLinkedToTheArtiste', async () => {
    render(await (Page as any)(props));

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

describe('Page artiste — sons et vidéos', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetAenLogo.mockResolvedValue(null);
    mockedGetLfa.mockResolvedValue({aenLfa: [], filtersInstru: [], filtersGpe: [], filtersGpeActif: []});
    mockedGetImg.mockResolvedValue('');
    mockedGetArtiste.mockResolvedValue(barou);
    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}, {aviId: 1, titre: 'Fest-noz', sousTitre: null, credit: null, youtubeId: 'abc', url: 'u', embedUrl: 'e', ordre: 0}]);
  });

  it('shouldOfferTheSoundsAndVideosOfTheArtiste', async () => {
    render(await (Page as any)(props));

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

describe('Page artiste — groupes actuels et agenda', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetImg.mockResolvedValue('');
    mockedGetArtiste.mockResolvedValue(barou);
  });

  it('shouldShowThePhotosOfTheActiveBandsLinkedToTheirPages', async () => {
    mockedGetLfa.mockResolvedValue({
      aenLfa: [],
      filtersInstru: [],
      filtersGpe: [
        {gpeId: '5', gpeNom: 'Startijenn', gpeActif: true, gpeAenId: '500'},
        {gpeId: '6', gpeNom: 'Ancien groupe', gpeActif: false, gpeAenId: '600'},
      ],
      filtersGpeActif: ['500'],
    });

    render(await (Page as any)(props));

    const galerie = screen.getByTestId('galerie-groupes_actuels_title');
    expect(galerie).toHaveAttribute('data-count', '1');
    expect(galerie).toHaveAttribute('data-noms', 'Startijenn');
    expect(galerie).toHaveAttribute('data-photos', 'https://media.test/startijenn.jpg');
    expect(galerie).toHaveAttribute('data-hrefs', '/fr/groupes/5');
  });

  it('shouldFeedTheAgendaWithTheArtistHimselfHisActiveBandsAndHisWorkshops', async () => {
    mockedGetLfa.mockResolvedValue({aenLfa: [], filtersInstru: [], filtersGpe: [], filtersGpeActif: ['500', '2025']});

    render(await (Page as any)(props));

    const agenda = screen.getByTestId('agenda');
    expect(agenda).toHaveAttribute('data-aens', '2025|500');
    expect(agenda).toHaveAttribute('data-formateur', '2025');
  });
});
