/* Blackstock — Modal de autenticación (registro + login) conectado a
 * api.blackstock.es. Reusa exactamente los mismos endpoints que
 * clientes.blackstock.es (el flujo y los códigos de error son idénticos).
 *
 * Vistas:
 *   register: nombre + username + email + tel? + password + confirm + términos
 *   verify:   código de 6 dígitos + reenvío con cooldown 60s
 *   login:    email + password
 *   success:  redirección
 *
 * Endpoints:
 *   GET  /api/client/csrf
 *   POST /api/client/register
 *   POST /api/client/verify-email
 *   POST /api/client/resend-verification
 *   POST /api/client/login
 *   GET  /api/client/me
 *
 * window.bsOpenAuth(planHint?, mode?='register')
 * window.bsCloseAuth()
 */

(function () {
  const API = 'https://api.blackstock.es/api';
  const RESEND_COOLDOWN_SEC = 60;
  const VERIFY_TTL_MIN = 10;

  let csrfToken = '';

  async function fetchCsrf() {
    if (csrfToken) return csrfToken;
    try {
      const r = await fetch(`${API}/client/csrf`, { credentials: 'include' });
      const j = await r.json().catch(() => ({}));
      if (j?.csrfToken) csrfToken = j.csrfToken;
    } catch (_) {}
    return csrfToken;
  }

  async function apiPost(path, body, retry = true) {
    if (!csrfToken) await fetchCsrf();
    const res = await fetch(`${API}${path}`, {
      method: 'POST',
      credentials: 'include',
      headers: {
        'Content-Type': 'application/json',
        'x-csrf-token': csrfToken,
      },
      body: JSON.stringify(body || {}),
    });
    let data = null;
    try { data = await res.json(); } catch (_) {}
    if (data?.csrfToken) csrfToken = data.csrfToken;
    if (!res.ok) {
      if (retry && data?.error === 'csrf_invalid') {
        csrfToken = '';
        await fetchCsrf();
        return apiPost(path, body, false);
      }
      const err = new Error(data?.error || `http_${res.status}`);
      err.status = res.status;
      err.data = data;
      throw err;
    }
    return data;
  }

  async function apiGet(path) {
    try {
      const r = await fetch(`${API}${path}`, { credentials: 'include' });
      if (!r.ok) return null;
      return await r.json().catch(() => null);
    } catch (_) { return null; }
  }

  // Sesión cacheada en window para que el avatar/dropdown la lea sin
  // hacer otra request.
  window.bsSession = window.bsSession || { authenticated: false, account: null };

  async function refreshSession() {
    const data = await apiGet('/client/me');
    const auth = !!(data?.authenticated && data?.account);
    window.bsSession = {
      authenticated: auth,
      account: auth ? data.account : null,
    };
    if (data?.csrfToken) csrfToken = data.csrfToken;
    document.dispatchEvent(new CustomEvent('bs:session-changed', { detail: window.bsSession }));
    return window.bsSession;
  }
  window.bsRefreshSession = refreshSession;

  async function bsLogout() {
    try { await apiPost('/client/logout', {}); } catch (_) {}
    csrfToken = '';
    window.bsSession = { authenticated: false, account: null };
    document.dispatchEvent(new CustomEvent('bs:session-changed', { detail: window.bsSession }));
  }
  window.bsLogout = bsLogout;

  const ERR_MESSAGES = {
    email_invalid: 'El email no es válido.',
    email_exists: 'Ya existe una cuenta con ese email. Inicia sesión.',
    username_invalid: 'Usuario no válido (3-32 caracteres, letras/números/._-).',
    username_exists: 'Ese nombre de usuario ya está cogido.',
    password_invalid: 'La contraseña debe tener entre 6 y 120 caracteres.',
    register_disabled: 'El registro está deshabilitado temporalmente.',
    verification_unavailable: 'No podemos enviar el código ahora. Inténtalo en unos minutos.',
    verification_send_failed: 'No se pudo enviar el código. Comprueba el email.',
    verification_session_missing: 'La sesión de verificación ha caducado. Empieza de nuevo.',
    verification_code_invalid: 'Código incorrecto. Revísalo.',
    verification_code_expired: 'El código ha caducado. Pulsa "Reenviar".',
    verification_resend_wait: 'Espera unos segundos antes de pedir otro código.',
    email_already_verified: 'Esa cuenta ya está verificada. Inicia sesión.',
    invalid_credentials: 'Email o contraseña incorrectos.',
    account_inactive: 'Tu cuenta no está activa. Contacta soporte.',
    email_not_verified: 'Tu email no está verificado. Te reenviamos el código.',
    rate_limited: 'Demasiados intentos. Espera unos minutos.',
  };

  const friendlyError = (err) => {
    if (!err) return 'Algo ha ido mal. Inténtalo de nuevo.';
    const code = String(err.data?.error || err.message || '').toLowerCase();
    return ERR_MESSAGES[code] || (err.data?.message || 'No pudimos completar la acción.');
  };

  const isValidEmail = (e) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(e || '').trim());
  const isValidUsername = (u) => /^[a-zA-Z0-9._-]{3,32}$/.test(String(u || '').trim());
  const isValidName = (n) => String(n || '').trim().length >= 2 && String(n || '').trim().length <= 80;
  const isValidPhone = (p) => !p || /^[+0-9\s().-]{6,24}$/.test(String(p || '').trim());

  const usernameSuggestion = (email) => {
    const local = String(email || '').split('@')[0] || '';
    return local.replace(/[^a-zA-Z0-9._-]/g, '').slice(0, 20);
  };

  const AuthModal = ({ open, onClose, planHint, initialMode }) => {
    const [view, setView] = React.useState(initialMode === 'login' ? 'login' : 'register');
    // Register fields
    const [name, setName] = React.useState('');
    const [username, setUsername] = React.useState('');
    const [email, setEmail] = React.useState('');
    const [phone, setPhone] = React.useState('');
    const [password, setPassword] = React.useState('');
    const [confirm, setConfirm] = React.useState('');
    const [terms, setTerms] = React.useState(false);
    // Verify
    const [code, setCode] = React.useState('');
    const [resendIn, setResendIn] = React.useState(0);
    // Login
    const [loginIdent, setLoginIdent] = React.useState('');
    const [loginPass, setLoginPass] = React.useState('');
    // Generales
    const [loading, setLoading] = React.useState(false);
    const [error, setError] = React.useState('');
    const [okMsg, setOkMsg] = React.useState('');
    const [shake, setShake] = React.useState(false);

    React.useEffect(() => {
      if (open) {
        setView(initialMode === 'login' ? 'login' : 'register');
        setError(''); setOkMsg(''); setLoading(false); setResendIn(0); setCode('');
        fetchCsrf().catch(() => {});
      }
    }, [open, initialMode]);

    React.useEffect(() => {
      if (resendIn <= 0) return;
      const t = setInterval(() => setResendIn((s) => Math.max(0, s - 1)), 1000);
      return () => clearInterval(t);
    }, [resendIn]);

    React.useEffect(() => {
      if (!open) return;
      const onKey = (e) => { if (e.key === 'Escape') onClose(); };
      window.addEventListener('keydown', onKey);
      const prev = document.body.style.overflow;
      document.body.style.overflow = 'hidden';
      return () => { window.removeEventListener('keydown', onKey); document.body.style.overflow = prev; };
    }, [open, onClose]);

    if (!open) return null;

    const triggerShake = () => { setShake(true); setTimeout(() => setShake(false), 380); };

    const goSuccess = (nextPath) => {
      setView('success');
      setOkMsg('¡Listo! Te llevamos al panel…');
      refreshSession().catch(() => {});
      setTimeout(() => {
        window.location.href = nextPath || 'https://clientes.blackstock.es/perfil/';
      }, 900);
    };

    // ─── Registro ──────────────────────────────────────────────
    const handleRegister = async (e) => {
      e?.preventDefault?.();
      setError('');
      const cleanEmail = email.trim().toLowerCase();
      const cleanUsername = username.trim() || usernameSuggestion(cleanEmail);
      if (!isValidName(name)) { setError('Pon tu nombre completo.'); triggerShake(); return; }
      if (!isValidEmail(cleanEmail)) { setError('Email no válido.'); triggerShake(); return; }
      if (!isValidUsername(cleanUsername)) { setError('Usuario: 3-32 caracteres (letras/números/._-).'); triggerShake(); return; }
      if (!isValidPhone(phone)) { setError('Teléfono no válido.'); triggerShake(); return; }
      if (password.length < 6) { setError('Contraseña mínima 6 caracteres.'); triggerShake(); return; }
      if (password !== confirm) { setError('Las contraseñas no coinciden.'); triggerShake(); return; }
      if (!terms) { setError('Debes aceptar los términos para continuar.'); triggerShake(); return; }
      setLoading(true);
      try {
        const res = await apiPost('/client/register', {
          name: name.trim(),
          email: cleanEmail,
          username: cleanUsername,
          password,
          phone: phone.trim() || undefined,
        });
        if (res?.requiresEmailVerification) {
          setView('verify');
          setResendIn(RESEND_COOLDOWN_SEC);
          setOkMsg(`Te hemos enviado un código a ${cleanEmail}.`);
        } else {
          goSuccess(res?.nextPath);
        }
      } catch (err) {
        setError(friendlyError(err));
        triggerShake();
      } finally {
        setLoading(false);
      }
    };

    // ─── Verificar código ──────────────────────────────────────
    const handleVerify = async (e) => {
      e?.preventDefault?.();
      setError('');
      const c = code.replace(/\D/g, '').slice(0, 6);
      if (c.length !== 6) { setError('El código tiene 6 dígitos.'); triggerShake(); return; }
      setLoading(true);
      try {
        const res = await apiPost('/client/verify-email', { code: c });
        goSuccess(res?.nextPath);
      } catch (err) {
        setError(friendlyError(err));
        setCode('');
        triggerShake();
      } finally {
        setLoading(false);
      }
    };

    const handleResend = async () => {
      if (resendIn > 0 || loading) return;
      setError('');
      setLoading(true);
      try {
        await apiPost('/client/resend-verification', {});
        setResendIn(RESEND_COOLDOWN_SEC);
        setOkMsg('Código reenviado. Mira tu bandeja y spam.');
      } catch (err) {
        setError(friendlyError(err));
      } finally {
        setLoading(false);
      }
    };

    // ─── Login ──────────────────────────────────────────────────
    const handleLogin = async (e) => {
      e?.preventDefault?.();
      setError('');
      const ident = loginIdent.trim();
      if (!ident || loginPass.length < 1) { setError('Email y contraseña requeridos.'); triggerShake(); return; }
      setLoading(true);
      try {
        const res = await apiPost('/client/login', {
          email: ident.toLowerCase(),
          password: loginPass,
        });
        if (res?.requiresEmailVerification) {
          setView('verify');
          setResendIn(RESEND_COOLDOWN_SEC);
          setOkMsg('Te reenviamos el código de verificación.');
        } else {
          goSuccess(res?.nextPath);
        }
      } catch (err) {
        // Si el server dice email_not_verified con 403, abrimos verify
        if (err?.data?.error === 'email_not_verified') {
          setView('verify');
          setResendIn(RESEND_COOLDOWN_SEC);
          setOkMsg('Tu email no está verificado. Te enviamos un nuevo código.');
        } else {
          setError(friendlyError(err));
          triggerShake();
        }
      } finally {
        setLoading(false);
      }
    };

    const totalSteps = view === 'register' ? 50 : view === 'verify' ? 90 : view === 'login' ? 50 : 100;

    return (
      <div className="bs-modal-overlay" onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}>
        <div className={`bs-modal-card ${shake ? 'bs-shake' : ''}`} role="dialog" aria-modal="true">
          <button type="button" className="bs-modal-close" aria-label="Cerrar" onClick={onClose}>
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round">
              <path d="M6 6 L18 18 M18 6 L6 18" />
            </svg>
          </button>

          <div className="bs-modal-progress"><div style={{ width: `${totalSteps}%` }} /></div>

          {/* Tabs Login/Register cuando no estamos en verify/success */}
          {(view === 'register' || view === 'login') && (
            <div className="bs-modal-tabs">
              <button type="button" className={view === 'register' ? 'is-active' : ''} onClick={() => { setView('register'); setError(''); }}>
                Crear cuenta
              </button>
              <button type="button" className={view === 'login' ? 'is-active' : ''} onClick={() => { setView('login'); setError(''); }}>
                Iniciar sesión
              </button>
            </div>
          )}

          {view === 'register' && (
            <form onSubmit={handleRegister} noValidate>
              <p className="bs-modal-eyebrow">{planHint ? `Plan ${planHint}` : 'Acceso a Blackstock'}</p>
              <h2 className="bs-modal-title">Empieza en 30 segundos</h2>
              <p className="bs-modal-sub">Te mandamos un código al email para verificar tu cuenta.</p>

              <div className="bs-grid-2">
                <label className="bs-field">
                  <span>Nombre</span>
                  <input type="text" autoComplete="given-name" required placeholder="Marc"
                    value={name} onChange={(e) => setName(e.target.value)} disabled={loading} autoFocus />
                </label>
                <label className="bs-field">
                  <span>Usuario</span>
                  <input type="text" autoComplete="username" required placeholder="marc23"
                    value={username} onChange={(e) => setUsername(e.target.value)} disabled={loading} />
                </label>
              </div>

              <label className="bs-field">
                <span>Email</span>
                <input type="email" inputMode="email" autoComplete="email" required placeholder="tu@email.com"
                  value={email} onChange={(e) => setEmail(e.target.value)} disabled={loading} />
              </label>

              <label className="bs-field">
                <span>Teléfono <small>(opcional)</small></span>
                <input type="tel" autoComplete="tel" placeholder="+34 600 000 000"
                  value={phone} onChange={(e) => setPhone(e.target.value)} disabled={loading} />
              </label>

              <div className="bs-grid-2">
                <label className="bs-field">
                  <span>Contraseña</span>
                  <input type="password" autoComplete="new-password" required minLength={6} placeholder="Mínimo 6"
                    value={password} onChange={(e) => setPassword(e.target.value)} disabled={loading} />
                </label>
                <label className="bs-field">
                  <span>Confirmar</span>
                  <input type="password" autoComplete="new-password" required minLength={6} placeholder="Repite contraseña"
                    value={confirm} onChange={(e) => setConfirm(e.target.value)} disabled={loading} />
                </label>
              </div>

              <label className="bs-checkbox-row">
                <span className="bs-checkbox-wrap">
                  <input
                    type="checkbox"
                    checked={terms}
                    onChange={(e) => setTerms(e.target.checked)}
                    disabled={loading}
                  />
                  <span className="bs-checkbox-box" aria-hidden="true">
                    <svg viewBox="0 0 24 24"><polyline points="5 12 10 17 19 8" /></svg>
                  </span>
                </span>
                <span>Acepto los <a href="https://blackstock.es/terminos" target="_blank" rel="noopener">términos</a> y la <a href="https://blackstock.es/privacidad" target="_blank" rel="noopener">privacidad</a>.</span>
              </label>

              {error ? <div className="bs-modal-error">{error}</div> : null}

              <button type="submit" className="bs-btn bs-btn-acid bs-btn-block" disabled={loading}>
                {loading ? <span className="bs-spinner" /> : null}
                {loading ? 'Creando cuenta…' : 'Continuar →'}
              </button>
            </form>
          )}

          {view === 'login' && (
            <form onSubmit={handleLogin} noValidate>
              <p className="bs-modal-eyebrow">Bienvenido de vuelta</p>
              <h2 className="bs-modal-title">Inicia sesión</h2>
              <p className="bs-modal-sub">Entra con tu email y contraseña.</p>

              <label className="bs-field">
                <span>Email</span>
                <input type="email" inputMode="email" autoComplete="email" required placeholder="tu@email.com"
                  value={loginIdent} onChange={(e) => setLoginIdent(e.target.value)} disabled={loading} autoFocus />
              </label>
              <label className="bs-field">
                <span>Contraseña</span>
                <input type="password" autoComplete="current-password" required placeholder="Tu contraseña"
                  value={loginPass} onChange={(e) => setLoginPass(e.target.value)} disabled={loading} />
              </label>

              {okMsg && !error ? <div className="bs-modal-ok">{okMsg}</div> : null}
              {error ? <div className="bs-modal-error">{error}</div> : null}

              <button type="submit" className="bs-btn bs-btn-acid bs-btn-block" disabled={loading}>
                {loading ? <span className="bs-spinner" /> : null}
                {loading ? 'Entrando…' : 'Iniciar sesión →'}
              </button>

              <p className="bs-modal-fineprint">
                <a href="https://clientes.blackstock.es/?reset=1">¿Has olvidado la contraseña?</a>
              </p>
            </form>
          )}

          {view === 'verify' && (
            <form onSubmit={handleVerify} noValidate>
              <p className="bs-modal-eyebrow">Verifica tu email</p>
              <h2 className="bs-modal-title">Te hemos enviado un código</h2>
              <p className="bs-modal-sub">Caduca en {VERIFY_TTL_MIN} minutos. Mira la bandeja de entrada o spam.</p>

              <label className="bs-field">
                <span>Código de 6 dígitos</span>
                <input type="text" inputMode="numeric" pattern="[0-9]*" autoComplete="one-time-code" required maxLength={6}
                  placeholder="••••••" value={code}
                  onChange={(e) => setCode(e.target.value.replace(/\D/g, '').slice(0, 6))}
                  disabled={loading} autoFocus className="bs-code-input" />
              </label>

              {okMsg && !error ? <div className="bs-modal-ok">{okMsg}</div> : null}
              {error ? <div className="bs-modal-error">{error}</div> : null}

              <button type="submit" className="bs-btn bs-btn-acid bs-btn-block" disabled={loading || code.length !== 6}>
                {loading ? <span className="bs-spinner" /> : null}
                {loading ? 'Verificando…' : 'Verificar y entrar →'}
              </button>

              <div className="bs-resend-row">
                {resendIn > 0 ? (
                  <span>Podrás reenviar en {resendIn}s</span>
                ) : (
                  <button type="button" className="bs-link-btn" onClick={handleResend} disabled={loading}>
                    Reenviar código
                  </button>
                )}
                <button type="button" className="bs-link-btn" onClick={() => { setView('register'); setCode(''); setError(''); }} disabled={loading}>
                  Cambiar email
                </button>
              </div>
            </form>
          )}

          {view === 'success' && (
            <div className="bs-modal-success">
              <div className="bs-modal-checkmark">
                <svg width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M5 12 L10 17 L19 7" />
                </svg>
              </div>
              <h2 className="bs-modal-title">¡Listo!</h2>
              <p className="bs-modal-sub">{okMsg}</p>
            </div>
          )}
        </div>
      </div>
    );
  };

  // Auto-detectar sesión al cargar
  if (typeof window !== 'undefined') {
    setTimeout(() => refreshSession().catch(() => {}), 600);
  }

  // Wrapper global
  let modalRoot = null, modalReactRoot = null;
  let currentPlan = null, currentMode = 'register';

  const renderModal = (open) => {
    if (!modalRoot) {
      modalRoot = document.createElement('div');
      modalRoot.id = 'bs-auth-root';
      document.body.appendChild(modalRoot);
      modalReactRoot = ReactDOM.createRoot(modalRoot);
    }
    modalReactRoot.render(
      <AuthModal open={open} planHint={currentPlan} initialMode={currentMode} onClose={() => renderModal(false)} />
    );
  };

  window.bsOpenAuth = (planHint, mode) => {
    currentPlan = planHint || null;
    currentMode = mode === 'login' ? 'login' : 'register';
    renderModal(true);
  };
  window.bsCloseAuth = () => renderModal(false);
  window.AuthModal = AuthModal;
})();
