const { useState, useEffect, useCallback, useRef } = React;
const API = 'https://api.vocal.ch';

// ==================== ICONS (SVG cohérents avec my.app) ====================
const Icon = {
  Phone: ({ s = 18 }) => (
    <svg xmlns="http://www.w3.org/2000/svg" width={s} height={s} fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2">
      <path strokeLinecap="round" strokeLinejoin="round" d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
    </svg>
  ),
  PhoneIn: ({ s = 18 }) => (
    <svg xmlns="http://www.w3.org/2000/svg" width={s} height={s} fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2">
      <path strokeLinecap="round" strokeLinejoin="round" d="M21 3l-6 6m0 0V4m0 5h5M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
    </svg>
  ),
  Bell: ({ s = 22 }) => (
    <svg xmlns="http://www.w3.org/2000/svg" width={s} height={s} fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2">
      <path strokeLinecap="round" strokeLinejoin="round" d="M15 17h5l-1.4-1.4A2 2 0 0118 14.17V11a6 6 0 10-12 0v3.17a2 2 0 01-.6 1.43L4 17h5m6 0a3 3 0 11-6 0" />
    </svg>
  ),
  Stack: ({ s = 22 }) => (
    <svg xmlns="http://www.w3.org/2000/svg" width={s} height={s} fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2">
      <path strokeLinecap="round" strokeLinejoin="round" d="M4 6h16M4 12h16M4 18h16" />
    </svg>
  ),
  Headphones: ({ s = 16 }) => (
    <svg xmlns="http://www.w3.org/2000/svg" width={s} height={s} fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2">
      <path strokeLinecap="round" strokeLinejoin="round" d="M19 11a7 7 0 10-14 0v6a2 2 0 002 2h2v-6H5m14 0v6a2 2 0 01-2 2h-2v-6h4" />
    </svg>
  ),
  Whisper: ({ s = 16 }) => (
    <svg xmlns="http://www.w3.org/2000/svg" width={s} height={s} fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2">
      <path strokeLinecap="round" strokeLinejoin="round" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
    </svg>
  ),
  Megaphone: ({ s = 16 }) => (
    <svg xmlns="http://www.w3.org/2000/svg" width={s} height={s} fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2">
      <path strokeLinecap="round" strokeLinejoin="round" d="M11 5.882V19.24a1.76 1.76 0 01-3.417.592l-2.147-6.15M18 13a3 3 0 100-6M5.436 13.683A4.001 4.001 0 017 6h1.832c4.1 0 7.625-1.234 9.168-3v14c-1.543-1.766-5.067-3-9.168-3H7a3.988 3.988 0 01-1.564-.317z" />
    </svg>
  ),
  Stop: ({ s = 16 }) => (
    <svg xmlns="http://www.w3.org/2000/svg" width={s} height={s} fill="currentColor" viewBox="0 0 24 24">
      <rect x="6" y="6" width="12" height="12" rx="2" />
    </svg>
  ),
  Robot: ({ s = 14 }) => (
    <svg xmlns="http://www.w3.org/2000/svg" width={s} height={s} fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2">
      <path strokeLinecap="round" strokeLinejoin="round" d="M12 2v3m-6 3h12a2 2 0 012 2v8a2 2 0 01-2 2H6a2 2 0 01-2-2v-8a2 2 0 012-2zm3 4h6m-6 4h.01m5.99 0H15M9 18h6" />
    </svg>
  ),
  Clock: ({ s = 14 }) => (
    <svg xmlns="http://www.w3.org/2000/svg" width={s} height={s} fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2">
      <path strokeLinecap="round" strokeLinejoin="round" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
    </svg>
  ),
  ArrowDown: ({ s = 14 }) => (
    <svg xmlns="http://www.w3.org/2000/svg" width={s} height={s} fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2">
      <path strokeLinecap="round" strokeLinejoin="round" d="M19 5L5 19m0 0h10M5 19V9" />
    </svg>
  ),
  ArrowUp: ({ s = 14 }) => (
    <svg xmlns="http://www.w3.org/2000/svg" width={s} height={s} fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2">
      <path strokeLinecap="round" strokeLinejoin="round" d="M5 19l14-14m0 0h-10m10 0v10" />
    </svg>
  ),
  Logout: ({ s = 14 }) => (
    <svg xmlns="http://www.w3.org/2000/svg" width={s} height={s} fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2">
      <path strokeLinecap="round" strokeLinejoin="round" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
    </svg>
  ),
  Alert: ({ s = 16 }) => (
    <svg xmlns="http://www.w3.org/2000/svg" width={s} height={s} fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="2">
      <path strokeLinecap="round" strokeLinejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
    </svg>
  ),
};

