// ============================================================================
//  auth.jsx — Écrans d'authentification (login / register / unlock).
//  Toute la cryptographie est faite ici localement avant tout dialogue serveur.
// ============================================================================

(function (global) {
  'use strict';

  const { useState, useRef, useEffect } = React;

  // ─── Helpers réseau + crypto ──────────────────────────────────────────────

  async function loginFlow(email, masterPassword) {
    const { kdf_salt, kdf_params } = await CPApi.salt(email);
    const { encKey, authKeyHex } = await CPCrypto.deriveKeys(masterPassword, kdf_salt, kdf_params);
    const r = await CPApi.login({ email, auth_key: authKeyHex });
    let vault;
    try {
      vault = await CPCrypto.decryptJSON(encKey, r.vault_blob, r.vault_iv);
    } catch (e) {
      // Pas censé arriver après un /login OK, sauf coffre corrompu côté serveur.
      throw new Error('Le serveur a accepté l’authentification mais le coffre est illisible.');
    }
    return {
      encKey,
      email: r.email,
      kdfSalt: r.kdf_salt,
      kdfParams: r.kdf_params,
      vault,
      vaultVersion: r.vault_version,
    };
  }

  async function registerFlow(email, masterPassword) {
    const saltBytes = CPCrypto.randomBytes(16);
    const saltHex = CPCrypto.bytesToHex(saltBytes);
    const kdfParams = CPCrypto.DEFAULT_KDF_PARAMS;

    const { encKey, authKeyHex } = await CPCrypto.deriveKeys(masterPassword, saltHex, kdfParams);
    const vault = CPCrypto.makeEmptyVault();
    const { blob, iv } = await CPCrypto.encryptJSON(encKey, vault);

    await CPApi.register({
      email,
      kdf_salt: saltHex,
      kdf_params: kdfParams,
      auth_key: authKeyHex,
      vault_blob: blob,
      vault_iv: iv,
    });

    return { encKey, email, kdfSalt: saltHex, kdfParams, vault, vaultVersion: 1 };
  }

  // Déverrouillage avec session déjà valide : pas de /login, on dérive et on
  // tente de déchiffrer le coffre récupéré via /vault.
  async function unlockFlow(masterPassword, sessionInfo) {
    const { encKey } = await CPCrypto.deriveKeys(
      masterPassword, sessionInfo.kdfSalt, sessionInfo.kdfParams
    );
    const v = await CPApi.vaultGet();
    let vault;
    try {
      vault = await CPCrypto.decryptJSON(encKey, v.vault_blob, v.vault_iv);
    } catch {
      throw new Error('Mot de passe maître incorrect.');
    }
    return {
      encKey,
      email: sessionInfo.email,
      kdfSalt: sessionInfo.kdfSalt,
      kdfParams: sessionInfo.kdfParams,
      vault,
      vaultVersion: v.vault_version,
    };
  }

  // ─── Estimateur de force du mot de passe (simple, à l'inscription) ───────

  function estimateStrength(pwd) {
    if (!pwd) return { score: 0, label: '—', color: '#666' };
    let score = 0;
    if (pwd.length >= 8)  score += 1;
    if (pwd.length >= 12) score += 1;
    if (pwd.length >= 16) score += 1;
    if (/[a-z]/.test(pwd) && /[A-Z]/.test(pwd)) score += 1;
    if (/\d/.test(pwd))   score += 1;
    if (/[^A-Za-z0-9]/.test(pwd)) score += 1;
    const labels = ['Très faible', 'Faible', 'Moyen', 'Bon', 'Très bon', 'Excellent', 'Excellent'];
    const colors = ['#EF4444', '#EF4444', '#F59E0B', '#F59E0B', '#10B981', '#10B981', '#10B981'];
    return { score, label: labels[score], color: colors[score] };
  }

  // ─── Composant principal ──────────────────────────────────────────────────

  const AuthScreen = ({ initialMode = 'login', sessionInfo = null, onAuthenticated, onSwitchAccount }) => {
    const [mode, setMode] = useState(initialMode); // 'login' | 'register' | 'unlock'
    const [email, setEmail] = useState(sessionInfo?.email || '');
    const [pwd, setPwd] = useState('');
    const [pwd2, setPwd2] = useState('');
    const [busy, setBusy] = useState(false);
    const [busyLabel, setBusyLabel] = useState('');
    const [error, setError] = useState('');
    const [showPwd, setShowPwd] = useState(false);
    const pwdRef = useRef(null);

    useEffect(() => { pwdRef.current?.focus(); }, [mode]);

    const strength = estimateStrength(pwd);

    async function submit(e) {
      e.preventDefault();
      if (busy) return;
      setError('');

      try {
        if (mode === 'register') {
          if (pwd.length < 12) return setError('Choisissez un mot de passe maître d’au moins 12 caractères.');
          if (pwd !== pwd2)   return setError('Les deux mots de passe ne correspondent pas.');
          if (strength.score < 3) return setError('Mot de passe maître trop faible. Mélangez majuscules, chiffres et symboles.');
        }
        if (!email && mode !== 'unlock') return setError('Email requis.');
        if (!pwd) return setError('Mot de passe requis.');

        setBusy(true);
        setBusyLabel('Dérivation Argon2id (peut prendre 1–2 secondes)…');

        let result;
        if (mode === 'register')      result = await registerFlow(email.trim(), pwd);
        else if (mode === 'unlock')   result = await unlockFlow(pwd, sessionInfo);
        else                          result = await loginFlow(email.trim(), pwd);

        setBusyLabel('');
        // On ne garde rien en clair dans le state une fois la clé dérivée.
        setPwd(''); setPwd2('');
        onAuthenticated(result);
      } catch (err) {
        setError(err.message || 'Erreur inconnue');
      } finally {
        setBusy(false);
        setBusyLabel('');
      }
    }

    const titles = {
      login:    { h: 'Bienvenue', s: 'Déverrouillez votre coffre.' },
      register: { h: 'Créer un coffre', s: 'Choisissez un mot de passe maître. Il ne quittera jamais ce navigateur.' },
      unlock:   { h: 'Coffre verrouillé', s: 'Saisissez votre mot de passe maître pour ré-ouvrir le coffre.' },
    };
    const t = titles[mode];

    return (
      <div className="cp-auth">
        <div className="cp-auth-bg" />
        <div className="cp-auth-card">
          <div className="cp-auth-logo">
            <svg width="32" height="32" viewBox="0 0 24 24" fill="none">
              <defs>
                <linearGradient id="auth-lg" x1="0" y1="0" x2="1" y2="1">
                  <stop offset="0" stopColor="#6366F1"/>
                  <stop offset="1" stopColor="#EC4899"/>
                </linearGradient>
              </defs>
              <circle cx="9" cy="14" r="5" stroke="url(#auth-lg)" strokeWidth="2"/>
              <path d="M12.5 11.5 21 3" stroke="url(#auth-lg)" strokeWidth="2" strokeLinecap="round"/>
              <path d="m18 6 2.5 2.5M15 9l2.5 2.5" stroke="url(#auth-lg)" strokeWidth="2" strokeLinecap="round"/>
            </svg>
          </div>
          <div className="cp-auth-name">CléPass</div>
          <h1 className="cp-auth-h">{t.h}</h1>
          <p className="cp-auth-sub">{t.s}</p>

          <form className="cp-auth-form" onSubmit={submit} autoComplete="on">
            {mode !== 'unlock' && (
              <label className="cp-auth-field">
                <span>Email</span>
                <input
                  type="email"
                  inputMode="email"
                  autoComplete="username"
                  required
                  value={email}
                  disabled={busy}
                  onChange={(e) => setEmail(e.target.value)}
                />
              </label>
            )}

            {mode === 'unlock' && (
              <div className="cp-auth-email-disp">
                <Icon name="mail" size={13} />
                <span>{sessionInfo?.email || ''}</span>
                {onSwitchAccount && (
                  <button type="button" className="cp-auth-link" onClick={onSwitchAccount}>
                    Changer
                  </button>
                )}
              </div>
            )}

            <label className="cp-auth-field">
              <span>Mot de passe maître</span>
              <div className="cp-auth-pwd">
                <input
                  ref={pwdRef}
                  type={showPwd ? 'text' : 'password'}
                  autoComplete={mode === 'register' ? 'new-password' : 'current-password'}
                  required
                  value={pwd}
                  disabled={busy}
                  onChange={(e) => setPwd(e.target.value)}
                />
                <button
                  type="button"
                  className="cp-field-eye"
                  onClick={() => setShowPwd(!showPwd)}
                  tabIndex={-1}
                  aria-label={showPwd ? 'Masquer' : 'Afficher'}
                >
                  <Icon name={showPwd ? 'eye-off' : 'eye'} size={14} />
                </button>
              </div>
            </label>

            {mode === 'register' && (
              <>
                <label className="cp-auth-field">
                  <span>Confirmation</span>
                  <input
                    type={showPwd ? 'text' : 'password'}
                    autoComplete="new-password"
                    required
                    value={pwd2}
                    disabled={busy}
                    onChange={(e) => setPwd2(e.target.value)}
                  />
                </label>
                <div className="cp-auth-strength">
                  <div className="cp-auth-strength-bar">
                    <div
                      className="cp-auth-strength-fill"
                      style={{
                        width: `${(strength.score / 6) * 100}%`,
                        background: strength.color,
                      }}
                    />
                  </div>
                  <span style={{ color: strength.color }}>{strength.label}</span>
                </div>
                <div className="cp-auth-warn">
                  <Icon name="alert" size={12} />
                  <span>
                    Si vous oubliez ce mot de passe, votre coffre est <b>définitivement perdu</b>.
                    Personne (pas même nous) ne peut le récupérer — c'est le principe du zero-knowledge.
                  </span>
                </div>
              </>
            )}

            {error && (
              <div className="cp-auth-error">
                <Icon name="alert" size={12} />
                <span>{error}</span>
              </div>
            )}

            <button type="submit" className="cp-auth-submit" disabled={busy}>
              {busy ? (
                <>
                  <span className="cp-spin" />
                  <span>{busyLabel || 'Patientez…'}</span>
                </>
              ) : (
                <span>
                  {mode === 'register' && 'Créer mon coffre'}
                  {mode === 'login'    && 'Déverrouiller'}
                  {mode === 'unlock'   && 'Déverrouiller'}
                </span>
              )}
            </button>
          </form>

          {mode !== 'unlock' && (
            <div className="cp-auth-switch">
              {mode === 'login' ? (
                <>Pas encore de coffre ?{' '}
                  <button type="button" className="cp-auth-link" onClick={() => { setError(''); setMode('register'); }}>
                    En créer un
                  </button>
                </>
              ) : (
                <>Déjà un coffre ?{' '}
                  <button type="button" className="cp-auth-link" onClick={() => { setError(''); setMode('login'); }}>
                    Se connecter
                  </button>
                </>
              )}
            </div>
          )}

          <div className="cp-auth-foot">
            <Icon name="shield-check" size={11} color="#10B981" />
            <span>Argon2id + AES-256-GCM · zero-knowledge</span>
          </div>
        </div>
      </div>
    );
  };

  global.AuthScreen = AuthScreen;
  global.CPAuthFlows = { loginFlow, registerFlow, unlockFlow, estimateStrength };
})(window);
