import type { EventApi, EventInput } from '@fullcalendar/core';
import dayGridPlugin from '@fullcalendar/daygrid';
import interactionPlugin from '@fullcalendar/interaction';
import FullCalendar from '@fullcalendar/react';
import tippy, { type Instance } from 'tippy.js';
import 'tippy.js/dist/tippy.css';
import 'tippy.js/themes/light.css';
import '../../../../../css/mini-calendar.css';

interface Props {
    events: EventInput[];
    /** Fenêtre couverte par les données ; la navigation s'y arrête. */
    validRange: { start: string; end: string };
    locale: string;
    /** Lignes de l'infobulle d'un événement. */
    tooltip: (event: EventApi) => string[];
    /** Un clic sur un jour ou un événement ouvre l'écran complet. */
    onOpen: () => void;
}

type TippyElement = HTMLElement & { _tippy?: Instance };

/**
 * Mois compact en lecture seule. Chargé à la demande (`React.lazy`) : la
 * bibliothèque de calendrier ne pèse sur la fiche qu'une fois l'accordéon ouvert.
 */
export default function MiniCalendar({ events, validRange, locale, tooltip, onOpen }: Props) {
    return (
        <div className="mini-calendar">
            <FullCalendar
                plugins={[dayGridPlugin, interactionPlugin]}
                initialView="dayGridMonth"
                locale={locale === 'en' ? 'en-gb' : 'fr'}
                firstDay={1}
                height="auto"
                fixedWeekCount={false}
                headerToolbar={{ left: 'prev', center: 'title', right: 'next' }}
                validRange={validRange}
                events={events}
                eventOrder="order"
                dateClick={onOpen}
                eventClick={(info) => {
                    info.jsEvent.preventDefault();
                    onOpen();
                }}
                eventDidMount={({ event, el }) => {
                    const lines = tooltip(event);
                    if (lines.length === 0) {
                        return;
                    }
                    // Contenu construit en nœuds texte : noms et commentaires ne sont jamais lus comme du HTML.
                    const content = document.createElement('div');
                    for (const line of lines) {
                        const row = document.createElement('div');
                        row.textContent = line;
                        content.appendChild(row);
                    }
                    tippy(el, { content, placement: 'top', theme: 'light', arrow: true, duration: [150, 100] });
                }}
                eventWillUnmount={({ el }) => {
                    (el as TippyElement)._tippy?.destroy();
                }}
            />
        </div>
    );
}
