/* ==================== Vocal Mobile App ==================== */
const { useState, useEffect, useRef, useCallback, useMemo, createContext, useContext, Fragment } = React;
const api = window.api;
const CONFIG = window.CONFIG;

/* ==================== Constants ==================== */
const LINE_TYPES = {
    forward: { label: 'Redirection', color: 'badge-info', icon: 'arrow-right' },
    ivr: { label: 'Menu IVR', color: 'badge-warning', icon: 'menu' },
    voice_ai: { label: 'IA Vocale', color: 'badge-primary', icon: 'sparkles' },
    voicemail: { label: 'Messagerie', color: 'badge-gray', icon: 'inbox' },
    browser: { label: 'Navigateur', color: 'badge-success', icon: 'globe' },
    link: { label: 'Lien SMS', color: 'badge-purple', icon: 'link' },
    webhook: { label: 'Webhook', color: 'badge-orange', icon: 'code' },
    external_api: { label: 'API externe', color: 'badge-dark', icon: 'cloud' },
};
const CALL_STATUS = {
    completed: { label: 'Terminé', color: 'badge-success' },
    ringing: { label: 'Sonne', color: 'badge-info' },
    'in-progress': { label: 'En cours', color: 'badge-info' },
    busy: { label: 'Occupé', color: 'badge-warning' },
    'no-answer': { label: 'Sans réponse', color: 'badge-warning' },
    failed: { label: 'Échoué', color: 'badge-danger' },
    canceled: { label: 'Annulé', color: 'badge-gray' },
    missed: { label: 'Manqué', color: 'badge-danger' },
};
const RECHARGE_PACKS = [
    { amount: 10, bonus: 0 },
    { amount: 25, bonus: 0 },
    { amount: 50, bonus: 2 },
    { amount: 100, bonus: 5, popular: true },
    { amount: 250, bonus: 20 },
    { amount: 500, bonus: 50 },
];
const SUB_PRICE_MONTHLY = 9;
const SUB_PRICE_YEARLY = 90;

/* ==================== Formatters ==================== */
const fmtDate = (d) => d ? new Date(d).toLocaleDateString('fr-CH', { day: '2-digit', month: '2-digit', year: 'numeric' }) : '-';
const fmtDateShort = (d) => { if (!d) return ''; const x = new Date(d); return `${String(x.getDate()).padStart(2,'0')}/${String(x.getMonth()+1).padStart(2,'0')}`; };
const fmtTime = (d) => d ? new Date(d).toLocaleTimeString('fr-CH', { hour: '2-digit', minute: '2-digit' }) : '';
const fmtDateTime = (d) => d ? `${fmtDate(d)} ${fmtTime(d)}` : '-';
const fmtAmount = (n, c = 'CHF', sign = false) => {
    if (n === null || n === undefined) return '-';
    const v = Number(n); const p = sign && v > 0 ? '+' : '';
    return `${p}${v.toFixed(2)} ${c}`;
};
const fmtDuration = (s) => {
    if (!s) return '-';
    const m = Math.floor(s / 60); const sec = s % 60;
    if (m === 0) return `${sec}s`;
    return `${m}m${sec > 0 ? String(sec).padStart(2, '0') + 's' : ''}`;
};
const fmtRelative = (d) => {
    if (!d) return '-';
    const diff = (Date.now() - new Date(d).getTime()) / 1000;
    if (diff < 60) return 'à l\'instant';
    if (diff < 3600) return `${Math.floor(diff / 60)} min`;
    if (diff < 86400) return `${Math.floor(diff / 3600)} h`;
    if (diff < 604800) return `${Math.floor(diff / 86400)} j`;
    return fmtDate(d);
};
const fmtPhone = (n) => {
    if (!n) return '';
    let s = String(n).replace(/[^\d+]/g, '');
    if (s.startsWith('+41') && s.length >= 12) {
        return `${s.slice(0, 3)} ${s.slice(3, 5)} ${s.slice(5, 8)} ${s.slice(8, 10)} ${s.slice(10)}`;
    }
    return s;
};

/* ==================== Icons ==================== */
const I = {
    Home: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/></svg>,
    Phone: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path 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: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path 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>,
    PhoneOut: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M16 3h5v5M21 3l-7 7M3 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>,
    Activity: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M22 12h-4l-3 9L9 3l-3 9H2"/></svg>,
    Wallet: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M21 12V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2h14a2 2 0 002-2v-3m-4-1a2 2 0 11-4 0 2 2 0 014 0z"/></svg>,
    Card: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z"/></svg>,
    Send: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/></svg>,
    Chat: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path 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>,
    Key: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z"/></svg>,
    Settings: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/><circle cx="12" cy="12" r="3"/></svg>,
    More: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="5" cy="12" r="2"/><circle cx="12" cy="12" r="2"/><circle cx="19" cy="12" r="2"/></svg>,
    User: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/></svg>,
    Logout: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path 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>,
    Plus: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 4v16m8-8H4"/></svg>,
    Refresh: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/></svg>,
    Back: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M15 19l-7-7 7-7"/></svg>,
    ChevronRight: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M9 5l7 7-7 7"/></svg>,
    Check: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M5 13l4 4L19 7"/></svg>,
    X: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M6 18L18 6M6 6l12 12"/></svg>,
    Search: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="11" cy="11" r="7"/><path d="M21 21l-4.35-4.35"/></svg>,
    Eye: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="12" cy="12" r="3"/><path d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/></svg>,
    EyeOff: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21"/></svg>,
    Copy: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg>,
    Trash: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 6h18M8 6V4a2 2 0 012-2h4a2 2 0 012 2v2m3 0v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6h14z"/></svg>,
    Bell: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"/></svg>,
    Edit: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/></svg>,
    Star: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z"/></svg>,
    Alert: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path 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>,
    Clock: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 3"/></svg>,
    ArrowDown: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M19 14l-7 7m0 0l-7-7m7 7V3"/></svg>,
    ArrowUp: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M5 10l7-7m0 0l7 7m-7-7v18"/></svg>,
    Globe: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3a13 13 0 010 18M12 3a13 13 0 000 18"/></svg>,
    Mail: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/></svg>,
    Cog: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09a1.65 1.65 0 00-1-1.51 1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83 0 2 2 0 010-2.83l.06-.06a1.65 1.65 0 00.33-1.82 1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09a1.65 1.65 0 001.51-1 1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06a1.65 1.65 0 001.82.33h0a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06a1.65 1.65 0 00-.33 1.82v0a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z"/></svg>,
    Logo: (p) => <svg viewBox="0 0 24 24" fill="currentColor" {...p}><path 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>,
};

/* ==================== Toast / Notifications ==================== */
const ToastContext = createContext();
const useToast = () => useContext(ToastContext);
const ToastProvider = ({ children }) => {
    const [toasts, setToasts] = useState([]);
    const push = useCallback((message, type = 'info') => {
        const id = Math.random().toString(36).slice(2);
        setToasts(t => [...t, { id, message, type }]);
        setTimeout(() => setToasts(t => t.filter(x => x.id !== id)), 3500);
    }, []);
    const ctx = useMemo(() => ({
        success: m => push(m, 'success'),
        error: m => push(m, 'error'),
        info: m => push(m, 'info'),
    }), [push]);
    return (
        <ToastContext.Provider value={ctx}>
            {children}
            <div className="toast-container">
                {toasts.map(t => <div key={t.id} className={`toast ${t.type}`}>{t.message}</div>)}
            </div>
        </ToastContext.Provider>
    );
};

/* ==================== App Context ==================== */
const AppContext = createContext();
const useApp = () => useContext(AppContext);

const TABS = [
    { id: 'home', label: 'Accueil', icon: I.Home },
    { id: 'lines', label: 'Lignes', icon: I.Phone },
    { id: 'activity', label: 'Activité', icon: I.Activity },
    { id: 'billing', label: 'Crédits', icon: I.Wallet },
    { id: 'more', label: 'Plus', icon: I.More },
];

