/**
 * Bascule maître/détail de la messagerie.
 *
 * Sur écran étroit un seul panneau tient : la liste des discussions OU la
 * conversation. La visibilité elle-même est faite en CSS (`lg:`) pour être juste
 * dès le premier rendu ; ce module ne porte que l'état logique — quel panneau
 * est au premier plan — pour rester testable (vitest tourne en environnement
 * `node` et ne monte pas de composants).
 */

export type MessageriePane = 'list' | 'thread';

/**
 * Largeur à partir de laquelle les deux panneaux cohabitent — le `lg:` de Tailwind.
 *
 * Et non `md:` (768 px) : la barre latérale de l'application en occupe 288, il ne
 * resterait que ~170 px pour la conversation, soit un mot par ligne (constaté à
 * 768 px avant correction). À 1024 px la conversation garde ~400 px utiles.
 */
export const TWO_PANE_MIN_WIDTH = 1024;

/**
 * Panneau au premier plan au chargement.
 *
 * Un lien de notification porte `?discussion=N` ([InboundMessageAlertService])
 * et doit ouvrir la conversation directement ; sinon on atterrit sur la liste.
 */
export function initialPane(hasDeepLink: boolean): MessageriePane {
    return hasDeepLink ? 'thread' : 'list';
}

/**
 * La conversation occupe-t-elle l'écran ?
 *
 * `thread` sans discussion active arrive quand la cible d'un lien profond n'est
 * pas encore chargée : on garde la liste au premier plan plutôt qu'un écran vide.
 */
export function isThreadFocused(pane: MessageriePane, hasActiveDiscussion: boolean): boolean {
    return pane === 'thread' && hasActiveDiscussion;
}

/**
 * Y a-t-il la place pour les deux panneaux ?
 *
 * Sert à décider, une seule fois au montage, si l'on présélectionne la première
 * discussion. Sur mobile on ne le fait pas : cela cacherait la liste et
 * marquerait comme lu un fil que personne n'a ouvert.
 *
 * Lu de façon synchrone plutôt que via `useIsMobile()`, dont la valeur n'arrive
 * qu'après le premier effet — trop tard, les effets enfants (dont le
 * marquage « lu ») se seraient déjà exécutés.
 */
export function prefersTwoPanes(): boolean {
    if (typeof window === 'undefined') return true; // rendu serveur : aligné sur les classes `lg:`
    return window.matchMedia(`(min-width: ${TWO_PANE_MIN_WIDTH}px)`).matches;
}

export interface PaneClasses {
    list: string;
    thread: string;
}

/**
 * Classes de visibilité des deux panneaux.
 *
 * Elles vivent ici plutôt que dans le JSX pour être couvertes par un test : le
 * défaut d'origine — les deux panneaux affichés côte à côte, la conversation
 * écrasée à quelques pixels — était entièrement contenu dans ces chaînes.
 */
export function paneVisibilityClasses(threadFocused: boolean): PaneClasses {
    return threadFocused ? { list: 'hidden lg:flex', thread: 'flex' } : { list: 'flex', thread: 'hidden lg:flex' };
}

/**
 * Un panneau est-il visible à cette largeur ?
 *
 * Mini-évaluateur qui ne comprend que les deux formes produites ci-dessus
 * (`flex` et `hidden lg:flex`) — juste assez pour verrouiller l'invariant
 * « exactement un panneau sous 1024 px, les deux au-delà ».
 */
export function isPaneVisibleAt(classes: string, viewportWidth: number): boolean {
    const tokens = classes.split(' ');
    if (viewportWidth >= TWO_PANE_MIN_WIDTH && tokens.includes('lg:flex')) return true;
    return !tokens.includes('hidden');
}
