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: {FedeDetailsPage: {}}})
);

jest.mock('@/services/federationService', () => ({
  getFederation: jest.fn(),
  getAnnuaireEntree: jest.fn(),
  getImg: jest.fn(),
  getFederes: jest.fn().mockResolvedValue({fedId: 3, fedAenId: 77, fedLibelle: 'Sonerion', federes: []}),
}));
jest.mock('@/components/shared/AnimateursGallery/AnimateursGallery', () => ({
  __esModule: true,
  default: ({animateurs, titleKey}: {animateurs: {aenId: number; aenLibelle: string; photoUrl: string | null; href?: string}[]; titleKey?: string}) => (
    <div data-testid="federes" data-title={titleKey} data-count={animateurs.length} data-hrefs={animateurs.map((a) => a.href).join('|')} data-photos={animateurs.map((a) => a.photoUrl ?? '').join('|')} />
  ),
}));

jest.mock('@/components/Groupes/ContactSection/ContactSection', () => ({__esModule: true, default: () => <div />}));
jest.mock('@/components/Annuaire/OrganisateurEventSection/OrganisateurEventSection', () => ({
  __esModule: true,
  default: ({idOrga}: {idOrga: number[]}) => <div data-testid="agenda" data-orgas={idOrga.join(',')} />,
}));


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('@/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/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;

/** 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 {getFederation, getAnnuaireEntree, getImg, getFederes} from '@/services/federationService';

const mockedGetFederes = getFederes as jest.Mock;

const mockedGetFederation = getFederation as jest.Mock;
const mockedGetAnnuaireEntree = getAnnuaireEntree as jest.Mock;
const mockedGetImg = getImg as jest.Mock;

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

const sonerion = {
  aenId: 77,
  aenLibelle: 'Sonerion',
  socleListeEntrees: [],
  filles: [],
  meres: [],
};

describe('Page fédération', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetFederation.mockResolvedValue({fedId: 3, fedAen: {aenId: 77}});
    mockedGetImg.mockResolvedValue(null);
  });

  it('shouldBuildTheDocumentTitleFromTheLabel', async () => {
    mockedGetAnnuaireEntree.mockResolvedValue(sonerion);

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

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

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

  it('shouldStillRenderTheFederationHeading', async () => {
    mockedGetAnnuaireEntree.mockResolvedValue(sonerion);

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

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

describe('Page fédération — bloc Bio', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetFederation.mockResolvedValue({fedId: 3, fedAen: {aenId: 77}});
    mockedGetImg.mockResolvedValue(null);
  });

  it('shouldDisplayTheBioWhenItIsFilled', async () => {
    mockedGetAnnuaireEntree.mockResolvedValue({...sonerion, aenBio: '<p>Fédération des <b>bagadoù</b>.</p>'});

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

    expect(screen.getByTestId('bio-section')).toHaveTextContent('Fédération des bagadoù.');
  });

  it('shouldNotDisplayTheBioWhenItIsEmpty', async () => {
    mockedGetAnnuaireEntree.mockResolvedValue(sonerion);

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

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

describe('Page fédération — logo et carte', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetAenLogo.mockResolvedValue(null);
    mockedGetFederation.mockResolvedValue({fedId: 3, fedAen: {aenId: 77}});
    mockedGetImg.mockResolvedValue(null);
  });

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

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

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

  it('shouldNotDisplayTheLogoWithoutOne', async () => {
    mockedGetAnnuaireEntree.mockResolvedValue(sonerion);

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

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

  it('shouldDisplayTheMapWhenTheVilleIsKnown', async () => {
    mockedGetAnnuaireEntree.mockResolvedValue(withVille(sonerion, {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 () => {
    mockedGetAnnuaireEntree.mockResolvedValue(withVille(sonerion, undefined));

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

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

describe('Page fédération — compteur de visites', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetAenLogo.mockResolvedValue(null);
    mockedGetFederation.mockResolvedValue({fedId: 3, fedAen: {aenId: 77}});
    mockedGetImg.mockResolvedValue(null);
    mockedGetAnnuaireEntree.mockResolvedValue(sonerion);
  });

  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', String(sonerion.aenId));
  });
});

describe('Page fédération — 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);
    mockedGetFederation.mockResolvedValue({fedId: 3, fedAen: {aenId: 77}});
    mockedGetImg.mockResolvedValue(null);
  });

  it('shouldDisplayThePartnerEpciOfTheVilleWithItsArticleLink', async () => {
    mockedGetAnnuaireEntree.mockResolvedValue({...sonerion, aenVil: {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 () => {
    mockedGetAnnuaireEntree.mockResolvedValue({...sonerion, aenVil: {vilId: 5, vilNom: 'Quimper', subAutres: [{...qbo, suaLogoPartenaire: 0}]}});

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

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

  it('shouldOfferTheUniversOfTheFederation', async () => {
    mockedGetAnnuaireEntree.mockResolvedValue({
      ...sonerion,
      socleListeEntrees: [{lieId: 50, lieNom: 'Fédérations', 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 fédération — vidéos', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetAenLogo.mockResolvedValue(null);
    mockedGetFederation.mockResolvedValue({fedId: 3, fedAen: {aenId: 77}});
    mockedGetImg.mockResolvedValue(null);
    mockedGetAnnuaireEntree.mockResolvedValue(sonerion);
    mockedGetVideos.mockResolvedValue([{aviId: 1, titre: 'Fest-noz', sousTitre: null, credit: null, youtubeId: 'abc', url: 'u', embedUrl: 'e', ordre: 0}]);
  });

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

    expect(mockedGetVideos).toHaveBeenCalledWith('77');
    expect(screen.getByTestId('videos')).toHaveAttribute('data-count', '1');
    expect(mockedGetSons).not.toHaveBeenCalled();
  });
});

describe('Page fédération — fédérés et agenda (spec L148, L149)', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetFederation.mockResolvedValue({fedId: 3, fedAen: {aenId: 77}});
    mockedGetImg.mockResolvedValue(null);
    mockedGetAenLogo.mockResolvedValue(null);
    mockedGetVideos.mockResolvedValue([]);
    mockedGetAnnuaireEntree.mockResolvedValue(sonerion);
  });

  it('shouldShowTheMembersGalleryLinkedToTheirOwnPages', async () => {
    mockedGetFederes.mockResolvedValue({fedId: 3, fedAenId: 77, fedLibelle: 'Sonerion', federes: [
      {aenId: 1, aenLibelle: 'Anna Le Goff', actif: true, photoUrl: 'https://pimcore.test/anna.jpg', type: 'artiste', cibleId: 1, listes: []},
      {aenId: 5, aenLibelle: 'Bagad Kemper', actif: true, photoUrl: null, type: 'groupe', cibleId: 9, listes: []},
      {aenId: 8, aenLibelle: 'Dañs Kemper', actif: true, photoUrl: null, type: 'annuaire', cibleId: 8, listes: []},
    ]});

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

    expect(mockedGetFederes).toHaveBeenCalledWith('3');
    const galerie = screen.getByTestId('federes');
    expect(galerie).toHaveAttribute('data-title', 'federes_title');
    expect(galerie).toHaveAttribute('data-count', '3');
    expect(galerie).toHaveAttribute('data-hrefs', '/fr/personne/1/anna-le-goff|/fr/groupes/9|/fr/annuaire_entree/8/dans-kemper');
    expect(galerie).toHaveAttribute('data-photos', 'https://pimcore.test/anna.jpg||');
    // Spec L149 : l'agenda couvre la fédération et ses fédérés.
    expect(screen.getByTestId('agenda')).toHaveAttribute('data-orgas', '77,1,5,8');
  });

  it('shouldHideTheGalleryWithoutMembersAndKeepTheFederationAgenda', async () => {
    mockedGetFederes.mockResolvedValue({fedId: 3, fedAenId: 77, fedLibelle: 'Sonerion', federes: []});

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

    expect(screen.queryByTestId('federes')).not.toBeInTheDocument();
    expect(screen.getByTestId('agenda')).toHaveAttribute('data-orgas', '77');
  });
});