const AppProvider = ({ children }) => {
    const [user, setUser] = useState(() => {
        const saved = localStorage.getItem(CONFIG.STORAGE_KEYS.USER);
        const token = localStorage.getItem(CONFIG.STORAGE_KEYS.TOKEN);
        if (saved && token) { api.token = token; try { return { ...JSON.parse(saved), token }; } catch (e) {} }
        return null;
    });
    const initialHash = (window.location.hash || '').replace('#', '');
    const initialTab = ['home', 'lines', 'activity', 'billing', 'more'].includes(initialHash) ? initialHash : 'home';
    const [tab, setTab] = useState(initialTab);
    const [stack, setStack] = useState([]);

    const toast = useToast();

    const push = useCallback((screen, params = {}) => {
        setStack(s => [...s, { screen, params, key: Math.random().toString(36).slice(2) }]);
    }, []);
    const pop = useCallback(() => setStack(s => s.slice(0, -1)), []);
    const popAll = useCallback(() => setStack([]), []);
    const switchTab = useCallback((id) => {
        setTab(id);
        setStack([]);
        try { window.history.replaceState(null, '', `#${id}`); } catch (e) {}
    }, []);

    const login = useCallback((userData, token) => {
        api.token = token;
        const u = { ...userData, token };
        setUser(u);
        localStorage.setItem(CONFIG.STORAGE_KEYS.USER, JSON.stringify(userData));
        localStorage.setItem(CONFIG.STORAGE_KEYS.TOKEN, token);
        toast.success('Bienvenue sur Vocal');
    }, [toast]);
    const logout = useCallback(() => {
        api.logout().catch(() => {});
        api.token = null;
        setUser(null);
        setStack([]);
        setTab('home');
        localStorage.removeItem(CONFIG.STORAGE_KEYS.USER);
        localStorage.removeItem(CONFIG.STORAGE_KEYS.TOKEN);
        toast.info('À bientôt');
    }, [toast]);
    const refreshProfile = useCallback(async () => {
        try {
            const data = await api.me();
            if (data?.success && data.user) {
                setUser(prev => ({ ...prev, ...data.user, token: prev?.token }));
                localStorage.setItem(CONFIG.STORAGE_KEYS.USER, JSON.stringify(data.user));
            }
        } catch (e) {}
    }, []);

    useEffect(() => {
        if (user) refreshProfile();
    }, [user?.token]);

    const value = useMemo(() => ({
        user, login, logout, refreshProfile, setUser,
        tab, switchTab, stack, push, pop, popAll,
        toast,
    }), [user, login, logout, refreshProfile, tab, switchTab, stack, push, pop, popAll, toast]);

    return <AppContext.Provider value={value}>{children}</AppContext.Provider>;
};

/* ==================== Shared UI ==================== */
const TopHeader = ({ title, right, transparent, left = false }) => (
    <div className={`top-header ${transparent ? 'transparent' : ''} ${left ? 'left' : ''}`}>
        <div style={{ width: 40 }} />
        <h1>{title}</h1>
        <div style={{ width: 40, display: 'flex', justifyContent: 'flex-end' }}>{right}</div>
    </div>
);

const StackHeader = ({ title, right }) => {
    const { pop } = useApp();
    return (
        <div className="top-header">
            <button className="header-action back-btn" onClick={pop} aria-label="Retour">
                <I.Back style={{ width: 22, height: 22 }} />
            </button>
            <h1>{title}</h1>
            <div style={{ width: 40, display: 'flex', justifyContent: 'flex-end' }}>{right}</div>
        </div>
    );
};

const TabBar = () => {
    const { tab, switchTab, stack } = useApp();
    if (stack.length > 0) return null;
    return (
        <div className="tab-bar">
            {TABS.map(t => (
                <button key={t.id} className={`tab-item ${tab === t.id ? 'active' : ''}`} onClick={() => switchTab(t.id)}>
                    <t.icon />
                    <span>{t.label}</span>
                </button>
            ))}
        </div>
    );
};

const Sheet = ({ open, onClose, title, children }) => {
    if (!open) return null;
    return (
        <div className="sheet-backdrop" onClick={onClose}>
            <div className="sheet" onClick={e => e.stopPropagation()}>
                <div className="sheet-handle" />
                {title && <h3 className="sheet-title">{title}</h3>}
                {children}
            </div>
        </div>
    );
};

const Skeleton = ({ w = '100%', h = 14, r = 6, style = {} }) => (
    <span className="skeleton" style={{ width: w, height: h, borderRadius: r, display: 'block', ...style }}>&nbsp;</span>
);

const EmptyState = ({ icon: Icon = I.Activity, title, message, action }) => (
    <div className="empty-state">
        <div className="icon-circle"><Icon style={{ width: 32, height: 32 }} /></div>
        <h3>{title}</h3>
        {message && <p>{message}</p>}
        {action}
    </div>
);

const Badge = ({ children, color = 'gray' }) => (
    <span className={`badge badge-${color}`}><span className="badge-dot" />{children}</span>
);

const PressableRow = ({ icon: Icon, iconColor = 'indigo', title, subtitle, trail, onClick }) => (
    <button className="list-item" onClick={onClick}>
        {Icon && <span className={`list-item-icon ${iconColor}`}><Icon /></span>}
        <span className="list-item-body">
            <span className="list-item-title">{title}</span>
            {subtitle && <span className="list-item-subtitle">{subtitle}</span>}
        </span>
        <span className="list-item-trail">
            {trail || <I.ChevronRight style={{ width: 18, height: 18 }} />}
        </span>
    </button>
);

const useCopy = () => {
    const toast = useToast();
    return useCallback((text, label = 'Copié') => {
        try {
            navigator.clipboard.writeText(text);
            toast.success(label);
        } catch (e) { toast.error('Impossible de copier'); }
    }, [toast]);
};

/* ==================== Login ==================== */
const LoginScreen = () => {
    const { login } = useApp();
    const toast = useToast();
    const [email, setEmail] = useState('');
    const [code, setCode] = useState('');
    const [step, setStep] = useState('email');
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState('');

    useEffect(() => {
        const params = new URLSearchParams(window.location.search);
        const magicEmail = params.get('email');
        const magicCode = params.get('code');
        if (magicEmail && magicCode) {
            window.history.replaceState({}, '', window.location.pathname);
            setLoading(true);
            api.verifyCode(magicEmail, magicCode).then(data => {
                if (data.success && data.token) login(data.user || { email: magicEmail }, data.token);
                else { setEmail(magicEmail); setStep('code'); setError('Lien expiré. Saisissez le code reçu.'); }
            }).finally(() => setLoading(false));
        }
    }, []);

    const sendCode = async (e) => {
        e?.preventDefault();
        if (!email) return;
        setLoading(true); setError('');
        const data = await api.requestCode(email);
        setLoading(false);
        if (data.success) { setStep('code'); toast.info('Code envoyé par email'); }
        else setError(data.error || 'Erreur');
    };
    const verify = async (e) => {
        e?.preventDefault();
        if (code.length < 4) return;
        setLoading(true); setError('');
        const data = await api.verifyCode(email, code);
        setLoading(false);
        if (data.success && data.token) login(data.user || { email }, data.token);
        else setError(data.error || 'Code invalide');
    };

    return (
        <div className="login-screen">
            <div className="login-hero">
                <div className="logo-circle"><I.Logo /></div>
                <h1>Vocal</h1>
                <p>Téléphonie cloud suisse pour vos lignes pros</p>
            </div>
            <div className="login-card">
                {step === 'email' ? (
                    <form onSubmit={sendCode}>
                        <h2>Connexion</h2>
                        <p className="login-subtitle">Recevez un code à 6 chiffres par email. Pas de mot de passe.</p>
                        <div className="input-group">
                            <label className="input-label">Adresse email</label>
                            <input type="email" autoComplete="email" inputMode="email"
                                className="input" placeholder="vous@exemple.com"
                                value={email} onChange={e => setEmail(e.target.value)}
                                autoFocus required />
                        </div>
                        {error && <div className="error-msg">{error}</div>}
                        <button type="submit" className="btn btn-primary btn-block btn-lg" disabled={loading || !email}>
                            {loading ? 'Envoi…' : 'Recevoir le code'}
                        </button>
                    </form>
                ) : (
                    <form onSubmit={verify}>
                        <h2>Code de vérification</h2>
                        <p className="login-subtitle">Code envoyé à <strong>{email}</strong></p>
                        <div className="input-group">
                            <input type="text" inputMode="numeric" pattern="[0-9]*" maxLength="6"
                                className="input code-input" placeholder="000000"
                                value={code} onChange={e => setCode(e.target.value.replace(/\D/g, ''))}
                                autoFocus />
                        </div>
                        {error && <div className="error-msg">{error}</div>}
                        <button type="submit" className="btn btn-primary btn-block btn-lg" disabled={loading || code.length < 4}>
                            {loading ? 'Vérification…' : 'Se connecter'}
                        </button>
                        <button type="button" className="btn btn-ghost btn-block mt-1" onClick={() => { setStep('email'); setCode(''); setError(''); }}>
                            Changer d'email
                        </button>
                    </form>
                )}
                <div className="login-features">
                    <div className="login-feature"><div className="icon">📞</div><div className="title">Lignes IVR & IA</div></div>
                    <div className="login-feature"><div className="icon">💳</div><div className="title">Crédits Stripe</div></div>
                    <div className="login-feature"><div className="icon">📊</div><div className="title">Stats temps réel</div></div>
                    <div className="login-feature"><div className="icon">🔐</div><div className="title">Magic link</div></div>
                </div>
            </div>
        </div>
    );
};