// ==================== API ====================
const api = {
  token: () => localStorage.getItem('center_token'),
  setToken: (t) => localStorage.setItem('center_token', t),
  clear: () => localStorage.removeItem('center_token'),
  async req(path, opts = {}) {
    const headers = { 'Content-Type': 'application/json', ...(opts.headers || {}) };
    const t = this.token(); if (t) headers['Authorization'] = 'Bearer ' + t;
    const r = await fetch(API + path, { ...opts, headers });
    if (r.status === 401) { this.clear(); location.reload(); return null; }
    let body = null;
    try { body = await r.json(); } catch (e) { body = {}; }
    if (body && typeof body === 'object') body.__status = r.status;
    return body;
  },
  get(p) { return this.req(p); },
  post(p, b) { return this.req(p, { method: 'POST', body: JSON.stringify(b || {}) }); },
};

// ==================== UTILS ====================
const fmtDur = (s) => {
  const m = Math.floor(s / 60); const r = s % 60;
  return `${m}:${String(r).padStart(2, '0')}`;
};

const initialFromNumber = (str) => {
  if (!str) return '?';
  const cleaned = String(str).replace(/[^\d+]/g, '');
  const last = cleaned.slice(-2);
  return last || '?';
};

const STATUS_LABELS = {
  'in-progress': 'En cours',
  'ringing': 'Sonnerie',
  'hold': 'En attente',
};

// ==================== LOGIN VIEW ====================
function LoginView({ onLogin }) {
  const [email, setEmail] = useState('');
  const [code, setCode] = useState('');
  const [step, setStep] = useState('email');
  const [loading, setLoading] = useState(false);
  const [err, setErr] = useState(null);

  const sendCode = async () => {
    setLoading(true); setErr(null);
    try {
      const r = await api.post('/auth/request-code', { email });
      if (r?.error) setErr(r.error);
      else setStep('code');
    } catch (e) { setErr('Erreur réseau'); }
    finally { setLoading(false); }
  };
  const verify = async () => {
    setLoading(true); setErr(null);
    try {
      const r = await api.post('/auth/verify-code', { email, code });
      if (r?.error) setErr(r.error);
      else { api.setToken(r.token); onLogin(); }
    } catch (e) { setErr('Erreur réseau'); }
    finally { setLoading(false); }
  };

  return (
    <div className="login-wrap">
      <div className="login-card">
        <div className="login-brand">
          <div className="brand-icon"><Icon.Bell s={20} /></div>
          <div>
            <h1>Vocal Center</h1>
          </div>
        </div>
        <p className="login-subtitle">Centre de supervision live de vos lignes ouvertes.</p>

        {err && (
          <div className="login-error">
            <Icon.Alert s={16} />
            <span>{err}</span>
          </div>
        )}

        {step === 'email' ? (
          <>
            <label htmlFor="login-email">Adresse email</label>
            <input
              id="login-email"
              type="email"
              placeholder="email@exemple.ch"
              value={email}
              onChange={e => setEmail(e.target.value)}
              autoFocus
            />
            <button className="btn btn-primary" onClick={sendCode} disabled={loading || !email}>
              {loading ? <><span className="spinner"></span> Envoi…</> : 'Recevoir le code'}
            </button>
          </>
        ) : (
          <>
            <label htmlFor="login-code">Code reçu par email</label>
            <input
              id="login-code"
              type="text"
              placeholder="123456"
              value={code}
              onChange={e => setCode(e.target.value)}
              maxLength={6}
              autoFocus
              style={{ letterSpacing: '0.3em', fontWeight: 700, textAlign: 'center', fontSize: '1.25rem' }}
            />
            <div className="login-actions">
              <button className="btn btn-primary" onClick={verify} disabled={loading || !code}>
                {loading ? <><span className="spinner"></span> Vérification…</> : 'Connexion'}
              </button>
              <button className="btn" onClick={() => { setStep('email'); setCode(''); }}>Retour</button>
            </div>
          </>
        )}
      </div>
    </div>
  );
}

