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: {AnnuaireDetailsPage: {share_on: 'Partager'}}})
);

jest.mock('@/services/annuaireService', () => ({
  getAnnuaire: jest.fn(),
  getImg: jest.fn(),
  getTypeAen: jest.fn(),
}));

jest.mock('@/components/Groupes/ContactSection/ContactSection', () => ({__esModule: true, default: () => <div />}));
jest.mock('@/components/Annuaire/OrganisateurEventSection/OrganisateurEventSection', () => ({__esModule: true, default: () => <div />}));
jest.mock('@/components/Annuaire/AnnuaireMemberEvents', () => ({
  __esModule: true,
  default: ({aenId, aenLibelle}: {aenId: number; aenLibelle?: string}) => <div data-testid="agenda" data-aen={aenId} data-libelle={aenLibelle} />,
}));
jest.mock('@/services/entreeRelationsService', () => ({
  getEntreeRelations: jest.fn().mockResolvedValue({meres: [], filles: [], federations: []}),
}));
jest.mock('@/services/mediaService', () => ({
  getLogoUrl: jest.fn().mockResolvedValue(null),
}));
jest.mock('@/components/shared/FederationsLogos/FederationsLogos', () => ({
  __esModule: true,
  default: ({federations}: {federations: {fedId: number; fedLibelle: string | null; logoUrl: string | null}[]}) => (
    <div data-testid="federations" data-count={federations.length} data-libelles={federations.map((f) => f.fedLibelle).join('|')} data-logos={federations.map((f) => f.logoUrl ?? '').join('|')} />
  ),
}));
jest.mock('@/components/Annuaire/PastEventsSection/PastEventsSection', () => ({__esModule: true, default: () => <div />}));
jest.mock('@/components/Annuaire/PhotosSection/PhotosSection', () => ({__esModule: true, default: () => <div />}));
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/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/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 {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 {getAnnuaire, getImg, getTypeAen} from '@/services/annuaireService';
import {getEntreeRelations} from '@/services/entreeRelationsService';
import {getLogoUrl} from '@/services/mediaService';

const mockedGetEntreeRelations = getEntreeRelations as jest.Mock;
const mockedGetLogoUrl = getLogoUrl as jest.Mock;

const mockedGetAnnuaire = getAnnuaire as jest.Mock;
const mockedGetImg = getImg as jest.Mock;
const mockedGetTypeAen = getTypeAen as jest.Mock;

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

const sonArLeurenn = {
  aenId: 13810,
  aenLibelle: 'Association Son Ar Leurenn',
  socleListeEntrees: [],
};

describe("Page entrée d'annuaire", () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetTypeAen.mockResolvedValue({type: 'aen'});
    mockedGetImg.mockResolvedValue('');
  });

  it('shouldBuildTheDocumentTitleFromTheLabel', async () => {
    mockedGetAnnuaire.mockResolvedValue(sonArLeurenn);

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

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

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

  it('shouldStillRenderTheEntryHeading', async () => {
    mockedGetAnnuaire.mockResolvedValue(sonArLeurenn);

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

    expect(screen.getByRole('heading', {level: 1})).toHaveTextContent('Association Son Ar Leurenn');
  });
});

describe("Page entrée d'annuaire — bloc Bio", () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetTypeAen.mockResolvedValue({type: 'aen'});
    mockedGetImg.mockResolvedValue('');
  });

  it('shouldDisplayTheBioWhenItIsFilled', async () => {
    mockedGetAnnuaire.mockResolvedValue({...sonArLeurenn, aenBio: '<p>Association créée en <b>1998</b>.</p>'});

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

    expect(screen.getByTestId('bio-section')).toHaveTextContent('Association créée en 1998.');
  });

  it('shouldNotDisplayTheBioWhenItIsEmpty', async () => {
    mockedGetAnnuaire.mockResolvedValue({...sonArLeurenn, aenBio: ''});

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

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

describe("Page entrée d'annuaire — logo et carte", () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetAenLogo.mockResolvedValue(null);
    mockedGetTypeAen.mockResolvedValue({type: 'aen'});
    mockedGetImg.mockResolvedValue('');
  });

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

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

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

  it('shouldNotDisplayTheLogoWithoutOne', async () => {
    mockedGetAnnuaire.mockResolvedValue(sonArLeurenn);

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

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

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

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

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

describe("Page entrée d'annuaire — favoris et compteur de visites", () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetAenLogo.mockResolvedValue(null);
    mockedGetTypeAen.mockResolvedValue({type: 'aen'});
    mockedGetImg.mockResolvedValue('');
    mockedGetAnnuaire.mockResolvedValue(sonArLeurenn);
  });

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

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

  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(sonArLeurenn.aenId));
  });
});