/* ==================== Home (Dashboard) ==================== */
const HomeScreen = () => {
    const { user, push, switchTab } = useApp();
    const toast = useToast();
    const [stats, setStats] = useState(null);
    const [balance, setBalance] = useState(null);
    const [recent, setRecent] = useState([]);
    const [loading, setLoading] = useState(true);
    const [refreshing, setRefreshing] = useState(false);

    const load = useCallback(async (bg = false) => {
        bg ? setRefreshing(true) : setLoading(true);
        try {
            const [s, c, b] = await Promise.all([api.stats(), api.calls(1, 5), api.balance()]);
            setStats(s);
            setBalance(b);
            setRecent(c?.calls || []);
        } catch (e) { toast.error('Erreur de chargement'); }
        finally { setLoading(false); setRefreshing(false); }
    }, []);
    useEffect(() => { load(); }, [load]);

    const greeting = (() => {
        const h = new Date().getHours();
        if (h < 6) return 'Bonsoir'; if (h < 12) return 'Bonjour'; if (h < 18) return 'Bon après-midi'; return 'Bonsoir';
    })();
    const name = user?.name || user?.client?.name || (user?.email ? user.email.split('@')[0] : '');

    const balLevel = balance ? (balance.balance < (balance.critical_threshold || 1) ? 'critical' : balance.balance < (balance.low_threshold || 5) ? 'warning' : 'ok') : 'ok';

    return (
        <div className="screen">
            <TopHeader title="Accueil" right={
                <button className="header-action" onClick={() => load(true)} aria-label="Rafraîchir">
                    <I.Refresh style={{ width: 20, height: 20, animation: refreshing ? 'spin 0.8s linear infinite' : 'none' }} />
                </button>
            } />
            <div className="screen-content">
                <div className="fade-in">
                    <div style={{ marginBottom: '1rem' }}>
                        <div className="text-xs text-muted font-semi" style={{ textTransform: 'uppercase', letterSpacing: '0.04em' }}>{greeting}</div>
                        <div className="text-2xl font-bold" style={{ letterSpacing: '-0.01em' }}>{name || 'Utilisateur'}</div>
                    </div>

                    {loading ? (
                        <div className="wallet-hero"><Skeleton w="40%" h={12} style={{ marginBottom: 12, background: 'rgba(255,255,255,0.3)' }} /><Skeleton w="60%" h={36} style={{ background: 'rgba(255,255,255,0.3)' }} /></div>
                    ) : balance ? (
                        <div className={`wallet-hero ${balLevel === 'warning' ? 'warning' : ''} ${balLevel === 'critical' ? 'critical' : ''}`}>
                            <div className="wallet-label">Solde wallet</div>
                            <div className="wallet-amount tabular">{(balance.balance || 0).toFixed(2)} <span style={{ fontSize: '1.25rem', opacity: 0.85 }}>{balance.currency || 'CHF'}</span></div>
                            {balLevel === 'critical' && <div className="wallet-meta">⚠️ Solde critique - rechargez maintenant</div>}
                            {balLevel === 'warning' && <div className="wallet-meta">Solde faible - pensez à recharger</div>}
                            {balLevel === 'ok' && balance.total_consumed != null && <div className="wallet-meta">Total consommé : {fmtAmount(balance.total_consumed)}</div>}
                            <button className="wallet-cta" onClick={() => switchTab('billing')}>
                                <I.Plus style={{ width: 18, height: 18 }} />
                                Recharger mon compte
                            </button>
                        </div>
                    ) : null}

                    <div className="section-title">Vue d'ensemble</div>
                    {loading ? (
                        <div className="stats-grid">
                            {[0,1,2,3].map(i => <div key={i} className="stat-card"><Skeleton h={38} w={38} r={11} /><Skeleton w="70%" h={10} /><Skeleton w="50%" h={20} /></div>)}
                        </div>
                    ) : (
                        <div className="stats-grid">
                            <button className="stat-card" onClick={() => switchTab('lines')}>
                                <div className="stat-icon green"><I.Phone /></div>
                                <div className="stat-label">Lignes actives</div>
                                <div className="stat-value">{stats?.lines?.active || 0}<span className="text-muted text-sm font-semi"> / {stats?.lines?.total || 0}</span></div>
                            </button>
                            <button className="stat-card" onClick={() => switchTab('activity')}>
                                <div className="stat-icon blue"><I.PhoneIn /></div>
                                <div className="stat-label">Appels ce mois</div>
                                <div className="stat-value">{stats?.calls?.month || 0}</div>
                            </button>
                            <button className="stat-card" onClick={() => switchTab('billing')}>
                                <div className="stat-icon purple"><I.Card /></div>
                                <div className="stat-label">Coût total</div>
                                <div className="stat-value tabular">{(Number(stats?.calls?.total_cost) || 0).toFixed(2)} <span className="text-muted text-sm">CHF</span></div>
                            </button>
                            <button className="stat-card" onClick={() => push('api-keys')}>
                                <div className="stat-icon orange"><I.Key /></div>
                                <div className="stat-label">Clés API</div>
                                <div className="stat-value">{stats?.api_keys?.total || 0}</div>
                            </button>
                        </div>
                    )}

                    <div className="section-title flex justify-between items-center" style={{ paddingRight: 4 }}>
                        <span>Derniers appels</span>
                        <button className="text-xs font-bold text-primary" style={{ textTransform: 'none', letterSpacing: 0 }} onClick={() => switchTab('activity')}>Tout voir</button>
                    </div>
                    {loading ? (
                        <div className="list">
                            {[0,1,2].map(i => <div key={i} className="list-item"><Skeleton w={40} h={40} r={12} /><div style={{flex:1}}><Skeleton w="60%" h={12} style={{marginBottom:6}} /><Skeleton w="40%" h={10} /></div></div>)}
                        </div>
                    ) : recent.length === 0 ? (
                        <div className="card card-padded" style={{ textAlign: 'center', color: 'var(--text-muted)' }}>Aucun appel récent</div>
                    ) : (
                        <div className="list">
                            {recent.slice(0, 5).map(c => <CallRow key={c.id} call={c} />)}
                        </div>
                    )}
                </div>
            </div>
        </div>
    );
};

const CallRow = ({ call, onClick }) => {
    const dir = call.direction === 'outbound' ? 'red' : 'green';
    const Icon = call.direction === 'outbound' ? I.PhoneOut : I.PhoneIn;
    const status = CALL_STATUS[call.status] || { label: call.status, color: 'gray' };
    const phone = call.direction === 'outbound' ? (call.to_number || call.to) : (call.from_number || call.from);
    return (
        <button className="list-item" onClick={onClick}>
            <span className={`list-item-icon ${dir}`}><Icon /></span>
            <span className="list-item-body">
                <span className="list-item-title">{fmtPhone(phone) || 'Numéro inconnu'}</span>
                <span className="list-item-subtitle flex gap-1 items-center">
                    <Badge color={status.color}>{status.label}</Badge>
                    {call.duration > 0 && <span>{fmtDuration(call.duration)}</span>}
                </span>
            </span>
            <span className="list-item-trail">
                <span className="price tabular">{call.cost ? fmtAmount(call.cost) : '-'}</span>
                <span className="when">{fmtRelative(call.start_time || call.created_at)}</span>
            </span>
        </button>
    );
};

/* ==================== Lines ==================== */
const LinesScreen = () => {
    const { push } = useApp();
    const toast = useToast();
    const [lines, setLines] = useState([]);
    const [subs, setSubs] = useState([]);
    const [loading, setLoading] = useState(true);
    const [search, setSearch] = useState('');

    const load = useCallback(async () => {
        setLoading(true);
        try {
            const [l, s] = await Promise.all([api.lines(), api.subscriptions()]);
            setLines(l?.lines || []);
            setSubs(s?.subscriptions || []);
        } catch (e) { toast.error('Erreur'); } finally { setLoading(false); }
    }, []);
    useEffect(() => { load(); }, [load]);

    const filtered = useMemo(() => {
        if (!search) return lines;
        const q = search.toLowerCase();
        return lines.filter(l =>
            (l.name || '').toLowerCase().includes(q) ||
            (l.phone_number || '').toLowerCase().includes(q) ||
            (l.type || '').toLowerCase().includes(q)
        );
    }, [lines, search]);

    return (
        <div className="screen">
            <TopHeader title="Mes lignes" right={
                <button className="header-action" onClick={load}><I.Refresh style={{ width: 20, height: 20 }} /></button>
            } />
            <div className="screen-content">
                <div className="search-wrapper mb-2">
                    <I.Search />
                    <input className="input search-input" placeholder="Rechercher une ligne…" value={search} onChange={e => setSearch(e.target.value)} />
                </div>

                {loading ? (
                    <div className="list">{[0,1,2,3].map(i => <div key={i} className="list-item"><Skeleton w={40} h={40} r={12} /><div style={{flex:1}}><Skeleton w="70%" h={12} style={{marginBottom:6}} /><Skeleton w="50%" h={10} /></div></div>)}</div>
                ) : filtered.length === 0 ? (
                    <EmptyState icon={I.Phone} title="Aucune ligne" message={search ? "Aucun résultat" : "Vos lignes apparaîtront ici"} />
                ) : (
                    <div className="list">
                        {filtered.map(line => {
                            const sub = subs.find(s => s.line_id === line.id);
                            const subActive = sub && (sub.status === 'active' || sub.status === 'trialing');
                            const type = LINE_TYPES[line.type] || { label: line.type, color: 'gray' };
                            return (
                                <button key={line.id} className="list-item" onClick={() => push('line-detail', { lineId: line.id })}>
                                    <span className={`list-item-icon ${line.is_active ? 'green' : 'gray'}`}><I.Phone /></span>
                                    <span className="list-item-body">
                                        <span className="list-item-title">{line.name || fmtPhone(line.phone_number) || 'Sans nom'}</span>
                                        <span className="list-item-subtitle flex gap-1 items-center">
                                            <Badge color={type.color}>{type.label}</Badge>
                                            {!subActive && <Badge color="warning">sans abo</Badge>}
                                        </span>
                                    </span>
                                    <I.ChevronRight style={{ width: 18, height: 18, color: 'var(--text-muted)' }} />
                                </button>
                            );
                        })}
                    </div>
                )}
            </div>
        </div>
    );
};