// ==================== DASHBOARD ====================
function Dashboard({ user, onLogout }) {
  const [calls, setCalls] = useState([]);
  const [tick, setTick] = useState(0);
  const [monitor, setMonitor] = useState(null);
  const [toast, setToast] = useState(null);
  const [moduleGate, setModuleGate] = useState(null);
  const deviceRef = useRef(null);
  const callRef = useRef(null);

  const showToast = (msg, kind = 'success') => {
    setToast({ msg, kind });
    setTimeout(() => setToast(null), 3500);
  };

  const loadCalls = useCallback(async () => {
    const r = await api.get('/my/live/active-calls');
    if (r && r.__status === 402) {
      setModuleGate({
        code: r.module_required || 'live_center',
        name: r.module_name || 'Live monitoring',
        price: r.module_price_chf || 0,
        hint: r.hint || '',
      });
      setCalls([]);
      return;
    }
    setModuleGate(null);
    setCalls(r?.active_calls || []);
  }, []);

  useEffect(() => { loadCalls(); }, [loadCalls]);
  useEffect(() => {
    if (moduleGate) return;
    const id = setInterval(() => { loadCalls(); setTick(t => t + 1); }, 3000);
    return () => clearInterval(id);
  }, [loadCalls, moduleGate]);

  if (moduleGate) {
    return (
      <div className="app">
        <div className="app-header">
          <h1>
            <div className="brand-icon"><Icon.Bell s={20} /></div>
            Vocal Center
          </h1>
          <div className="user-info">
            <span className="user-email">{user?.email}</span>
            <button className="btn btn-sm" onClick={onLogout}>
              <Icon.Logout s={14} />
              Déconnexion
            </button>
          </div>
        </div>
        <div className="dashboard">
          <div className="module-gate">
            <div className="module-gate-icon"><Icon.Headphones s={36} /></div>
            <h2>Module « {moduleGate.name} » non activé</h2>
            <p>
              Le centre de supervision live nécessite l'activation du module
              {' '}<strong>{moduleGate.name}</strong>
              {moduleGate.price ? <> ({moduleGate.price.toFixed(2)} CHF / mois)</> : null}.
            </p>
            <p className="module-gate-hint">{moduleGate.hint || 'Activez-le depuis Mon Vocal → Modules.'}</p>
            <div className="module-gate-actions">
              <a className="btn btn-primary" href="https://my.vocal.ch/#modules" target="_blank" rel="noopener">
                Activer le module
              </a>
              <button className="btn" onClick={() => { setModuleGate(null); loadCalls(); }}>
                Réessayer
              </button>
            </div>
          </div>
        </div>
        {toast && <div className={'toast ' + toast.kind}>{toast.msg}</div>}
      </div>
    );
  }

  const startMonitor = async (callSid, mode = 'monitor') => {
    try {
      const r = await api.post('/my/live/start', { call_sid: callSid, mode });
      if (r?.error) { showToast(r.error, 'error'); return; }
      const tokR = await api.get('/my/live/listen-token?session_id=' + r.session_id);
      if (tokR?.error) { showToast(tokR.error, 'error'); return; }
      const Device = window.Twilio?.Device;
      if (!Device) { showToast('SDK Twilio non chargé', 'error'); return; }
      if (deviceRef.current) { try { deviceRef.current.destroy(); } catch (e) {} }
      const dev = new Device(tokR.token, { logLevel: 1, codecPreferences: ['opus', 'pcmu'] });
      deviceRef.current = dev;
      await dev.register();
      const params = { conferenceName: tokR.conference_name, mode };
      const conn = await dev.connect({ params });
      callRef.current = conn;
      conn.on('disconnect', () => { setMonitor(null); callRef.current = null; });
      setMonitor({ sessionId: r.session_id, callSid, mode, conferenceName: tokR.conference_name });
      showToast('Surveillance active', 'success');
    } catch (e) {
      showToast('Erreur: ' + e.message, 'error');
    }
  };

  const stopMonitor = async () => {
    if (callRef.current) { try { callRef.current.disconnect(); } catch (e) {} callRef.current = null; }
    if (deviceRef.current) { try { await deviceRef.current.destroy(); } catch (e) {} deviceRef.current = null; }
    if (monitor) {
      await api.post('/my/live/sessions/' + monitor.sessionId + '/stop');
    }
    setMonitor(null);
    showToast('Surveillance arrêtée', 'success');
  };

  const stats = {
    active: calls.filter(c => c.status === 'in-progress').length,
    ringing: calls.filter(c => c.status === 'ringing').length,
    total: calls.length,
  };

  const monitorLabels = { monitor: 'Écoute', whisper: 'Whisper', barge: 'Barge-in' };

  return (
    <div className="app">
      <div className="app-header">
        <h1>
          <div className="brand-icon"><Icon.Bell s={20} /></div>
          <span className="live-pulse"></span>
          Vocal Center
        </h1>
        <div className="user-info">
          {monitor && (
            <span className="monitor-badge">
              <span className="dot"></span>
              Surveillance · {monitorLabels[monitor.mode] || monitor.mode}
            </span>
          )}
          <span className="user-email">{user?.email}</span>
          <button className="btn btn-sm" onClick={onLogout}>
            <Icon.Logout s={14} />
            Déconnexion
          </button>
        </div>
      </div>

      <div className="dashboard">
        <div className="stats-grid">
          <div className="stat-card">
            <div className="stat-icon live"><Icon.Phone s={22} /></div>
            <div className="stat-value live-color">{stats.active}</div>
            <div className="stat-label">Appels actifs</div>
          </div>
          <div className="stat-card">
            <div className="stat-icon warning"><Icon.Bell s={22} /></div>
            <div className="stat-value">{stats.ringing}</div>
            <div className="stat-label">En sonnerie</div>
          </div>
          <div className="stat-card">
            <div className="stat-icon purple"><Icon.Stack s={22} /></div>
            <div className="stat-value">{stats.total}</div>
            <div className="stat-label">Total en cours</div>
          </div>
        </div>

        <div className="section-title">
          <h2>Appels en cours</h2>
          <span className="auto-refresh">
            <span className="dot"></span>
            Auto-refresh · 3s
          </span>
        </div>

        {calls.length === 0 ? (
          <div className="empty-state">
            <div className="empty-state-icon"><Icon.Phone s={28} /></div>
            <h2>Aucun appel en cours</h2>
            <p>Les appels actifs sur vos lignes apparaîtront ici en temps réel.</p>
          </div>
        ) : (
          <div className="calls-grid">
            {calls.map(c => {
              const isMonitored = monitor?.callSid === c.call_sid;
              const elapsed = Math.floor((Date.now() - new Date(c.started_at + 'Z').getTime()) / 1000);
              return (
                <div key={c.call_sid} className={'call-card live' + (isMonitored ? ' monitoring' : '')}>
                  <div className="call-header">
                    <div className="call-from-block">
                      <div className="call-avatar">{initialFromNumber(c.from_number)}</div>
                      <div className="call-from-info">
                        <div className="call-from">{c.from_number || '?'}</div>
                        <div className="call-line">→ {c.line_label || c.line_phone}</div>
                      </div>
                    </div>
                    <span className={'call-status ' + c.status}>
                      <span className="dot"></span>
                      {STATUS_LABELS[c.status] || c.status}
                    </span>
                  </div>

                  <div className="call-meta">
                    <span className="meta-pill">
                      <Icon.Clock s={12} />
                      {fmtDur(elapsed)}
                    </span>
                    <span className={'meta-pill ' + (c.direction === 'inbound' ? 'direction-in' : 'direction-out')}>
                      {c.direction === 'inbound' ? <Icon.ArrowDown s={12} /> : <Icon.ArrowUp s={12} />}
                      {c.direction === 'inbound' ? 'Entrant' : 'Sortant'}
                    </span>
                    {c.bot_id && (
                      <span className="meta-pill bot">
                        <Icon.Robot s={12} />
                        Bot
                      </span>
                    )}
                  </div>

                  <div className="call-actions">
                    {!isMonitored && (
                      <>
                        <button className="btn btn-sm btn-primary" onClick={() => startMonitor(c.call_sid, 'monitor')} title="Écouter discrètement">
                          <Icon.Headphones s={14} />
                          Écouter
                        </button>
                        <button className="btn btn-sm" onClick={() => startMonitor(c.call_sid, 'whisper')} title="Souffler à l'agent">
                          <Icon.Whisper s={14} />
                          Whisper
                        </button>
                        <button className="btn btn-sm" onClick={() => startMonitor(c.call_sid, 'barge')} title="Prendre la main">
                          <Icon.Megaphone s={14} />
                          Barge-in
                        </button>
                      </>
                    )}
                    {isMonitored && (
                      <button className="btn btn-sm btn-danger" onClick={stopMonitor}>
                        <Icon.Stop s={12} />
                        Arrêter
                      </button>
                    )}
                  </div>
                </div>
              );
            })}
          </div>
        )}
      </div>

      {toast && <div className={'toast ' + toast.kind}>{toast.msg}</div>}
    </div>
  );
}

// ==================== APP ====================
function App() {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    if (!api.token()) { setLoading(false); return; }
    api.get('/my/profile').then(r => {
      if (r && !r.error) setUser(r.profile || r.user || { email: 'connecté' });
      setLoading(false);
    });
  }, []);

  if (loading) return <div className="app-loading"><div className="loading-spinner"></div></div>;
  if (!user) return <LoginView onLogin={() => { window.location.reload(); }} />;
  return <Dashboard user={user} onLogout={() => { api.clear(); setUser(null); }} />;
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
