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

const mockedGet = jest.fn();
jest.mock('@/http', () => ({
  __esModule: true,
  default: {get: (...args: unknown[]) => mockedGet(...args)},
  HttpError: class HttpError extends Error {
    status: number;
    constructor(status: number) {
      super(`HTTP ${status}`);
      this.status = status;
    }
  },
}));
jest.mock('@/i18n', () =>
  jest.fn().mockResolvedValue({messages: {PropositionEvenementPage: {modification_title: 'Modifier un événement', modification_lead: 'Texte par défaut'}}})
);
jest.mock('@/services/mediaPageService', () => ({getMediaPage: jest.fn()}));
jest.mock('next/navigation', () => ({
  notFound: jest.fn(() => {
    throw new Error('NOT_FOUND');
  }),
}));
jest.mock('next/link', () => ({
  __esModule: true,
  default: ({children, href}: {children: React.ReactNode; href: string}) => <a href={href}>{children}</a>,
}));
jest.mock('@/components/Articles/ArticleBody', () => ({
  __esModule: true,
  default: ({html}: {html: string}) => <div data-testid="texte-kasour">{html}</div>,
}));
jest.mock('@/components/PropositionEvenement/PropositionEvenementForm', () => ({
  __esModule: true,
  default: (props: {mode: string; evenementId: number; evenementHref: string; typeEvents: unknown[]; initialValues: {lieu: string}}) => (
    <div data-testid="form" data-mode={props.mode} data-evenement={props.evenementId} data-href={props.evenementHref} data-types={props.typeEvents.length} data-lieu={props.initialValues.lieu} />
  ),
}));

import Page, {generateMetadata} from '../page';
import {getMediaPage} from '@/services/mediaPageService';
import {HttpError} from '@/http';

const props = {params: Promise.resolve({locale: 'fr', eveId: '72'})};
const festNoz = {
  eveId: 72,
  eveDate: '2026-09-20',
  eveHeure: '21:00',
  eveValide: 1,
  eveLibelle: 'Grand fest-noz',
  evePrixLibelle: '7 €',
  evePla: {plaNom: 'Salle de la Cité', plaAdresse: '10 rue Saint-Louis'},
  eveTev: {tevId: 1, tevLibelle: 'Fest-noz'},
  eveVil: {vilNom: 'Rennes'},
  aenParticipants: [{aenId: 5, aenLibelle: 'Bagad Kemper'}],
};
const types = [{tevId: 1, tevLibelle: 'Fest-noz', tevDpr: {dprNom: 'Musique'}}, {tevId: 4, tevLibelle: 'Stage', tevDpr: {dprNom: 'Formation'}}];

function servir(event: unknown | Error) {
  mockedGet.mockImplementation((url: string) => {
    if (url.startsWith('/evenement_type_evenements')) return Promise.resolve({data: {'hydra:member': types}});
    return event instanceof Error ? Promise.reject(event) : Promise.resolve({data: event});
  });
}

describe('Page de modification d\'un événement', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    servir(festNoz);
    (getMediaPage as jest.Mock).mockResolvedValue(null);
  });

  it('shouldPrefillTheProposalFormForTheEvent', async () => {
    render(await Page(props));

    const form = screen.getByTestId('form');
    expect(form).toHaveAttribute('data-mode', 'modification');
    expect(form).toHaveAttribute('data-evenement', '72');
    expect(form).toHaveAttribute('data-href', '/fr/evenement/72/fest-noz-rennes');
    expect(form).toHaveAttribute('data-types', '2');
    expect(form).toHaveAttribute('data-lieu', 'Salle de la Cité, Rennes');
    expect(screen.getByRole('heading', {level: 1})).toHaveTextContent('Modifier un événement');
    expect(screen.getByRole('link', {name: /Fest-noz à Rennes/})).toHaveAttribute('href', '/fr/evenement/72/fest-noz-rennes');
  });

  it('shouldShowTheTextAdministeredInKasour', async () => {
    (getMediaPage as jest.Mock).mockResolvedValue({slug: 'modification-evenement', langue: 'fr', titre: 'Modifier', contenu: '<p>Texte Kasour</p>'});

    render(await Page(props));

    expect(getMediaPage).toHaveBeenCalledWith('modification-evenement', 'fr');
    expect(screen.getByTestId('texte-kasour')).toHaveTextContent('<p>Texte Kasour</p>');
    expect(screen.queryByText('Texte par défaut')).not.toBeInTheDocument();
  });

  it('shouldFallBackToTheDefaultTextWithoutKasourPage', async () => {
    render(await Page(props));

    expect(screen.getByText('Texte par défaut')).toBeInTheDocument();
  });

  it('shouldBeNotFoundWhenTheEventDoesNotExist', async () => {
    servir(new HttpError(404, null));

    await expect(Page(props)).rejects.toThrow('NOT_FOUND');
  });

  it('shouldBeNotFoundWhenTheEventIsNotPublished', async () => {
    servir({...festNoz, eveValide: 0});

    await expect(Page(props)).rejects.toThrow('NOT_FOUND');
  });

  it('shouldTitleTheDocumentWithTheEvent', async () => {
    const metadata = await generateMetadata(props);

    expect(metadata.title).toContain('Modifier un événement');
    expect(metadata.title).toContain('Fest-noz à Rennes');
  });
});