const LineDetailScreen = ({ params }) => {
    const { push } = useApp();
    const toast = useToast();
    const copy = useCopy();
    const lineId = params?.lineId;
    const [line, setLine] = useState(null);
    const [loading, setLoading] = useState(true);
    const [tab, setTab] = useState('summary');
    const [editing, setEditing] = useState(false);
    const [form, setForm] = useState({});
    const [saving, setSaving] = useState(false);

    const load = useCallback(async () => {
        setLoading(true);
        const d = await api.line(lineId);
        if (d?.success && d.line) {
            setLine(d.line);
            setForm({
                name: d.line.name || '',
                forward_number: d.line.forward_number || '',
                voicemail_email: d.line.voicemail_email || '',
                webhook_url: d.line.webhook_url || '',
                custom_link: d.line.custom_link || '',
            });
        } else if (d?.error) toast.error(d.error);
        setLoading(false);
    }, [lineId]);
    useEffect(() => { load(); }, [load]);

    const save = async () => {
        setSaving(true);
        const r = await api.updateLine(lineId, form);
        setSaving(false);
        if (r?.success) { toast.success('Ligne mise à jour'); setEditing(false); load(); }
        else toast.error(r?.error || 'Erreur');
    };

    if (loading || !line) {
        return (
            <div className="screen">
                <StackHeader title="Ligne" />
                <div className="screen-content"><Skeleton h={120} r={16} style={{ marginBottom: 16 }} /><Skeleton h={300} r={16} /></div>
            </div>
        );
    }

    const type = LINE_TYPES[line.type] || { label: line.type, color: 'gray' };
    const sub = line.subscription;
    const subActive = sub && (sub.status === 'active' || sub.status === 'trialing');

    return (
        <div className="screen">
            <StackHeader title={line.name || 'Ligne'} right={
                tab === 'config' && (
                    editing ? (
                        <button className="header-action" onClick={() => { setEditing(false); load(); }}><I.X style={{ width: 20, height: 20 }} /></button>
                    ) : (
                        <button className="header-action" onClick={() => setEditing(true)}><I.Edit style={{ width: 20, height: 20 }} /></button>
                    )
                )
            } />
            <div className="screen-content">
                <div className="card card-padded-lg fade-in" style={{ marginBottom: '1rem', textAlign: 'center', background: 'var(--gradient-soft)' }}>
                    <Badge color={type.color}>{type.label}</Badge>
                    <div className="phone-large mt-1" style={{ marginTop: 12 }}>{fmtPhone(line.phone_number) || '-'}</div>
                    {line.phone_number && (
                        <button className="copy-btn mt-1" onClick={() => copy(line.phone_number)}>
                            <I.Copy style={{ width: 14, height: 14 }} /> Copier
                        </button>
                    )}
                    <div className="flex justify-between mt-2" style={{ borderTop: '1px solid var(--border)', paddingTop: 12 }}>
                        <div>
                            <div className="text-xs text-muted font-semi">État</div>
                            <Badge color={line.is_active ? 'success' : 'gray'}>{line.is_active ? 'Active' : 'Inactive'}</Badge>
                        </div>
                        <div>
                            <div className="text-xs text-muted font-semi">Abonnement</div>
                            <Badge color={subActive ? 'success' : 'warning'}>{subActive ? 'Actif' : 'Aucun'}</Badge>
                        </div>
                    </div>
                </div>

                <div className="tabs-bar mb-2">
                    <button className={tab === 'summary' ? 'active' : ''} onClick={() => setTab('summary')}>Résumé</button>
                    <button className={tab === 'config' ? 'active' : ''} onClick={() => setTab('config')}>Config</button>
                    <button className={tab === 'sub' ? 'active' : ''} onClick={() => setTab('sub')}>Abonnement</button>
                </div>

                {tab === 'summary' && (
                    <div className="card kv-card fade-in">
                        <div className="detail-row"><span className="label">Type</span><span className="value">{type.label}</span></div>
                        <div className="detail-row"><span className="label">Numéro</span><span className="value tabular">{fmtPhone(line.phone_number) || '-'}</span></div>
                        <div className="detail-row"><span className="label">Nom</span><span className="value">{line.name || '-'}</span></div>
                        {line.forward_number && <div className="detail-row"><span className="label">Renvoi vers</span><span className="value tabular">{fmtPhone(line.forward_number)}</span></div>}
                        {line.voicemail_email && <div className="detail-row"><span className="label">Email vocal</span><span className="value">{line.voicemail_email}</span></div>}
                        {line.webhook_url && <div className="detail-row col"><span className="label">Webhook</span><span className="value text-xs" style={{ wordBreak: 'break-all' }}>{line.webhook_url}</span></div>}
                        <div className="detail-row"><span className="label">Créée le</span><span className="value">{fmtDate(line.created_at)}</span></div>
                    </div>
                )}

                {tab === 'config' && (
                    editing ? (
                        <div className="card card-padded fade-in">
                            <div className="input-group">
                                <label className="input-label">Nom de la ligne</label>
                                <input className="input" value={form.name} onChange={e => setForm({ ...form, name: e.target.value })} />
                            </div>
                            {(line.type === 'forward' || form.forward_number) && (
                                <div className="input-group">
                                    <label className="input-label">Numéro de renvoi</label>
                                    <input className="input" inputMode="tel" value={form.forward_number} onChange={e => setForm({ ...form, forward_number: e.target.value })} />
                                </div>
                            )}
                            {(line.type === 'voicemail' || form.voicemail_email) && (
                                <div className="input-group">
                                    <label className="input-label">Email pour messages vocaux</label>
                                    <input className="input" type="email" value={form.voicemail_email} onChange={e => setForm({ ...form, voicemail_email: e.target.value })} />
                                </div>
                            )}
                            {(line.type === 'webhook' || form.webhook_url) && (
                                <div className="input-group">
                                    <label className="input-label">URL du webhook</label>
                                    <input className="input" type="url" value={form.webhook_url} onChange={e => setForm({ ...form, webhook_url: e.target.value })} />
                                </div>
                            )}
                            {(line.type === 'link' || form.custom_link) && (
                                <div className="input-group">
                                    <label className="input-label">Lien personnalisé</label>
                                    <input className="input" value={form.custom_link} onChange={e => setForm({ ...form, custom_link: e.target.value })} />
                                </div>
                            )}
                            <button className="btn btn-primary btn-block btn-lg" onClick={save} disabled={saving}>
                                {saving ? 'Enregistrement…' : 'Enregistrer'}
                            </button>
                        </div>
                    ) : (
                        <div className="card kv-card fade-in">
                            <div className="detail-row"><span className="label">Nom</span><span className="value">{line.name || '-'}</span></div>
                            <div className="detail-row"><span className="label">Numéro de renvoi</span><span className="value tabular">{fmtPhone(line.forward_number) || '-'}</span></div>
                            <div className="detail-row"><span className="label">Email messagerie</span><span className="value">{line.voicemail_email || '-'}</span></div>
                            <div className="detail-row col"><span className="label">URL webhook</span><span className="value text-xs" style={{ wordBreak: 'break-all' }}>{line.webhook_url || '-'}</span></div>
                            <div className="detail-row col"><span className="label">Lien personnalisé</span><span className="value text-xs" style={{ wordBreak: 'break-all' }}>{line.custom_link || '-'}</span></div>
                            <div style={{ padding: '0.75rem 1rem' }}>
                                <button className="btn btn-secondary btn-block" onClick={() => setEditing(true)}>
                                    <I.Edit style={{ width: 18, height: 18 }} /> Modifier
                                </button>
                            </div>
                        </div>
                    )
                )}

                {tab === 'sub' && <SubscriptionPanel line={line} sub={sub} reload={load} />}
            </div>
        </div>
    );
};

