/**
 * Types du système de visite guidée (TourGuide.js).
 *
 * Principe : le CONTENU d'une étape ne vit jamais dans le JSX. Le JSX ne porte
 * qu'une ancre — `data-tour="mon-ancre"` — et le texte vit dans
 * `lang/{fr,en}/tours.php`. C'est ce qui rend la visite bilingue sans dupliquer
 * un seul mot dans les composants.
 *
 * Voir `.claude/TOURS.md` pour la marche à suivre quand on ajoute une fonctionnalité.
 */

/** Une étape de visite, telle qu'on la déclare dans `lib/tour/tours/*.tour.ts`. */
export interface AppTourStep {
    /**
     * Valeur de l'attribut `data-tour` posé sur l'élément à surligner.
     * L'élément DOIT exister dans le DOM au moment où la visite démarre — sauf
     * si l'étape est marquée `optional`.
     *
     * ⚠️ NE JAMAIS viser un élément PLUS HAUT QUE L'ÉCRAN. Ce n'est pas qu'une
     * affaire de surlignage : la bibliothèque amène la cible à l'écran avec
     * `scrollIntoView({ block: 'end' })`, qui aligne le BAS de la cible sur le
     * bas de la fenêtre. Sur une colonne étirée par un parent flex — un rail
     * d'étapes, un panneau pleine hauteur — cela défile jusqu'au pied de la
     * page : la visite s'ouvre là-bas, loin de ce qu'elle décrit, et paraît
     * cassée. Viser le plus petit élément porteur de sens ; ce qui l'entoure
     * reste visible à côté et n'a pas besoin d'être surligné.
     */
    anchor: string;

    /**
     * Racine des clés de traduction. Deux clés sont lues dans le namespace
     * `tours` : `<tourId>.<key>.title` et `<tourId>.<key>.content`.
     */
    key: string;

    /** Ordre d'apparition. Croissant, pas nécessairement contigu. */
    order: number;

    /** Permission Spatie requise pour voir l'étape. Absente = visible par tous. */
    permission?: string;

    /** L'étape ne s'affiche que pour un administrateur (siège). */
    adminOnly?: boolean;

    /**
     * L'ancre peut légitimement être absente (élément conditionnel, onglet non
     * ouvert, liste vide). L'étape est alors SAUTÉE au lieu de casser la visite.
     *
     * Une étape non optionnelle dont l'ancre manque est également sautée — mais
     * elle est signalée en console, parce que c'est presque toujours un bug
     * (ancre renommée dans le JSX et pas dans le tour).
     */
    optional?: boolean;

    /** L'élément est en `position: fixed` (en-tête, barre latérale). */
    fixed?: boolean;

    /**
     * L'ancre est un déclencheur de menu / panneau repliable : on l'OUVRE en
     * arrivant sur l'étape, et on le referme en la quittant. Sans quoi l'étape
     * décrit un contenu que l'utilisateur ne voit pas.
     *
     * L'ancre doit alors être le déclencheur lui-même (un `DropdownMenuTrigger`,
     * un `PopoverTrigger`…), parce que l'ouverture se fait en le cliquant et que
     * l'état se lit sur son attribut `data-state` — la convention Radix.
     *
     * Pendant la visite, le contenu ouvert est VISIBLE mais non cliquable : la
     * feuille de style de TourGuide neutralise tout ce qui est hors du dialogue.
     * C'est voulu — une étape ne doit pas pouvoir emmener l'utilisateur ailleurs.
     */
    openOnEnter?: boolean;
}

/** Une visite guidée, rattachée à une ou plusieurs pages Inertia. */
export interface AppTour {
    /**
     * Identifiant du groupe TourGuide. Sert AUSSI de clé de complétion dans le
     * localStorage du navigateur : le changer refait passer la visite à tout le
     * monde. À traiter comme une clé stable.
     */
    id: string;

    /**
     * Noms de composants Inertia sur lesquels cette visite s'applique,
     * exactement tels que passés à `Inertia::render()`.
     * Exemple : `['Dashboard/index']`.
     */
    components: string[];

    /**
     * Démarrer automatiquement la visite à la première venue de l'utilisateur
     * sur la page (une seule fois, mémorisé dans le localStorage).
     * Par défaut `false` : une visite qui s'impose est une visite qu'on ferme.
     */
    autoStart?: boolean;

    steps: AppTourStep[];
}

/** Contexte d'évaluation des étapes — ce qui décide qu'une étape est visible. */
export interface TourViewerContext {
    permissions: string[];
    isAdmin: boolean;
    /** Vrai si l'ancre est présente dans le DOM. Injecté pour garder le registre pur. */
    hasAnchor: (anchor: string) => boolean;
}
