// features/acces/Acces.jsx — page « Accès » de l'espace direction
// ---------------------------------------------------------------
// Les comptes de psychologues rattachés à l'établissement : accepter ou
// refuser une demande, retirer un accès accordé. Réservée au COMPTE
// ÉTABLISSEMENT (la direction) : une psychologue ne voit pas les autres
// psychologues, et n'en retire aucune.
//
// Trois invariants, tenus côté serveur et rappelés ici :
//  1. Le client ne fait que LIRE `rattachements`. Chaque décision passe par
//     la fonction `comptes`, seule à pouvoir recalculer le claim de la
//     psychologue — un statut écrit en base n'ouvrirait rien par lui-même.
//  2. Retirer un accès est immédiat : le jeton est recalculé dans la foulée.
//     D'où une confirmation, en ligne, qui nomme la personne.
//  3. Le nombre de demandes en attente alimente la pastille du rail : la
//     page remonte chaque changement à App via `onChange`.

const { useState: useStateAc, useEffect: useEffectAc } = React;

const ETATS_ACCES = {
  valide: { texte: 'Accès accordé', classe: 'ok' },
  en_attente: { texte: 'En attente', classe: 'attente' },
  refuse: { texte: 'Refusée', classe: 'refus' },
  revoque: { texte: 'Accès retiré', classe: 'refus' },
};

function initialesAcces(nom, email) {
  const mots = String(nom || '').split(' ').filter(Boolean).slice(0, 2);
  const i = mots.map((m) => m[0]).join('').toUpperCase();
  return i || String(email || '?').slice(0, 2).toUpperCase();
}

// « 2 septembre 2026 » depuis une date ISO ; vide si absente ou illisible.
function dateLongue(iso) {
  if (!iso) return '';
  const d = new Date(iso);
  if (isNaN(d)) return '';
  return d.toLocaleDateString('fr-FR', { day: 'numeric', month: 'long', year: 'numeric' });
}

function roleLisible(role) {
  return role === 'psychologue' ? 'Psychologue' : (role || 'Compte individuel');
}