const SubscriptionPanel = ({ line, sub, reload }) => {
    const toast = useToast();
    const [busy, setBusy] = useState(false);
    const subActive = sub && (sub.status === 'active' || sub.status === 'trialing');

    const subscribe = async (period) => {
        setBusy(true);
        const r = await api.subscribe(line.id, period);
        setBusy(false);
        if (r?.success && r.url) window.location.href = r.url;
        else toast.error(r?.error || 'Erreur');
    };
    const cancel = async () => {
        if (!confirm('Annuler cet abonnement à la fin de la période en cours ?')) return;
        setBusy(true);
        const r = await api.cancelSub(sub.id);
        setBusy(false);
        if (r?.success) { toast.success('Annulé'); reload(); }
        else toast.error(r?.error || 'Erreur');
    };
    const reactivate = async () => {
        setBusy(true);
        const r = await api.reactivateSub(sub.id);
        setBusy(false);
        if (r?.success) { toast.success('Réactivé'); reload(); }
        else toast.error(r?.error || 'Erreur');
    };

    if (!subActive) {
        return (
            <div className="card card-padded fade-in">
                <div className="text-center" style={{ textAlign: 'center', padding: '0.5rem 0 1rem' }}>
                    <div className="list-item-icon amber" style={{ margin: '0 auto', width: 48, height: 48 }}><I.Alert /></div>
                    <h3 style={{ margin: '12px 0 4px', fontSize: '1rem', fontWeight: 700 }}>Aucun abonnement actif</h3>
                    <p className="text-sm text-muted">Activez un abonnement pour utiliser cette ligne</p>
                </div>
                <button className="btn btn-primary btn-block btn-lg mb-1" onClick={() => subscribe('monthly')} disabled={busy}>
                    Mensuel - {SUB_PRICE_MONTHLY} CHF/mois
                </button>
                <button className="btn btn-secondary btn-block" onClick={() => subscribe('yearly')} disabled={busy}>
                    Annuel - {SUB_PRICE_YEARLY} CHF/an <span className="badge badge-success" style={{ marginLeft: 8 }}>2 mois offerts</span>
                </button>
            </div>
        );
    }

    return (
        <div className="card kv-card fade-in">
            <div className="detail-row"><span className="label">Statut</span><Badge color={sub.cancel_at_period_end ? 'warning' : 'success'}>{sub.cancel_at_period_end ? 'Se termine bientôt' : 'Actif'}</Badge></div>
            <div className="detail-row"><span className="label">Formule</span><span className="value">{sub.billing_period === 'yearly' ? `Annuel - ${SUB_PRICE_YEARLY} CHF/an` : `Mensuel - ${SUB_PRICE_MONTHLY} CHF/mois`}</span></div>
            {sub.current_period_end && <div className="detail-row"><span className="label">{sub.cancel_at_period_end ? 'Fin' : 'Prochaine échéance'}</span><span className="value">{fmtDate(sub.current_period_end)}</span></div>}
            <div style={{ padding: '0.75rem 1rem' }}>
                {sub.cancel_at_period_end ? (
                    <button className="btn btn-primary btn-block" onClick={reactivate} disabled={busy}>Réactiver l'abonnement</button>
                ) : (
                    <button className="btn btn-secondary btn-block" onClick={cancel} disabled={busy} style={{ color: 'var(--danger)' }}>Annuler l'abonnement</button>
                )}
            </div>
        </div>
    );
};

/* ==================== Activity (Calls + SMS) ==================== */
const ActivityScreen = () => {
    const [tab, setTab] = useState('calls');
    return (
        <div className="screen">
            <TopHeader title="Activité" left />
            <div style={{ padding: '0.75rem 1rem 0' }}>
                <div className="segmented">
                    <button className={tab === 'calls' ? 'active' : ''} onClick={() => setTab('calls')}>Appels</button>
                    <button className={tab === 'sms' ? 'active' : ''} onClick={() => setTab('sms')}>SMS</button>
                    <button className={tab === 'whatsapp' ? 'active' : ''} onClick={() => setTab('whatsapp')}>WhatsApp</button>
                </div>
            </div>
            <div className="screen-content" style={{ paddingTop: 0 }}>
                {tab === 'calls' && <CallsList />}
                {tab === 'sms' && <MessagesList type="sms" />}
                {tab === 'whatsapp' && <MessagesList type="whatsapp" />}
            </div>
        </div>
    );
};

const CallsList = () => {
    const { push } = useApp();
    const toast = useToast();
    const [calls, setCalls] = useState([]);
    const [loading, setLoading] = useState(true);
    const [page, setPage] = useState(1);
    const [hasMore, setHasMore] = useState(false);

    const load = useCallback(async (p = 1, append = false) => {
        if (!append) setLoading(true);
        const d = await api.calls(p, 30);
        if (d?.calls) {
            setCalls(prev => append ? [...prev, ...d.calls] : d.calls);
            setHasMore((d.calls?.length || 0) === 30);
        } else { toast.error('Erreur'); }
        setLoading(false);
    }, []);
    useEffect(() => { load(1, false); }, [load]);

    if (loading) return <div className="list">{[0,1,2,3,4].map(i => <div key={i} className="list-item"><Skeleton w={40} h={40} r={12} /><div style={{flex:1}}><Skeleton w="65%" h={12} style={{marginBottom:6}} /><Skeleton w="40%" h={10} /></div></div>)}</div>;
    if (!calls.length) return <EmptyState icon={I.PhoneIn} title="Aucun appel" message="Vos appels apparaîtront ici" />;
    return (
        <div className="list fade-in">
            {calls.map(c => <CallRow key={c.id} call={c} onClick={() => push('call-detail', { call: c })} />)}
            {hasMore && (
                <button className="btn btn-secondary btn-block mt-2" onClick={() => { const np = page + 1; setPage(np); load(np, true); }}>
                    Charger plus
                </button>
            )}
        </div>
    );
};

const MessagesList = ({ type }) => {
    const { push } = useApp();
    const toast = useToast();
    const [items, setItems] = useState([]);
    const [loading, setLoading] = useState(true);
    const [page, setPage] = useState(1);
    const [hasMore, setHasMore] = useState(false);

    const load = useCallback(async (p = 1, append = false) => {
        if (!append) setLoading(true);
        const d = type === 'sms' ? await api.sms(p, 30) : await api.whatsapp(p, 30);
        const list = d?.messages || d?.sms || d?.whatsapp || d?.items || [];
        setItems(prev => append ? [...prev, ...list] : list);
        setHasMore(list.length === 30);
        setLoading(false);
    }, [type]);
    useEffect(() => { load(1, false); }, [load]);

    if (loading) return <div className="list">{[0,1,2].map(i => <div key={i} className="list-item"><Skeleton w={40} h={40} r={12} /><div style={{flex:1}}><Skeleton w="65%" h={12} style={{marginBottom:6}} /><Skeleton w="80%" h={10} /></div></div>)}</div>;
    if (!items.length) return <EmptyState icon={type === 'sms' ? I.Send : I.Chat} title={type === 'sms' ? 'Aucun SMS' : 'Aucun message WhatsApp'} message="Aucun message à afficher" />;
    return (
        <div className="list fade-in">
            {items.map(m => (
                <button key={m.id} className="list-item" onClick={() => push('message-detail', { message: m, type })}>
                    <span className="list-item-icon purple">{type === 'sms' ? <I.Send /> : <I.Chat />}</span>
                    <span className="list-item-body">
                        <span className="list-item-title">{fmtPhone(m.to_number || m.to) || '-'}</span>
                        <span className="list-item-subtitle">{m.body || m.message || '(sans contenu)'}</span>
                    </span>
                    <span className="list-item-trail">
                        <span className="price tabular">{m.cost ? fmtAmount(m.cost) : '-'}</span>
                        <span className="when">{fmtRelative(m.created_at || m.sent_at)}</span>
                    </span>
                </button>
            ))}
            {hasMore && <button className="btn btn-secondary btn-block mt-2" onClick={() => { const np = page + 1; setPage(np); load(np, true); }}>Charger plus</button>}
        </div>
    );
};