describe("Page entrée d'annuaire — 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);
    mockedGetTypeAen.mockResolvedValue({type: 'aen'});
    mockedGetImg.mockResolvedValue('');
  });

  it('shouldPassTheArticleLinkToThePartnerEpciBlock', async () => {
    mockedGetAnnuaire.mockResolvedValue({...sonArLeurenn, aenVil: {vilId: 5, vilNom: 'Quimper', subAutres: [qbo]}});

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

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

  it('shouldOfferTheUniversOfTheEntry', async () => {
    mockedGetAnnuaire.mockResolvedValue({
      ...sonArLeurenn,
      socleListeEntrees: [{lieId: 40, lieNom: 'Luthiers', 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');
    expect(screen.queryByText('Diplômes et certifications')).not.toBeInTheDocument();
  });
});

describe("Page entrée d'annuaire — articles du Mag", () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetAenLogo.mockResolvedValue(null);
    mockedGetTypeAen.mockResolvedValue({type: 'aen'});
    mockedGetImg.mockResolvedValue('');
    mockedGetAnnuaire.mockResolvedValue(sonArLeurenn);
    mockedGetArticlesLies.mockResolvedValue([{id: 1, title: 'Les sonneurs de couple', slug: 'sonneurs-de-couple'}]);
  });

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

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

describe("Page entrée d'annuaire — spécialisation, fédérations, agenda (spec L16, L87, L91)", () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockedGetTypeAen.mockResolvedValue({type: 'aen'});
    mockedGetImg.mockResolvedValue('');
    mockedGetAenLogo.mockResolvedValue(null);
    mockedGetArticlesLies.mockResolvedValue([]);
    mockedGetEntreeRelations.mockResolvedValue({meres: [], filles: [], federations: []});
    mockedGetLogoUrl.mockResolvedValue(null);
  });

  it('shouldDisplayTheSpecialisationWithItsCategory', async () => {
    mockedGetAnnuaire.mockResolvedValue({...sonArLeurenn, aenAqs: {aqsId: 4, aqsNom: 'Luthier', aqsAqc: {aqcId: 1, aqcNom: 'Artisanat'}}});

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

    const bloc = screen.getByTestId('specialisation');
    expect(bloc).toHaveTextContent('Artisanat');
    expect(bloc).toHaveTextContent('Luthier');
  });

  it('shouldNotDisplayTheSpecialisationBlockWithoutOne', async () => {
    mockedGetAnnuaire.mockResolvedValue(sonArLeurenn);

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

    expect(screen.queryByTestId('specialisation')).not.toBeInTheDocument();
  });

  it('shouldShowTheFederationsOfTheEntryWithTheirLogos', async () => {
    mockedGetAnnuaire.mockResolvedValue(sonArLeurenn);
    mockedGetEntreeRelations.mockResolvedValue({meres: [], filles: [], federations: [
      {fedId: 3, fedAenId: 77, fedLibelle: 'Sonerion'},
      {fedId: 5, fedAenId: null, fedLibelle: 'Kendalc\'h'},
    ]});
    mockedGetLogoUrl.mockImplementation(async (_type: string, id: number) => (id === 77 ? 'https://pimcore.test/sonerion.png' : null));

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

    expect(mockedGetEntreeRelations).toHaveBeenCalledWith('13810');
    const federations = screen.getByTestId('federations');
    expect(federations).toHaveAttribute('data-count', '2');
    expect(federations).toHaveAttribute('data-libelles', 'Sonerion|Kendalc\'h');
    expect(federations).toHaveAttribute('data-logos', 'https://pimcore.test/sonerion.png|');
  });

  it('shouldNameTheEntryInTheAgendaBlock', async () => {
    mockedGetAnnuaire.mockResolvedValue(sonArLeurenn);

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

    const agenda = screen.getByTestId('agenda');
    expect(agenda).toHaveAttribute('data-aen', '13810');
    expect(agenda).toHaveAttribute('data-libelle', 'Association Son Ar Leurenn');
  });
});