function PageAcces({ etabId, onChange }) {
  const [liste, setListe] = useStateAc(null);        // null : chargement en cours
  const [erreur, setErreur] = useStateAc('');
  const [enCours, setEnCours] = useStateAc('');      // uid en cours de traitement
  const [aRetirer, setARetirer] = useStateAc('');    // uid dont on confirme le retrait

  const charger = async () => {
    try {
      const l = await window.LivanaAPI.rattachementsEtablissement(etabId);
      setListe(l);
      setErreur('');
      if (onChange) onChange(l);
    } catch (e) {
      setListe([]);
      setErreur("La liste des accès n'a pas pu être chargée.");
    }
  };
  useEffectAc(() => { charger(); }, [etabId]);

  // Chaque action recharge la liste depuis la base : c'est elle qui fait foi,
  // pas l'état local — et la pastille du rail suit par `onChange`.
  const agir = async (uid, fn) => {
    setEnCours(uid);
    setErreur('');
    try {
      await fn();
      await charger();
    } catch (e) {
      setErreur((e && e.message) || "L'action n'a pas pu être effectuée.");
    } finally {
      setEnCours('');
      setARetirer('');
    }
  };
  const repondre = (a, accepte) => agir(a.uid, () =>
    window.LivanaAPI.repondreRattachement({ etablissementId: etabId, uid: a.uid, accepte: accepte }));
  const retirer = (a) => agir(a.uid, () =>
    window.LivanaAPI.revoquerRattachement({ etablissementId: etabId, uid: a.uid }));

  if (liste === null) {
    return (
      <div className="page page-acces fade-up">
        <div className="acc-vide">Chargement des accès…</div>
      </div>);
  }

  // Les plus récents d'abord, dans chaque bloc.
  const trier = (l, champ) => l.slice().sort((x, y) => String(y[champ] || '').localeCompare(String(x[champ] || '')));
  const attente = trier(liste.filter((a) => a.statut === 'en_attente'), 'demande_le');
  const accordes = trier(liste.filter((a) => a.statut === 'valide'), 'repondu_le');
  const passes = trier(liste.filter((a) => a.statut === 'refuse' || a.statut === 'revoque'), 'repondu_le');

  const identite = (a, complement) => (
    <React.Fragment>
      <span className="acc-past">{initialesAcces(a.nom, a.email)}</span>
      <span className="acc-txt">
        <span className="acc-nom">{a.nom || a.email || 'Compte'}</span>
        <span className="acc-sous">{[a.email, roleLisible(a.role), complement].filter(Boolean).join(' · ')}</span>
      </span>
    </React.Fragment>
  );

  return (
    <div className="page page-acces fade-up">
      {erreur && <div className="acc-erreur">{erreur}</div>}

      {liste.length === 0 && (
        <div className="acc-vide">
          Aucune psychologue n'a encore demandé l'accès à votre établissement.
        </div>
      )}

      {attente.length > 0 && (
        <div className="acc-bloc">
          <div className="acc-bloc-h">
            <h3>{attente.length > 1 ? 'Demandes en attente' : 'Demande en attente'}</h3>
            <span className="eyebrow">à traiter</span>
          </div>
          {attente.map((a) => (
            <div key={a.uid} className="acc-ligne attente">
              {identite(a, a.demande_le ? 'demandé le ' + dateLongue(a.demande_le) : '')}
              <span className="acc-actions">
                <button className="btn btn-ghost btn-sm" type="button" disabled={enCours === a.uid}
                  onClick={() => repondre(a, false)}>Refuser</button>
                <button className="btn btn-accent btn-sm" type="button" disabled={enCours === a.uid}
                  onClick={() => repondre(a, true)}>{enCours === a.uid ? 'En cours…' : 'Accepter'}</button>
              </span>
            </div>
          ))}
        </div>
      )}

      {accordes.length > 0 && (
        <div className="acc-bloc">
          <div className="acc-bloc-h">
            <h3>Accès accordés</h3>
            <span className="eyebrow">{accordes.length} {accordes.length > 1 ? 'psychologues' : 'psychologue'}</span>
          </div>
          {accordes.map((a) => (
            <React.Fragment key={a.uid}>
              <div className="acc-ligne">
                {identite(a, a.repondu_le ? 'accès accordé le ' + dateLongue(a.repondu_le) : '')}
                <span className="acc-actions">
                  <button className="btn btn-sm btn-danger-ghost" type="button"
                    disabled={enCours === a.uid || aRetirer === a.uid}
                    onClick={() => setARetirer(a.uid)}>Retirer l'accès</button>
                </span>
              </div>
              {/* La confirmation nomme la personne et dit ce qui se passe :
                  l'effet est immédiat, et réversible seulement par une
                  nouvelle demande de sa part. */}
              {aRetirer === a.uid && (
                <div className="acc-confirm">
                  <span>
                    Retirer l'accès de <b>{a.nom || a.email}</b> ? Elle ne verra plus aucune donnée
                    de l'établissement, dès maintenant. Elle pourra redemander un accès plus tard.
                  </span>
                  <span className="acc-actions">
                    <button className="btn btn-ghost btn-sm" type="button" disabled={enCours === a.uid}
                      onClick={() => setARetirer('')}>Annuler</button>
                    <button className="btn btn-danger btn-sm" type="button" disabled={enCours === a.uid}
                      onClick={() => retirer(a)}>{enCours === a.uid ? 'Retrait…' : "Retirer l'accès"}</button>
                  </span>
                </div>
              )}
            </React.Fragment>
          ))}
        </div>
      )}

      {passes.length > 0 && (
        <div className="acc-bloc">
          <div className="acc-bloc-h">
            <h3>Décisions passées</h3>
            <span className="eyebrow">historique</span>
          </div>
          {passes.map((a) => {
            const e = ETATS_ACCES[a.statut] || { texte: a.statut, classe: 'refus' };
            const quand = a.statut === 'revoque'
              ? (a.revoque_le ? 'accès retiré le ' + dateLongue(a.revoque_le) : '')
              : (a.repondu_le ? 'demande refusée le ' + dateLongue(a.repondu_le) : '');
            return (
              <div key={a.uid} className="acc-ligne passe">
                {identite(a, quand)}
                <span className={`pe-etat ${e.classe}`}>{e.texte}</span>
              </div>
            );
          })}
        </div>
      )}

      <div className="acc-note">
        Une psychologue demande l'accès depuis son propre compte, en saisissant l'adresse
        e-mail de l'établissement. Vous recevez aussi cette demande par courriel : les deux
        chemins font la même chose. Un accès accordé donne accès à tous les résidents de
        l'établissement, transcriptions comprises.
      </div>
    </div>
  );
}

window.PageAcces = PageAcces;