const CallDetailScreen = ({ params }) => {
    const c = params?.call || {};
    const status = CALL_STATUS[c.status] || { label: c.status, color: 'gray' };
    const phone = c.direction === 'outbound' ? (c.to_number || c.to) : (c.from_number || c.from);
    return (
        <div className="screen">
            <StackHeader title="Détail appel" />
            <div className="screen-content">
                <div className="card card-padded-lg" style={{ textAlign: 'center', background: 'var(--gradient-soft)', marginBottom: '1rem' }}>
                    <div className={`list-item-icon ${c.direction === 'outbound' ? 'red' : 'green'}`} style={{ margin: '0 auto', width: 56, height: 56 }}>
                        {c.direction === 'outbound' ? <I.PhoneOut /> : <I.PhoneIn />}
                    </div>
                    <div className="phone-large mt-1">{fmtPhone(phone)}</div>
                    <Badge color={status.color}>{status.label}</Badge>
                </div>
                <div className="card kv-card">
                    <div className="detail-row"><span className="label">Direction</span><span className="value">{c.direction === 'outbound' ? 'Sortant' : 'Entrant'}</span></div>
                    <div className="detail-row"><span className="label">De</span><span className="value tabular">{fmtPhone(c.from_number || c.from) || '-'}</span></div>
                    <div className="detail-row"><span className="label">Vers</span><span className="value tabular">{fmtPhone(c.to_number || c.to) || '-'}</span></div>
                    <div className="detail-row"><span className="label">Durée</span><span className="value">{fmtDuration(c.duration)}</span></div>
                    <div className="detail-row"><span className="label">Coût</span><span className="value tabular">{fmtAmount(c.cost)}</span></div>
                    <div className="detail-row"><span className="label">Date</span><span className="value">{fmtDateTime(c.start_time || c.created_at)}</span></div>
                    {c.line_name && <div className="detail-row"><span className="label">Ligne</span><span className="value">{c.line_name}</span></div>}
                </div>
            </div>
        </div>
    );
};

const MessageDetailScreen = ({ params }) => {
    const m = params?.message || {};
    const isWA = params?.type === 'whatsapp';
    return (
        <div className="screen">
            <StackHeader title={isWA ? 'Message WhatsApp' : 'SMS'} />
            <div className="screen-content">
                <div className="card kv-card mb-2">
                    <div className="detail-row"><span className="label">De</span><span className="value tabular">{fmtPhone(m.from_number || m.from) || '-'}</span></div>
                    <div className="detail-row"><span className="label">Vers</span><span className="value tabular">{fmtPhone(m.to_number || m.to) || '-'}</span></div>
                    <div className="detail-row"><span className="label">Statut</span><Badge color="info">{m.status || 'envoyé'}</Badge></div>
                    <div className="detail-row"><span className="label">Coût</span><span className="value tabular">{fmtAmount(m.cost)}</span></div>
                    <div className="detail-row"><span className="label">Date</span><span className="value">{fmtDateTime(m.created_at || m.sent_at)}</span></div>
                </div>
                <div className="section-title">Contenu</div>
                <div className="card card-padded">
                    <p style={{ margin: 0, whiteSpace: 'pre-wrap' }}>{m.body || m.message || '(vide)'}</p>
                </div>
            </div>
        </div>
    );
};

/* ==================== Billing ==================== */
const BillingScreen = () => {
    const { push } = useApp();
    const toast = useToast();
    const [balance, setBalance] = useState(null);
    const [tx, setTx] = useState([]);
    const [recharges, setRecharges] = useState([]);
    const [loading, setLoading] = useState(true);
    const [tab, setTab] = useState('overview');
    const [sheetOpen, setSheetOpen] = useState(false);
    const [customAmount, setCustomAmount] = useState('');
    const [busy, setBusy] = useState(false);

    const load = useCallback(async () => {
        setLoading(true);
        const [b, t, r] = await Promise.all([api.balance(), api.transactions(50), api.recharges()]);
        setBalance(b);
        setTx(t?.transactions || []);
        setRecharges(r?.recharges || []);
        setLoading(false);
    }, []);
    useEffect(() => { load(); }, [load]);

    const recharge = async (amount) => {
        if (!amount || amount < 5) { toast.error('Min. 5 CHF'); return; }
        if (amount > 1000) { toast.error('Max. 1000 CHF'); return; }
        setBusy(true);
        const r = await api.createRecharge({ amount: Number(amount) });
        setBusy(false);
        if (r?.success && r.url) window.location.href = r.url;
        else toast.error(r?.error || 'Erreur');
    };

    const balLevel = balance ? (balance.balance < (balance.critical_threshold || 1) ? 'critical' : balance.balance < (balance.low_threshold || 5) ? 'warning' : 'ok') : 'ok';

    return (
        <div className="screen">
            <TopHeader title="Crédits & Facturation" />
            <div className="screen-content">
                {loading ? (
                    <Skeleton h={150} r={20} />
                ) : balance && (
                    <div className={`wallet-hero ${balLevel === 'warning' ? 'warning' : ''} ${balLevel === 'critical' ? 'critical' : ''} fade-in`}>
                        <div className="wallet-label">Solde disponible</div>
                        <div className="wallet-amount tabular">{(balance.balance || 0).toFixed(2)} <span style={{ fontSize: '1.25rem', opacity: 0.85 }}>{balance.currency || 'CHF'}</span></div>
                        <div className="wallet-meta">Total rechargé : {fmtAmount(balance.total_recharged)} - Consommé : {fmtAmount(balance.total_consumed)}</div>
                        <button className="wallet-cta" onClick={() => setSheetOpen(true)}>
                            <I.Plus style={{ width: 18, height: 18 }} /> Recharger
                        </button>
                    </div>
                )}

                <div className="segmented mt-2">
                    <button className={tab === 'overview' ? 'active' : ''} onClick={() => setTab('overview')}>Recharges</button>
                    <button className={tab === 'tx' ? 'active' : ''} onClick={() => setTab('tx')}>Transactions</button>
                </div>

                {tab === 'overview' && (
                    <div className="fade-in">
                        <div className="section-title">Recharges Stripe</div>
                        {recharges.length === 0 ? (
                            <div className="card card-padded text-center text-muted">Aucune recharge pour le moment</div>
                        ) : (
                            <div className="list">
                                {recharges.map(r => (
                                    <div key={r.id} className="list-item">
                                        <span className={`list-item-icon ${r.status === 'completed' ? 'green' : r.status === 'pending' ? 'amber' : 'gray'}`}><I.Card /></span>
                                        <span className="list-item-body">
                                            <span className="list-item-title">Recharge {fmtAmount(r.amount, r.currency || 'CHF')}</span>
                                            <span className="list-item-subtitle"><Badge color={r.status === 'completed' ? 'success' : r.status === 'pending' ? 'warning' : 'gray'}>{r.status}</Badge></span>
                                        </span>
                                        <span className="list-item-trail">
                                            <span className="when">{fmtDate(r.created_at)}</span>
                                        </span>
                                    </div>
                                ))}
                            </div>
                        )}
                    </div>
                )}

                {tab === 'tx' && (
                    <div className="fade-in">
                        <div className="section-title">Mouvements récents</div>
                        {tx.length === 0 ? (
                            <div className="card card-padded text-center text-muted">Aucune transaction</div>
                        ) : (
                            <div className="list">
                                {tx.map(t => {
                                    const credit = (t.type || '').includes('credit') || (t.type || '').includes('recharge') || Number(t.amount) > 0;
                                    return (
                                        <div key={t.id} className="list-item">
                                            <span className={`list-item-icon ${credit ? 'green' : 'red'}`}>{credit ? <I.ArrowDown /> : <I.ArrowUp />}</span>
                                            <span className="list-item-body">
                                                <span className="list-item-title">{t.description || (credit ? 'Crédit' : 'Débit')}</span>
                                                <span className="list-item-subtitle">{fmtRelative(t.created_at)}</span>
                                            </span>
                                            <span className="list-item-trail">
                                                <span className="price tabular" style={{ color: credit ? 'var(--success)' : 'var(--danger)' }}>
                                                    {credit ? '+' : '-'}{Math.abs(Number(t.amount) || 0).toFixed(2)} {t.currency || 'CHF'}
                                                </span>
                                                <span className="when tabular">Solde : {Number(t.balance_after || 0).toFixed(2)}</span>
                                            </span>
                                        </div>
                                    );
                                })}
                            </div>
                        )}
                    </div>
                )}

                <div className="card card-padded mt-2" style={{ background: 'var(--gradient-soft)', borderColor: '#c7d2fe' }}>
                    <div className="flex items-center gap-2 mb-1"><I.Card style={{ width: 18, height: 18, color: 'var(--primary)' }} /><strong>Abonnements de lignes</strong></div>
                    <p className="text-sm text-muted mb-2" style={{ margin: 0, marginBottom: 12 }}>Gérez les abonnements mensuels et annuels de chacune de vos lignes.</p>
                    <button className="btn btn-secondary btn-block" onClick={() => push('subscriptions')}>
                        Voir mes abonnements <I.ChevronRight style={{ width: 18, height: 18 }} />
                    </button>
                </div>
            </div>

            <Sheet open={sheetOpen} onClose={() => setSheetOpen(false)} title="Recharger mon compte">
                <p className="text-sm text-muted mb-2">Choisissez un montant ou saisissez le vôtre. Min. 5 CHF - Max. 1000 CHF.</p>
                <div className="pack-grid mb-2">
                    {RECHARGE_PACKS.map(p => (
                        <button key={p.amount} className={`pack-card ${p.popular ? 'popular' : ''}`} onClick={() => recharge(p.amount)} disabled={busy}>
                            {p.popular && <span className="pack-popular">★</span>}
                            <div className="pack-amount">{p.amount}</div>
                            <div className="pack-currency">CHF</div>
                            {p.bonus > 0 && <div className="pack-bonus">+{p.bonus} CHF offerts</div>}
                        </button>
                    ))}
                </div>
                <div className="input-group">
                    <label className="input-label">Montant personnalisé (CHF)</label>
                    <div className="flex gap-1">
                        <input className="input flex-1" type="number" inputMode="decimal" min="5" max="1000" value={customAmount} onChange={e => setCustomAmount(e.target.value)} placeholder="Ex. 75" />
                        <button className="btn btn-primary" onClick={() => { recharge(customAmount); setCustomAmount(''); }} disabled={busy || !customAmount}>Payer</button>
                    </div>
                </div>
                <p className="text-xs text-muted text-center mt-1">Paiement sécurisé Stripe</p>
            </Sheet>
        </div>
    );
};

/* ==================== Subscriptions ==================== */
const SubscriptionsScreen = () => {
    const { push } = useApp();
    const toast = useToast();
    const [lines, setLines] = useState([]);
    const [subs, setSubs] = useState([]);
    const [loading, setLoading] = useState(true);

    const load = useCallback(async () => {
        setLoading(true);
        const [l, s] = await Promise.all([api.lines(), api.subscriptions()]);
        setLines(l?.lines || []);
        setSubs(s?.subscriptions || []);
        setLoading(false);
    }, []);
    useEffect(() => { load(); }, [load]);

    const linesWithSub = useMemo(() => {
        return (lines || []).map(l => {
            const sub = subs.find(s => s.line_id === l.id);
            return { ...l, sub, subActive: sub && (sub.status === 'active' || sub.status === 'trialing') };
        });
    }, [lines, subs]);

    const active = linesWithSub.filter(l => l.subActive);
    const inactive = linesWithSub.filter(l => !l.subActive);

    if (loading) return (
        <div className="screen">
            <StackHeader title="Mes abonnements" />
            <div className="screen-content"><Skeleton h={200} r={16} style={{ marginBottom: 12 }} /><Skeleton h={200} r={16} /></div>
        </div>
    );

    return (
        <div className="screen">
            <StackHeader title="Mes abonnements" />
            <div className="screen-content">
                <div className="stats-grid mb-2">
                    <div className="stat-card" style={{ pointerEvents: 'none' }}>
                        <div className="stat-icon green"><I.Check /></div>
                        <div className="stat-label">Actifs</div>
                        <div className="stat-value">{active.length}</div>
                    </div>
                    <div className="stat-card" style={{ pointerEvents: 'none' }}>
                        <div className="stat-icon amber"><I.Alert /></div>
                        <div className="stat-label">Inactifs</div>
                        <div className="stat-value">{inactive.length}</div>
                    </div>
                </div>

                {active.length > 0 && (
                    <>
                        <div className="section-title">Abonnements actifs</div>
                        <div className="list">
                            {active.map(l => (
                                <button key={l.id} className="list-item" onClick={() => push('line-detail', { lineId: l.id })}>
                                    <span className="list-item-icon green"><I.Phone /></span>
                                    <span className="list-item-body">
                                        <span className="list-item-title">{l.name || fmtPhone(l.phone_number) || 'Ligne'}</span>
                                        <span className="list-item-subtitle">{l.sub.billing_period === 'yearly' ? `Annuel - ${SUB_PRICE_YEARLY} CHF/an` : `Mensuel - ${SUB_PRICE_MONTHLY} CHF/mois`}</span>
                                    </span>
                                    <span className="list-item-trail">
                                        <Badge color={l.sub.cancel_at_period_end ? 'warning' : 'success'}>{l.sub.cancel_at_period_end ? 'Se termine' : 'Actif'}</Badge>
                                    </span>
                                </button>
                            ))}
                        </div>
                    </>
                )}

                {inactive.length > 0 && (
                    <>
                        <div className="section-title mt-2">Sans abonnement</div>
                        <div className="list">
                            {inactive.map(l => (
                                <button key={l.id} className="list-item" onClick={() => push('line-detail', { lineId: l.id })}>
                                    <span className="list-item-icon gray"><I.Phone /></span>
                                    <span className="list-item-body">
                                        <span className="list-item-title">{l.name || fmtPhone(l.phone_number) || 'Ligne'}</span>
                                        <span className="list-item-subtitle">Aucun abonnement actif</span>
                                    </span>
                                    <I.ChevronRight style={{ width: 18, height: 18, color: 'var(--text-muted)' }} />
                                </button>
                            ))}
                        </div>
                    </>
                )}

                {linesWithSub.length === 0 && <EmptyState icon={I.Card} title="Aucune ligne" message="Ajoutez d'abord une ligne pour gérer son abonnement" />}
            </div>
        </div>
    );
};

/* ==================== More menu ==================== */
const MoreScreen = () => {
    const { user, logout, push } = useApp();
    return (
        <div className="screen">
            <TopHeader title="Plus" left />
            <div className="screen-content">
                <div className="card card-padded-lg flex items-center gap-3 mb-2" style={{ background: 'var(--gradient-soft)' }}>
                    <div style={{ width: 56, height: 56, borderRadius: '50%', background: 'var(--gradient-primary)', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', fontWeight: 700, fontSize: '1.5rem' }}>
                        {(user?.name || user?.email || 'U')[0].toUpperCase()}
                    </div>
                    <div className="flex-1 truncate">
                        <div className="font-bold truncate">{user?.name || user?.client?.name || 'Mon compte'}</div>
                        <div className="text-sm text-muted truncate">{user?.email}</div>
                    </div>
                </div>

                <div className="section-title">Compte</div>
                <div className="list">
                    <PressableRow icon={I.User} iconColor="indigo" title="Profil" subtitle="Vos informations personnelles" onClick={() => push('settings')} />
                    <PressableRow icon={I.Card} iconColor="purple" title="Mes abonnements" subtitle="Gestion des lignes payantes" onClick={() => push('subscriptions')} />
                </div>

                <div className="section-title">Outils</div>
                <div className="list">
                    <PressableRow icon={I.Key} iconColor="orange" title="Clés API" subtitle="Intégrations tierces" onClick={() => push('api-keys')} />
                    <PressableRow icon={I.Chat} iconColor="green" title="WhatsApp" subtitle="Messages WhatsApp Business" onClick={() => push('whatsapp')} />
                </div>

                <div className="section-title">Aide</div>
                <div className="list">
                    <PressableRow icon={I.Mail} iconColor="blue" title="Support" subtitle="support@helvia.app" onClick={() => window.location.href = 'mailto:support@helvia.app'} />
                    <PressableRow icon={I.Globe} iconColor="gray" title="Site web" subtitle="helvia.app" onClick={() => window.open('https://helvia.app', '_blank')} />
                </div>

                <button className="btn btn-secondary btn-block mt-3" onClick={logout} style={{ color: 'var(--danger)' }}>
                    <I.Logout style={{ width: 18, height: 18 }} /> Se déconnecter
                </button>
                <p className="text-xs text-muted text-center mt-2">Vocal v2 - Téléphonie cloud suisse</p>
            </div>
        </div>
    );
};

/* ==================== Settings (Profile) ==================== */
const SettingsScreen = () => {
    const { user, refreshProfile } = useApp();
    const toast = useToast();
    const [form, setForm] = useState({ name: '', phone: '', company: '' });
    const [loading, setLoading] = useState(true);
    const [saving, setSaving] = useState(false);

    useEffect(() => {
        (async () => {
            const d = await api.profile();
            if (d?.success && d.profile) setForm({ name: d.profile.name || '', phone: d.profile.phone || '', company: d.profile.company || '' });
            else if (user) setForm({ name: user.name || '', phone: user.phone || '', company: user.client?.name || '' });
            setLoading(false);
        })();
    }, []);

    const save = async () => {
        setSaving(true);
        const r = await api.updateProfile(form);
        setSaving(false);
        if (r?.success) { toast.success('Profil mis à jour'); refreshProfile(); }
        else toast.error(r?.error || 'Erreur');
    };

    return (
        <div className="screen">
            <StackHeader title="Mon profil" />
            <div className="screen-content">
                {loading ? <Skeleton h={300} r={16} /> : (
                    <div className="card card-padded fade-in">
                        <div className="input-group">
                            <label className="input-label">Email</label>
                            <input className="input" value={user?.email || ''} disabled style={{ background: 'var(--surface-2)', color: 'var(--text-muted)' }} />
                        </div>
                        <div className="input-group">
                            <label className="input-label">Nom complet</label>
                            <input className="input" value={form.name} onChange={e => setForm({ ...form, name: e.target.value })} />
                        </div>
                        <div className="input-group">
                            <label className="input-label">Téléphone</label>
                            <input className="input" type="tel" inputMode="tel" value={form.phone} onChange={e => setForm({ ...form, phone: e.target.value })} />
                        </div>
                        <div className="input-group">
                            <label className="input-label">Société</label>
                            <input className="input" value={form.company} onChange={e => setForm({ ...form, company: e.target.value })} />
                        </div>
                        <button className="btn btn-primary btn-block btn-lg" onClick={save} disabled={saving}>
                            {saving ? 'Enregistrement…' : 'Enregistrer'}
                        </button>
                    </div>
                )}
            </div>
        </div>
    );
};

/* ==================== API Keys ==================== */
const ApiKeysScreen = () => {
    const toast = useToast();
    const copy = useCopy();
    const [keys, setKeys] = useState([]);
    const [lines, setLines] = useState([]);
    const [loading, setLoading] = useState(true);
    const [sheetOpen, setSheetOpen] = useState(false);
    const [newLabel, setNewLabel] = useState('');
    const [newLineIds, setNewLineIds] = useState([]);
    const [newKey, setNewKey] = useState(null);
    const [revealId, setRevealId] = useState(null);

    const load = useCallback(async () => {
        setLoading(true);
        const [k, l] = await Promise.all([api.apiKeys(), api.lines()]);
        setKeys(k?.api_keys || k?.keys || []);
        setLines(l?.lines || []);
        setLoading(false);
    }, []);
    useEffect(() => { load(); }, [load]);

    const create = async () => {
        if (!newLabel) { toast.error('Nom requis'); return; }
        const r = await api.createApiKey(newLabel, newLineIds);
        if (r?.success) { setNewKey(r.api_key || r.key); setNewLabel(''); setNewLineIds([]); load(); }
        else toast.error(r?.error || 'Erreur');
    };
    const toggle = async (k) => {
        const r = await api.updateApiKey(k.id, { is_active: k.is_active ? 0 : 1 });
        if (r?.success) { toast.success('Mis à jour'); load(); }
    };
    const remove = async (k) => {
        if (!confirm(`Supprimer la clé "${k.label}" ?`)) return;
        const r = await api.deleteApiKey(k.id);
        if (r?.success) { toast.success('Supprimée'); load(); }
    };

    return (
        <div className="screen">
            <StackHeader title="Clés API" right={
                <button className="header-action" onClick={() => { setSheetOpen(true); setNewKey(null); }}><I.Plus style={{ width: 22, height: 22 }} /></button>
            } />
            <div className="screen-content">
                {loading ? <div className="list">{[0,1].map(i => <div key={i} className="list-item"><Skeleton w={40} h={40} r={12} /><div style={{flex:1}}><Skeleton w="60%" h={12} style={{marginBottom:6}} /><Skeleton w="80%" h={10} /></div></div>)}</div>
                : keys.length === 0 ? <EmptyState icon={I.Key} title="Aucune clé API" message="Créez une clé pour intégrer Vocal à vos outils" action={<button className="btn btn-primary mt-2" onClick={() => setSheetOpen(true)}><I.Plus style={{ width: 18, height: 18 }} /> Créer une clé</button>} />
                : (
                    <div className="list">
                        {keys.map(k => (
                            <div key={k.id} className="card card-padded">
                                <div className="flex items-center gap-2 mb-1">
                                    <div className={`list-item-icon ${k.is_active ? 'orange' : 'gray'}`}><I.Key /></div>
                                    <div className="flex-1 truncate">
                                        <div className="font-bold truncate">{k.label}</div>
                                        <div className="text-xs text-muted">{k.line_ids?.length || 0} ligne(s) - {fmtDate(k.created_at)}</div>
                                    </div>
                                    <Badge color={k.is_active ? 'success' : 'gray'}>{k.is_active ? 'Active' : 'Inactive'}</Badge>
                                </div>
                                {k.key && (
                                    <div className="flex items-center gap-1 mb-1" style={{ background: 'var(--surface-2)', padding: '0.5rem 0.75rem', borderRadius: 8 }}>
                                        <code className="text-xs flex-1 truncate tabular">{revealId === k.id ? k.key : k.key.slice(0, 12) + '••••••••'}</code>
                                        <button className="copy-btn" onClick={() => setRevealId(revealId === k.id ? null : k.id)}>{revealId === k.id ? <I.EyeOff style={{ width: 14, height: 14 }} /> : <I.Eye style={{ width: 14, height: 14 }} />}</button>
                                        <button className="copy-btn" onClick={() => copy(k.key)}><I.Copy style={{ width: 14, height: 14 }} /></button>
                                    </div>
                                )}
                                <div className="flex gap-1">
                                    <button className="btn btn-secondary btn-sm flex-1" onClick={() => toggle(k)}>{k.is_active ? 'Désactiver' : 'Activer'}</button>
                                    <button className="btn btn-secondary btn-sm" onClick={() => remove(k)} style={{ color: 'var(--danger)' }}><I.Trash style={{ width: 16, height: 16 }} /></button>
                                </div>
                            </div>
                        ))}
                    </div>
                )}
            </div>

            <Sheet open={sheetOpen} onClose={() => { setSheetOpen(false); setNewKey(null); }} title={newKey ? 'Clé créée' : 'Nouvelle clé API'}>
                {newKey ? (
                    <div>
                        <div className="success-msg">Clé créée. Conservez-la précieusement, elle ne sera plus affichée en entier.</div>
                        <div style={{ background: 'var(--surface-2)', padding: '0.75rem', borderRadius: 8, fontFamily: 'monospace', fontSize: '0.8125rem', wordBreak: 'break-all', marginBottom: 12 }}>{newKey.key || newKey}</div>
                        <button className="btn btn-primary btn-block" onClick={() => { copy(newKey.key || newKey, 'Clé copiée'); setSheetOpen(false); setNewKey(null); }}>
                            <I.Copy style={{ width: 16, height: 16 }} /> Copier et fermer
                        </button>
                    </div>
                ) : (
                    <div>
                        <div className="input-group">
                            <label className="input-label">Nom de la clé</label>
                            <input className="input" value={newLabel} onChange={e => setNewLabel(e.target.value)} placeholder="Ex. Intégration CRM" />
                        </div>
                        <div className="input-group">
                            <label className="input-label">Lignes accessibles</label>
                            <div className="list" style={{ maxHeight: 220, overflowY: 'auto' }}>
                                {lines.map(l => (
                                    <label key={l.id} className="list-item" style={{ cursor: 'pointer' }}>
                                        <input type="checkbox" checked={newLineIds.includes(l.id)} onChange={e => {
                                            setNewLineIds(prev => e.target.checked ? [...prev, l.id] : prev.filter(x => x !== l.id));
                                        }} style={{ marginRight: 8 }} />
                                        <span className="list-item-body">
                                            <span className="list-item-title">{l.name || fmtPhone(l.phone_number)}</span>
                                        </span>
                                    </label>
                                ))}
                            </div>
                        </div>
                        <button className="btn btn-primary btn-block btn-lg" onClick={create}>Créer la clé</button>
                    </div>
                )}
            </Sheet>
        </div>
    );
};

/* ==================== WhatsApp ==================== */
const WhatsAppScreen = () => (
    <div className="screen">
        <StackHeader title="WhatsApp" />
        <div className="screen-content">
            <MessagesList type="whatsapp" />
        </div>
    </div>
);

/* ==================== Stack Renderer ==================== */
const renderStackScreen = ({ screen, params }) => {
    switch (screen) {
        case 'line-detail': return <LineDetailScreen params={params} />;
        case 'call-detail': return <CallDetailScreen params={params} />;
        case 'message-detail': return <MessageDetailScreen params={params} />;
        case 'subscriptions': return <SubscriptionsScreen />;
        case 'api-keys': return <ApiKeysScreen />;
        case 'settings': return <SettingsScreen />;
        case 'whatsapp': return <WhatsAppScreen />;
        default: return null;
    }
};

const renderTabScreen = (tab) => {
    switch (tab) {
        case 'home': return <HomeScreen />;
        case 'lines': return <LinesScreen />;
        case 'activity': return <ActivityScreen />;
        case 'billing': return <BillingScreen />;
        case 'more': return <MoreScreen />;
        default: return <HomeScreen />;
    }
};

/* ==================== Root App ==================== */
const App = () => {
    const { user, tab, stack } = useApp();
    if (!user) return <LoginScreen />;
    const top = stack[stack.length - 1];
    return (
        <div className="app-shell">
            {top ? renderStackScreen(top) : renderTabScreen(tab)}
            <TabBar />
        </div>
    );
};

const Root = () => (
    <ToastProvider>
        <AppProvider>
            <App />
        </AppProvider>
    </ToastProvider>
);

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