/**
 * mypro.ch · Manager — App React (JSX via Babel)
 * Couvre la parité fonctionnelle avec net.adlap.connect (centrales).
 */
const { useState, useEffect, useCallback, useMemo, useRef } = React;

// ============================================================================
// Toast helper
// ============================================================================
let _toastSetter = null;
function toast(msg, type = 'success') {
    if (_toastSetter) _toastSetter({ msg, type, id: Date.now() });
}
function ToastContainer() {
    const [t, set] = useState(null);
    useEffect(() => { _toastSetter = set; return () => { _toastSetter = null; }; }, []);
    useEffect(() => { if (t) { const id = setTimeout(() => set(null), 3000); return () => clearTimeout(id); } }, [t]);
    if (!t) return null;
    return <div className={`toast toast-${t.type}`}>{t.msg}</div>;
}

// ============================================================================
// Modal
// ============================================================================
function Modal({ title, onClose, children, footer, size = 'md' }) {
    return (
        <div className="modal-backdrop" onClick={onClose}>
            <div className="modal" style={{ maxWidth: size === 'lg' ? 920 : 720 }} onClick={e => e.stopPropagation()}>
                <div className="modal-header">
                    <h3 className="font-bold text-lg">{title}</h3>
                    <button onClick={onClose} className="text-gray-400 hover:text-gray-700"><i className="fas fa-times"></i></button>
                </div>
                <div className="modal-body">{children}</div>
                {footer && <div className="modal-footer">{footer}</div>}
            </div>
        </div>
    );
}

function ConfirmDialog({ title, message, confirmLabel = 'Confirmer', danger, onConfirm, onCancel }) {
    return (
        <Modal title={title} onClose={onCancel} footer={
            <>
                <button className="btn btn-secondary" onClick={onCancel}>Annuler</button>
                <button className={`btn ${danger ? 'btn-danger' : 'btn-primary'}`} onClick={onConfirm}>{confirmLabel}</button>
            </>
        }>
            <p className="text-sm text-gray-700">{message}</p>
        </Modal>
    );
}

// ============================================================================
// Form Field
// ============================================================================
function Field({ label, children }) {
    return <div className="field"><label>{label}</label>{children}</div>;
}

function TextInput({ value, onChange, type = 'text', placeholder, required }) {
    return <input type={type} className="input" value={value ?? ''} required={required}
                  placeholder={placeholder} onChange={e => onChange(e.target.value)} />;
}

function TextArea({ value, onChange, rows = 4 }) {
    return <textarea className="input" rows={rows} value={value ?? ''}
                     onChange={e => onChange(e.target.value)} />;
}

function Select({ value, onChange, options, placeholder = '— choisir —' }) {
    return (
        <select className="input" value={value ?? ''} onChange={e => onChange(e.target.value)}>
            <option value="">{placeholder}</option>
            {options.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
        </select>
    );
}

function Checkbox({ value, onChange, label }) {
    return (
        <label className="inline-flex items-center gap-2 text-sm cursor-pointer">
            <input type="checkbox" checked={!!value} onChange={e => onChange(e.target.checked ? 1 : 0)} className="w-4 h-4" />
            {label}
        </label>
    );
}

// ============================================================================
// Generic CRUD View — table + create/edit modal
// ============================================================================
/**
 * fields = [
 *   { key, label, type: 'text'|'number'|'date'|'datetime'|'textarea'|'bool'|'select', options? },
 * ]
 * Optional :
 *   listColumns: subset of fields shown in table
 *   formColumns: subset shown in modal (default = all editable)
 *   formGrid: 1 | 2 (CSS columns)
 *   onRowClick(row, ctx)  → custom handler
 *   actions: ({row, reload}) => extra <button>s in last column
 */
function CrudView({ resource, title, fields, listColumns, formColumns,
                   formGrid = 2, searchable = true, canCreate = true, canEdit = true, canDelete = true,
                   actions, onRowClick, defaultRow }) {
    const [rows, setRows] = useState(null);
    const [err, setErr] = useState('');
    const [search, setSearch] = useState('');
    const [editing, setEditing] = useState(null);          // {} = new, object = edit
    const [confirm, setConfirm] = useState(null);

    const cols = listColumns || fields.slice(0, 6);
    const fcols = formColumns || fields;

    const reload = useCallback(async () => {
        setRows(null); setErr('');
        try {
            const params = search ? { q: search } : {};
            const data = await MyProAPI.list(resource, params);
            setRows(data[Object.keys(data).find(k => Array.isArray(data[k]))] || []);
        } catch (e) { setErr(e.message); setRows([]); }
    }, [resource, search]);

    useEffect(() => { reload(); }, [reload]);

    async function save() {
        try {
            if (editing.id) {
                const patch = { ...editing };
                delete patch.id; delete patch.created; delete patch.modified; delete patch.md5;
                delete patch.central_id; delete patch.website_id;
                await MyProAPI.update(resource, editing.id, patch);
                toast('Enregistré');
            } else {
                await MyProAPI.create(resource, editing);
                toast('Créé');
            }
            setEditing(null);
            reload();
        } catch (e) { toast(e.message, 'error'); }
    }

    async function doDelete(id) {
        try {
            await MyProAPI.remove(resource, id);
            toast('Supprimé');
            setConfirm(null);
            reload();
        } catch (e) { toast(e.message, 'error'); }
    }

    function renderCell(row, col) {
        const v = row[col.key];
        if (col.type === 'bool') return v
            ? <span className="badge badge-success">Oui</span>
            : <span className="badge badge-muted">—</span>;
        if (col.type === 'date' && v) return v.slice(0, 10);
        if (col.type === 'datetime' && v) return v.replace('T', ' ').slice(0, 16);
        if (col.type === 'select' && col.options) {
            const opt = col.options.find(o => String(o.value) === String(v));
            return opt ? opt.label : (v ?? '—');
        }
        return v == null || v === '' ? '—' : String(v);
    }

    function renderField(f) {
        const v = editing[f.key];
        const set = nv => setEditing(e => ({ ...e, [f.key]: nv }));
        if (f.type === 'textarea') return <TextArea value={v} onChange={set} rows={f.rows || 4} />;
        if (f.type === 'bool')     return <Checkbox value={v} onChange={set} label={f.checkboxLabel || 'Activé'} />;
        if (f.type === 'select')   return <Select value={v} onChange={set} options={f.options || []} placeholder={f.placeholder} />;
        if (f.type === 'number')   return <TextInput value={v} onChange={set} type="number" />;
        if (f.type === 'date')     return <TextInput value={v} onChange={set} type="date" />;
        if (f.type === 'datetime') return <TextInput value={v} onChange={set} type="datetime-local" />;
        return <TextInput value={v} onChange={set} placeholder={f.placeholder} />;
    }

    return (
        <div>
            <div className="flex items-center justify-between mb-4">
                <h1 className="text-2xl font-bold">{title}</h1>
                {canCreate && (
                    <button className="btn btn-primary" onClick={() => setEditing(defaultRow ? { ...defaultRow } : {})}>
                        <i className="fas fa-plus"></i> Nouveau
                    </button>
                )}
            </div>

            {searchable && (
                <div className="toolbar">
                    <input className="search-input" placeholder="Rechercher…" value={search}
                           onChange={e => setSearch(e.target.value)} />
                </div>
            )}

            {err && <div className="card text-red-600 mb-3">{err}</div>}

            {rows == null ? (
                <div className="flex justify-center py-10"><div className="loading-spinner"></div></div>
            ) : rows.length === 0 ? (
                <div className="card text-center text-gray-500 py-10">Aucun élément</div>
            ) : (
                <div className="card" style={{ padding: 0, overflow: 'auto' }}>
                    <table className="data">
                        <thead><tr>
                            {cols.map(c => <th key={c.key}>{c.label}</th>)}
                            <th style={{ width: 1 }}></th>
                        </tr></thead>
                        <tbody>
                            {rows.map(row => (
                                <tr key={row.id} className={onRowClick ? 'row-link' : ''}
                                    onClick={onRowClick ? () => onRowClick(row, { reload }) : undefined}>
                                    {cols.map(c => <td key={c.key}>{renderCell(row, c)}</td>)}
                                    <td onClick={e => e.stopPropagation()} className="whitespace-nowrap">
                                        {actions && actions({ row, reload })}
                                        {canEdit && (
                                            <button className="text-gray-500 hover:text-indigo-600 px-2"
                                                    onClick={() => setEditing(row)}>
                                                <i className="fas fa-pen"></i>
                                            </button>
                                        )}
                                        {canDelete && (
                                            <button className="text-gray-500 hover:text-red-600 px-2"
                                                    onClick={() => setConfirm(row)}>
                                                <i className="fas fa-trash"></i>
                                            </button>
                                        )}
                                    </td>
                                </tr>
                            ))}
                        </tbody>
                    </table>
                </div>
            )}

            {editing && (
                <Modal title={editing.id ? 'Modifier' : 'Nouveau'} onClose={() => setEditing(null)}
                       footer={<>
                           <button className="btn btn-secondary" onClick={() => setEditing(null)}>Annuler</button>
                           <button className="btn btn-primary" onClick={save}>Enregistrer</button>
                       </>}>
                    <div className={`grid grid-cols-1 md:grid-cols-${formGrid} gap-3`}>
                        {fcols.map(f => <Field key={f.key} label={f.label}>{renderField(f)}</Field>)}
                    </div>
                </Modal>
            )}

            {confirm && (
                <ConfirmDialog title="Confirmer la suppression" danger
                               message={`Voulez-vous vraiment supprimer cet élément ?`}
                               confirmLabel="Supprimer"
                               onCancel={() => setConfirm(null)}
                               onConfirm={() => doDelete(confirm.id)} />
            )}
        </div>
    );
}

// ============================================================================
// Helper hooks
// ============================================================================
function useResource(resource, params = {}) {
    const [data, setData] = useState(null);
    const [err, setErr] = useState('');
    const reload = useCallback(() => {
        setData(null);
        MyProAPI.list(resource, params).then(d => {
            setData(d[Object.keys(d).find(k => Array.isArray(d[k]))] || []);
        }).catch(e => { setErr(e.message); setData([]); });
    }, [resource, JSON.stringify(params)]);
    useEffect(() => { reload(); }, [reload]);
    return { data, err, reload };
}

// ============================================================================
// LOGIN
// ============================================================================
function Login({ onLogged }) {
    const [email, setEmail] = useState('');
    const [sending, setSending] = useState(false);
    const [sent, setSent] = useState(false);
    const [err, setErr] = useState('');

    async function submit(e) {
        e.preventDefault();
        setErr(''); setSending(true);
        try {
            await MyProAuth.requestMagic(email.trim().toLowerCase());
            setSent(true);
        } catch (e) { setErr(e.message); }
        finally { setSending(false); }
    }

    return (
        <div className="min-h-screen flex items-center justify-center px-4">
            <div className="card w-full max-w-md">
                <div className="text-center mb-6">
                    <div className="inline-flex items-center justify-center w-14 h-14 rounded-2xl mb-4"
                         style={{ background: 'linear-gradient(135deg, #4f46e5, #7c3aed)' }}>
                        <i className="fas fa-taxi text-white text-2xl"></i>
                    </div>
                    <h1 className="text-2xl font-bold mb-1">mypro.ch · Manager</h1>
                    <p className="text-gray-500 text-sm">Espace de gestion de votre centrale</p>
                </div>
                {sent ? (
                    <div className="text-center py-4">
                        <i className="fas fa-envelope-open-text text-4xl text-indigo-500 mb-3"></i>
                        <h3 className="font-semibold mb-1">Vérifiez vos emails</h3>
                        <p className="text-sm text-gray-500 mb-4">Un lien a été envoyé à <strong>{email}</strong></p>
                        <button className="btn btn-secondary" onClick={() => { setSent(false); setEmail(''); }}>
                            Utiliser une autre adresse
                        </button>
                    </div>
                ) : (
                    <form onSubmit={submit}>
                        <Field label="Adresse email">
                            <input type="email" required autoFocus className="input"
                                   placeholder="vous@centrale.ch" value={email}
                                   onChange={e => setEmail(e.target.value)} />
                        </Field>
                        {err && <div className="text-sm text-red-600 mb-3">{err}</div>}
                        <button type="submit" className="btn btn-primary w-full" disabled={sending}>
                            {sending ? <span className="spinner-dot"></span> : 'Recevoir un lien de connexion'}
                        </button>
                        <p className="text-xs text-gray-400 text-center mt-4">
                            Pas de mot de passe : un lien sécurisé sera envoyé à votre adresse.
                        </p>
                    </form>
                )}
            </div>
        </div>
    );
}

// ============================================================================
// LAYOUT — sidebar avec sections
// ============================================================================
const NAV = [
    { type: 'item',    id: 'dashboard',   label: 'Tableau de bord',  icon: 'home' },
    { type: 'item',    id: 'calendar',    label: 'Calendrier',       icon: 'calendar-week' },
    { type: 'group',   label: 'Courses' },
    { type: 'item',    id: 'bookings.today',     label: 'Aujourd\'hui',  icon: 'sun' },
    { type: 'item',    id: 'bookings.upcoming',  label: 'À venir',       icon: 'clock' },
    { type: 'item',    id: 'bookings.past',      label: 'Passées',       icon: 'check' },
    { type: 'item',    id: 'bookings.to-pay',    label: 'À payer',       icon: 'money-bill-wave' },
    { type: 'item',    id: 'bookings.no-show',   label: 'No-show',       icon: 'user-slash' },
    { type: 'item',    id: 'bookings.cancelled', label: 'Annulées',      icon: 'ban' },
    { type: 'group',   label: 'Personnes' },
    { type: 'item',    id: 'drivers',     label: 'Chauffeurs',       icon: 'user-tie' },
    { type: 'item',    id: 'customers',   label: 'Clients',          icon: 'users' },
    { type: 'item',    id: 'partnerships',label: 'Partenariats',     icon: 'handshake' },
    { type: 'group',   label: 'Tarification' },
    { type: 'item',    id: 'ranges',      label: 'Gammes',           icon: 'car' },
    { type: 'item',    id: 'centralprices',label: 'Tarifs',          icon: 'tag' },
    { type: 'item',    id: 'dispositions',label: 'Forfaits horaires',icon: 'hourglass' },
    { type: 'item',    id: 'mixeddiscounts',label: 'Forfaits zones', icon: 'map-marked-alt' },
    { type: 'item',    id: 'promocodes',  label: 'Codes promo',      icon: 'ticket-alt' },
    { type: 'item',    id: 'offers',      label: 'Offres',           icon: 'percent' },
    { type: 'item',    id: 'options',     label: 'Suppléments',      icon: 'plus-square' },
    { type: 'item',    id: 'vehicles',    label: 'Véhicules',        icon: 'taxi' },
    { type: 'group',   label: 'Comptabilité' },
    { type: 'item',    id: 'invoices',    label: 'Factures',         icon: 'file-invoice' },
    { type: 'item',    id: 'payments',    label: 'Paiements',        icon: 'credit-card' },
    { type: 'group',   label: 'Centrale' },
    { type: 'item',    id: 'centrale.info',     label: 'Informations',  icon: 'info-circle' },
    { type: 'item',    id: 'centrale.branding', label: 'Branding',      icon: 'palette' },
    { type: 'item',    id: 'centrale.params',   label: 'Paramètres',    icon: 'cog' },
    { type: 'item',    id: 'blockdates', label: 'Dates de fermeture', icon: 'calendar-times' },
    { type: 'item',    id: 'texts',      label: 'Textes (templates)', icon: 'file-alt' },
    { type: 'group',   label: 'Notifications' },
    { type: 'item',    id: 'sms',        label: 'Recharges SMS',     icon: 'sms' },
    { type: 'item',    id: 'sms-history',label: 'Historique SMS',    icon: 'history' },
    { type: 'item',    id: 'notif-history', label: 'Historique push', icon: 'bell' },
];

function Layout({ user, page, setPage, children }) {
    return (
        <div className="min-h-screen flex">
            <aside className="hidden md:flex flex-col w-64 bg-white border-r border-gray-200 overflow-y-auto">
                <div className="p-5 border-b border-gray-200">
                    <div className="flex items-center gap-3">
                        <div className="w-10 h-10 rounded-lg flex items-center justify-center"
                             style={{ background: 'linear-gradient(135deg, #4f46e5, #7c3aed)' }}>
                            <i className="fas fa-taxi text-white"></i>
                        </div>
                        <div>
                            <div className="font-bold text-sm">mypro.ch</div>
                            <div className="text-xs text-gray-500 truncate" style={{ maxWidth: 160 }}>{user.company || user.email}</div>
                        </div>
                    </div>
                </div>
                <nav className="flex-1 p-2">
                    {NAV.map((n, i) => n.type === 'group'
                        ? <div key={i} className="section-title">{n.label}</div>
                        : <div key={n.id} className={`nav-link ${page === n.id ? 'active' : ''}`}
                               onClick={() => setPage(n.id)}>
                              <i className={`fas fa-${n.icon}`}></i>{n.label}
                          </div>
                    )}
                </nav>
                <div className="p-3 border-t border-gray-200">
                    <button onClick={() => MyProAuth.logout()}
                            className="w-full text-left text-sm text-gray-700 hover:text-red-600 py-1.5 flex items-center gap-2">
                        <i className="fas fa-sign-out-alt w-5 text-center"></i> Déconnexion
                    </button>
                </div>
            </aside>
            <main className="flex-1 overflow-auto">
                <div className="md:hidden bg-white border-b border-gray-200 p-4 flex items-center justify-between">
                    <div className="flex items-center gap-2">
                        <i className="fas fa-taxi text-indigo-600"></i>
                        <span className="font-bold">mypro.ch</span>
                    </div>
                    <select value={page} onChange={e => setPage(e.target.value)} className="input" style={{ maxWidth: 220 }}>
                        {NAV.filter(n => n.type === 'item').map(n =>
                            <option key={n.id} value={n.id}>{n.label}</option>)}
                    </select>
                </div>
                <div className="p-6 max-w-7xl mx-auto">{children}</div>
            </main>
            <ToastContainer />
        </div>
    );
}

// ============================================================================
// DASHBOARD
// ============================================================================
function PageDashboard({ user }) {
    const [stats, setStats] = useState(null);
    const [err, setErr] = useState('');
    useEffect(() => { MyProAPI.statsWebsite().then(setStats).catch(e => setErr(e.message)); }, []);

    if (err) return <div className="card text-red-600">{err}</div>;
    if (!stats) return <div className="flex justify-center py-10"><div className="loading-spinner"></div></div>;

    const sms = stats.sms_balance ?? 0;
    return (
        <div>
            <div className="mb-6">
                <h1 className="text-2xl font-bold">Bonjour {user.company || user.email}</h1>
                <p className="text-gray-500 text-sm">Aperçu de votre activité</p>
            </div>
            {stats.sms_alert ? (
                <div className="card mb-4 border-red-200 bg-red-50">
                    <div className="flex items-center gap-3">
                        <i className="fas fa-exclamation-triangle text-red-600 text-xl"></i>
                        <div>
                            <div className="font-semibold text-red-900">Solde SMS épuisé</div>
                            <div className="text-sm text-red-700">Rechargez votre compte pour continuer à recevoir/envoyer des SMS.</div>
                        </div>
                    </div>
                </div>
            ) : null}
            <div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6">
                <StatCard label="SMS restants" value={sms} icon="sms" color={sms <= 20 ? '#ef4444' : '#10b981'} />
                <StatCard label="Courses aujourd'hui" value={stats.bookings_today} icon="calendar-day" color="#4f46e5" />
                <StatCard label="Courses à venir" value={stats.bookings_upcoming} icon="calendar-plus" color="#0ea5e9" />
                <StatCard label="Visiteurs" value={stats.visitors} icon="users" color="#7c3aed" />
            </div>
            <div className="card">
                <h2 className="font-semibold mb-3">Dernière commande SMS</h2>
                {stats.last_order ? (
                    <div className="flex items-center justify-between">
                        <div>
                            <div className="font-semibold">{stats.last_order.sms_count} SMS</div>
                            <div className="text-sm text-gray-500">{stats.last_order.created}</div>
                        </div>
                        <span className={`badge ${stats.last_order.is_payed ? 'badge-success' : 'badge-warn'}`}>
                            {stats.last_order.is_payed ? 'Payé' : 'En attente'}
                        </span>
                    </div>
                ) : <div className="text-sm text-gray-500">Aucune commande</div>}
            </div>
        </div>
    );
}

function StatCard({ label, value, icon, color }) {
    return (
        <div className="card">
            <div className="flex items-center gap-3 mb-2">
                <div className="w-10 h-10 rounded-lg flex items-center justify-center"
                     style={{ background: color + '15', color }}>
                    <i className={`fas fa-${icon}`}></i>
                </div>
                <div className="text-xs text-gray-500">{label}</div>
            </div>
            <div className="text-2xl font-bold">{value ?? 0}</div>
        </div>
    );
}

// ============================================================================
// CALENDAR
// ============================================================================
function PageCalendar() {
    const today = new Date().toISOString().slice(0, 10);
    const weekFromNow = new Date(Date.now() + 6 * 86400000).toISOString().slice(0, 10);
    const [from, setFrom] = useState(today);
    const [to, setTo] = useState(weekFromNow);
    const [data, setData] = useState(null);
    const [err, setErr] = useState('');

    useEffect(() => {
        setData(null);
        MyProAPI.calendar(from, to).then(setData).catch(e => setErr(e.message));
    }, [from, to]);

    const days = useMemo(() => {
        const out = [];
        const start = new Date(from);
        const end = new Date(to);
        for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) {
            out.push(d.toISOString().slice(0, 10));
        }
        return out;
    }, [from, to]);

    return (
        <div>
            <div className="flex items-center justify-between mb-4">
                <h1 className="text-2xl font-bold">Calendrier</h1>
                <div className="flex gap-2 items-center text-sm">
                    <input type="date" value={from} onChange={e => setFrom(e.target.value)} className="input" style={{ width: 160 }} />
                    <span className="text-gray-500">→</span>
                    <input type="date" value={to} onChange={e => setTo(e.target.value)} className="input" style={{ width: 160 }} />
                </div>
            </div>
            {err && <div className="card text-red-600 mb-3">{err}</div>}
            {!data ? <div className="flex justify-center py-10"><div className="loading-spinner"></div></div>
                   : (
                <div className="space-y-3">
                    {days.map(day => {
                        const list = (data.bookings || []).filter(b => (b.dated || '').slice(0, 10) === day);
                        const blocked = (data.blockdates || []).find(bd => day >= bd.date_from && day <= bd.date_to);
                        return (
                            <div key={day} className="card">
                                <div className="flex items-center justify-between mb-2">
                                    <div className="font-semibold">
                                        {new Date(day).toLocaleDateString('fr-CH', { weekday: 'long', day: 'numeric', month: 'long' })}
                                        {blocked && <span className="badge badge-danger ml-2">Fermé : {blocked.label}</span>}
                                    </div>
                                    <div className="text-xs text-gray-500">{list.length} course{list.length > 1 ? 's' : ''}</div>
                                </div>
                                {list.length === 0 ? (
                                    <div className="text-sm text-gray-400 italic">Pas de course</div>
                                ) : (
                                    <div className="divide-y">
                                        {list.map(b => (
                                            <div key={b.id} className="py-2 flex items-center justify-between text-sm">
                                                <div>
                                                    <span className="font-mono text-xs text-gray-500 mr-2">{(b.dated || '').slice(11, 16)}</span>
                                                    <span className="font-semibold">{b.customer_firstname} {b.customer_lastname}</span>
                                                    <span className="text-gray-500"> · {b.origin_address?.slice(0, 40)} → {b.destination_address?.slice(0, 40)}</span>
                                                </div>
                                                <div>
                                                    {b.cancelled ? <span className="badge badge-danger">Annulée</span>
                                                     : b.is_no_show ? <span className="badge badge-warn">No-show</span>
                                                     : b.is_completed ? <span className="badge badge-success">Terminée</span>
                                                     : b.selected_driver_id ? <span className="badge badge-success">Assignée</span>
                                                     : <span className="badge badge-muted">Non assignée</span>}
                                                </div>
                                            </div>
                                        ))}
                                    </div>
                                )}
                            </div>
                        );
                    })}
                </div>
            )}
        </div>
    );
}

// ============================================================================
// BOOKINGS — list + detail
// ============================================================================
function PageBookings({ mode }) {
    const [data, setData] = useState(null);
    const [err, setErr] = useState('');
    const [search, setSearch] = useState('');
    const [creating, setCreating] = useState(false);
    const [detail, setDetail] = useState(null);

    const reload = useCallback(() => {
        setData(null); setErr('');
        MyProAPI.bookings(mode, search ? { q: search } : {}).then(d => setData(d.bookings || [])).catch(e => setErr(e.message));
    }, [mode, search]);

    useEffect(() => { reload(); }, [reload]);

    return (
        <div>
            <div className="flex items-center justify-between mb-4">
                <h1 className="text-2xl font-bold">Courses · {({ today: 'Aujourd\'hui', upcoming: 'À venir', past: 'Passées', cancelled: 'Annulées', 'to-pay': 'À payer', 'no-show': 'No-show', all: 'Toutes' })[mode]}</h1>
                <button className="btn btn-primary" onClick={() => setCreating(true)}><i className="fas fa-plus"></i> Nouvelle course</button>
            </div>
            <div className="toolbar">
                <input className="search-input" placeholder="Rechercher (réf, client, email, mobile)…"
                       value={search} onChange={e => setSearch(e.target.value)} />
            </div>
            {err && <div className="card text-red-600 mb-3">{err}</div>}
            {!data ? <div className="flex justify-center py-10"><div className="loading-spinner"></div></div>
             : data.length === 0 ? <div className="card text-center text-gray-500 py-10">Aucune course</div>
             : (
                <div className="card" style={{ padding: 0, overflow: 'auto' }}>
                    <table className="data">
                        <thead><tr>
                            <th>Réf.</th><th>Client</th><th>Date</th><th>Trajet</th>
                            <th>Prix</th><th>Chauffeur</th><th>Statut</th><th></th>
                        </tr></thead>
                        <tbody>
                            {data.map(b => (
                                <tr key={b.id} className="row-link" onClick={() => setDetail(b.id)}>
                                    <td><strong>{b.reference || ('#' + b.id)}</strong></td>
                                    <td>{((b.customer_firstname || '') + ' ' + (b.customer_lastname || '')).trim() || '—'}</td>
                                    <td className="whitespace-nowrap text-sm">{(b.dated || '—').replace('T', ' ').slice(0, 16)}</td>
                                    <td className="max-w-xs">
                                        <div className="text-xs text-gray-600 truncate">↑ {b.origin_address || '—'}</div>
                                        <div className="text-xs text-gray-600 truncate">↓ {b.destination_address || '—'}</div>
                                    </td>
                                    <td className="whitespace-nowrap">{(b.price || 0)} CHF</td>
                                    <td>{b.selected_driver_id ? <span className="text-xs">#{b.selected_driver_id}</span> : <span className="badge badge-muted">—</span>}</td>
                                    <td>
                                        {b.cancelled ? <span className="badge badge-danger">Annulée</span>
                                         : b.is_no_show ? <span className="badge badge-warn">No-show</span>
                                         : b.is_completed ? (b.is_paid ? <span className="badge badge-success">Payée</span> : <span className="badge badge-warn">À payer</span>)
                                         : b.selected_driver_id ? <span className="badge badge-success">Assignée</span>
                                         : <span className="badge badge-muted">En attente</span>}
                                    </td>
                                    <td><i className="fas fa-chevron-right text-gray-400"></i></td>
                                </tr>
                            ))}
                        </tbody>
                    </table>
                </div>
            )}
            {creating && <BookingCreateModal onClose={() => setCreating(false)} onSaved={() => { setCreating(false); reload(); }} />}
            {detail && <BookingDetailModal id={detail} onClose={() => setDetail(null)} onChanged={reload} />}
        </div>
    );
}

function BookingDetailModal({ id, onClose, onChanged }) {
    const [data, setData] = useState(null);
    const [err, setErr] = useState('');
    const [drivers, setDrivers] = useState([]);
    const [tab, setTab] = useState('info');
    const [confirmCancel, setConfirmCancel] = useState(false);

    const reload = useCallback(() => {
        setData(null);
        MyProAPI.booking(id).then(setData).catch(e => setErr(e.message));
    }, [id]);
    useEffect(() => { reload(); }, [reload]);
    useEffect(() => { MyProAPI.drivers({ active: 1, limit: 200 }).then(d => setDrivers(d.drivers || [])); }, []);

    async function action(act, body = {}) {
        try {
            await MyProAPI.bookingAction(id, act, body);
            toast('Action effectuée');
            reload(); onChanged?.();
        } catch (e) { toast(e.message, 'error'); }
    }

    return (
        <Modal title={data?.booking ? `Course ${data.booking.reference}` : 'Course'} onClose={onClose} size="lg">
            {err && <div className="text-red-600 text-sm mb-3">{err}</div>}
            {!data ? <div className="flex justify-center py-10"><div className="loading-spinner"></div></div> : (
                <>
                    <div className="flex gap-2 mb-4">
                        <button className={`tab-btn ${tab === 'info' ? 'active' : ''}`} onClick={() => setTab('info')}>Détails</button>
                        <button className={`tab-btn ${tab === 'driver' ? 'active' : ''}`} onClick={() => setTab('driver')}>Chauffeur</button>
                        <button className={`tab-btn ${tab === 'payment' ? 'active' : ''}`} onClick={() => setTab('payment')}>Paiement</button>
                        <button className={`tab-btn ${tab === 'history' ? 'active' : ''}`} onClick={() => setTab('history')}>Historique</button>
                    </div>

                    {tab === 'info' && (
                        <div>
                            {[
                                ['Référence', data.booking.reference],
                                ['Date prévue', (data.booking.dated || '').replace('T', ' ').slice(0, 16)],
                                ['Client', `${data.booking.customer_firstname || ''} ${data.booking.customer_lastname || ''}`.trim()],
                                ['Email', data.booking.customer_email],
                                ['Mobile', data.booking.customer_mobile],
                                ['Origine', data.booking.origin_address],
                                ['Destination', data.booking.destination_address],
                                ['Distance', `${data.booking.distance_km || 0} km`],
                                ['Durée', `${data.booking.duration_min || 0} min`],
                                ['Sièges / bagages', `${data.booking.seats}/${data.booking.luggage}`],
                                ['Vol', data.booking.flight_number],
                                ['Notes', data.booking.notes],
                                ['Promo', data.booking.promocode],
                                ['Prix', `${data.booking.price || 0} CHF`],
                            ].map(([k, v]) => v ? (
                                <div key={k} className="detail-row"><div className="label">{k}</div><div>{v}</div></div>
                            ) : null)}
                        </div>
                    )}

                    {tab === 'driver' && (
                        <div>
                            {data.driver ? (
                                <div className="card mb-3">
                                    <div className="font-semibold">{data.driver.firstname} {data.driver.lastname}</div>
                                    <div className="text-sm text-gray-500">{data.driver.email} · {data.driver.mobile}</div>
                                </div>
                            ) : <div className="text-sm text-gray-500 mb-3">Aucun chauffeur assigné</div>}
                            <Field label="Assigner un chauffeur">
                                <Select value={data.booking.selected_driver_id || ''}
                                        onChange={v => action('assign', { driver_id: parseInt(v, 10) })}
                                        options={drivers.map(d => ({ value: d.id, label: `${d.firstname || ''} ${d.lastname || ''} — ${d.mobile || ''}` }))}
                                        placeholder="— Choisir —" />
                            </Field>
                            <button className="btn btn-secondary mt-2" onClick={() => action('redispatch')}>
                                <i className="fas fa-sync"></i> Relancer la recherche
                            </button>
                        </div>
                    )}

                    {tab === 'payment' && (
                        <div>
                            <div className="detail-row"><div className="label">Méthode</div><div>{data.booking.payment_method || '—'}</div></div>
                            <div className="detail-row"><div className="label">Statut</div><div>
                                {data.booking.is_paid ? <span className="badge badge-success">Payée</span> : <span className="badge badge-warn">À payer</span>}
                            </div></div>
                            <div className="detail-row"><div className="label">Montant</div><div>{data.booking.price} CHF</div></div>
                            {!data.booking.is_paid && (
                                <div className="mt-3 flex gap-2">
                                    <button className="btn btn-primary" onClick={() => action('mark-paid', { method: 'cash' })}>
                                        Marquer payée (cash)
                                    </button>
                                    <button className="btn btn-secondary" onClick={() => action('mark-paid', { method: 'bill' })}>
                                        Marquer payée (facture)
                                    </button>
                                </div>
                            )}
                            <h4 className="font-semibold mt-4 mb-2">Transactions</h4>
                            {data.payments?.length ? (
                                <ul className="text-sm space-y-1">
                                    {data.payments.map(p => (
                                        <li key={p.id} className="flex justify-between">
                                            <span>{p.created} · {p.method} · {p.provider}</span>
                                            <span>{p.amount} {p.currency} <span className="badge badge-muted ml-2">{p.status}</span></span>
                                        </li>
                                    ))}
                                </ul>
                            ) : <div className="text-sm text-gray-500">Aucune transaction</div>}
                        </div>
                    )}

                    {tab === 'history' && (
                        <div>
                            <h4 className="font-semibold mb-2">Propositions chauffeurs</h4>
                            {data.proposals?.length ? (
                                <ul className="text-sm space-y-1">
                                    {data.proposals.map(p => (
                                        <li key={p.id} className="flex justify-between">
                                            <span>{p.created} · {p.firstname} {p.lastname}</span>
                                            <span>
                                                {p.is_accepted ? <span className="badge badge-success">Acceptée</span>
                                                 : p.is_declined ? <span className="badge badge-danger">Refusée</span>
                                                 : p.is_opened ? <span className="badge badge-warn">Vue</span>
                                                 : <span className="badge badge-muted">Envoyée</span>}
                                            </span>
                                        </li>
                                    ))}
                                </ul>
                            ) : <div className="text-sm text-gray-500">Aucune proposition</div>}
                        </div>
                    )}

                    <div className="modal-footer mt-4 -mx-[22px] -mb-[20px]">
                        {!data.booking.cancelled && !data.booking.is_completed && (
                            <>
                                <button className="btn btn-secondary" onClick={() => action('no-show')}>
                                    <i className="fas fa-user-slash"></i> No-show
                                </button>
                                <button className="btn btn-secondary" onClick={() => action('complete')}>
                                    <i className="fas fa-check"></i> Marquer terminée
                                </button>
                                <button className="btn btn-danger" onClick={() => setConfirmCancel(true)}>
                                    <i className="fas fa-ban"></i> Annuler
                                </button>
                            </>
                        )}
                    </div>
                </>
            )}
            {confirmCancel && (
                <ConfirmDialog title="Annuler la course" message="Confirmer l'annulation ?" danger
                               confirmLabel="Annuler la course"
                               onCancel={() => setConfirmCancel(false)}
                               onConfirm={() => { setConfirmCancel(false); action('cancel'); }} />
            )}
        </Modal>
    );
}

function BookingCreateModal({ onClose, onSaved }) {
    const [data, setData] = useState({ seats: 1, luggage: 0, payment_method: 'cash' });
    const [drivers, setDrivers] = useState([]);
    const [ranges, setRanges] = useState([]);
    const [originSugg, setOriginSugg] = useState([]);
    const [destSugg, setDestSugg] = useState([]);
    useEffect(() => {
        MyProAPI.drivers({ active: 1, limit: 200 }).then(r => setDrivers(r.drivers || []));
        MyProAPI.list('ranges').then(r => setRanges(r.ranges || []));
    }, []);

    function set(k, v) { setData(d => ({ ...d, [k]: v })); }
    async function searchAddr(q, setter) {
        if (!q || q.length < 3) { setter([]); return; }
        const preds = await MyProMaps.search(q);
        setter(preds.slice(0, 5));
    }
    async function pickAddr(p, prefix, setter) {
        const det = await MyProMaps.details(p.place_id);
        if (det) {
            setData(d => ({ ...d,
                [`${prefix}_address`]: p.description,
                [`${prefix}_latitude`]: det.geometry?.location?.lat,
                [`${prefix}_longitude`]: det.geometry?.location?.lng,
            }));
        } else {
            set(`${prefix}_address`, p.description);
        }
        setter([]);
    }

    async function save() {
        try {
            await MyProAPI.createBooking(data);
            toast('Course créée');
            onSaved();
        } catch (e) { toast(e.message, 'error'); }
    }

    return (
        <Modal title="Nouvelle course" onClose={onClose} size="lg" footer={<>
            <button className="btn btn-secondary" onClick={onClose}>Annuler</button>
            <button className="btn btn-primary" onClick={save}>Créer</button>
        </>}>
            <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
                <Field label="Prénom client"><TextInput value={data.customer_firstname} onChange={v => set('customer_firstname', v)} /></Field>
                <Field label="Nom client"><TextInput value={data.customer_lastname} onChange={v => set('customer_lastname', v)} /></Field>
                <Field label="Email"><TextInput type="email" value={data.customer_email} onChange={v => set('customer_email', v)} /></Field>
                <Field label="Mobile"><TextInput value={data.customer_mobile} onChange={v => set('customer_mobile', v)} /></Field>
                <Field label="Date / heure"><TextInput type="datetime-local" value={data.dated} onChange={v => set('dated', v)} /></Field>
                <Field label="Vol"><TextInput value={data.flight_number} onChange={v => set('flight_number', v)} /></Field>
                <div className="md:col-span-2">
                    <Field label="Origine">
                        <input className="input" value={data.origin_address || ''}
                               onChange={e => { set('origin_address', e.target.value); searchAddr(e.target.value, setOriginSugg); }} />
                        {originSugg.length > 0 && (
                            <div className="card mt-1" style={{ padding: 0, maxHeight: 180, overflow: 'auto' }}>
                                {originSugg.map(p => (
                                    <div key={p.place_id} className="px-3 py-2 hover:bg-gray-50 cursor-pointer text-sm"
                                         onClick={() => pickAddr(p, 'origin', setOriginSugg)}>{p.description}</div>
                                ))}
                            </div>
                        )}
                    </Field>
                </div>
                <div className="md:col-span-2">
                    <Field label="Destination">
                        <input className="input" value={data.destination_address || ''}
                               onChange={e => { set('destination_address', e.target.value); searchAddr(e.target.value, setDestSugg); }} />
                        {destSugg.length > 0 && (
                            <div className="card mt-1" style={{ padding: 0, maxHeight: 180, overflow: 'auto' }}>
                                {destSugg.map(p => (
                                    <div key={p.place_id} className="px-3 py-2 hover:bg-gray-50 cursor-pointer text-sm"
                                         onClick={() => pickAddr(p, 'destination', setDestSugg)}>{p.description}</div>
                                ))}
                            </div>
                        )}
                    </Field>
                </div>
                <Field label="Sièges"><TextInput type="number" value={data.seats} onChange={v => set('seats', parseInt(v, 10))} /></Field>
                <Field label="Bagages"><TextInput type="number" value={data.luggage} onChange={v => set('luggage', parseInt(v, 10))} /></Field>
                <Field label="Distance (km)"><TextInput type="number" value={data.distance_km} onChange={v => set('distance_km', parseFloat(v))} /></Field>
                <Field label="Durée (min)"><TextInput type="number" value={data.duration_min} onChange={v => set('duration_min', parseInt(v, 10))} /></Field>
                <Field label="Prix (CHF)"><TextInput type="number" value={data.price} onChange={v => set('price', parseFloat(v))} /></Field>
                <Field label="Gamme"><Select value={data.range_id} onChange={v => set('range_id', parseInt(v, 10))}
                    options={ranges.map(r => ({ value: r.id, label: r.label }))} /></Field>
                <Field label="Paiement">
                    <Select value={data.payment_method} onChange={v => set('payment_method', v)}
                            options={[{ value: 'cash', label: 'Cash' }, { value: 'card', label: 'Carte' },
                                      { value: 'bill', label: 'Facture' }, { value: 'twint', label: 'TWINT' }]}
                            placeholder="" />
                </Field>
                <Field label="Chauffeur (optionnel)">
                    <Select value={data.selected_driver_id} onChange={v => set('selected_driver_id', parseInt(v, 10))}
                            options={drivers.map(d => ({ value: d.id, label: `${d.firstname || ''} ${d.lastname || ''}` }))} />
                </Field>
                <div className="md:col-span-2"><Field label="Notes"><TextArea value={data.notes} onChange={v => set('notes', v)} /></Field></div>
            </div>
        </Modal>
    );
}

// ============================================================================
// DRIVERS — list + detail with toggles
// ============================================================================
function PageDrivers() {
    const [data, setData] = useState(null);
    const [err, setErr] = useState('');
    const [search, setSearch] = useState('');
    const [editing, setEditing] = useState(null);
    const [detail, setDetail] = useState(null);

    const reload = useCallback(() => {
        setData(null); setErr('');
        MyProAPI.drivers(search ? { q: search } : {}).then(d => setData(d.drivers || [])).catch(e => setErr(e.message));
    }, [search]);
    useEffect(() => { reload(); }, [reload]);

    async function toggle(id, field, value) {
        try { await MyProAPI.driverAction(id, 'toggle', { field, value }); toast('Mis à jour'); reload(); }
        catch (e) { toast(e.message, 'error'); }
    }
    async function sendMagic(id, action) {
        try { await MyProAPI.driverAction(id, action); toast('Email envoyé'); }
        catch (e) { toast(e.message, 'error'); }
    }

    async function save() {
        try {
            if (editing.id) {
                const p = { ...editing }; ['id','md5','created','modified','central_id'].forEach(k => delete p[k]);
                await MyProAPI.updateDriver(editing.id, p);
            } else {
                await MyProAPI.createDriver(editing);
            }
            toast('Enregistré'); setEditing(null); reload();
        } catch (e) { toast(e.message, 'error'); }
    }

    return (
        <div>
            <div className="flex items-center justify-between mb-4">
                <h1 className="text-2xl font-bold">Chauffeurs</h1>
                <button className="btn btn-primary" onClick={() => setEditing({ is_active: 1, is_automatic: 1 })}>
                    <i className="fas fa-plus"></i> Nouveau chauffeur
                </button>
            </div>
            <div className="toolbar"><input className="search-input" placeholder="Rechercher…" value={search} onChange={e => setSearch(e.target.value)} /></div>
            {err && <div className="card text-red-600 mb-3">{err}</div>}
            {!data ? <div className="flex justify-center py-10"><div className="loading-spinner"></div></div>
             : (
                <div className="card" style={{ padding: 0, overflow: 'auto' }}>
                    <table className="data">
                        <thead><tr>
                            <th></th><th>Nom</th><th>Contact</th>
                            <th>Actif</th><th>Auto</th><th>Repéré</th><th>Star</th><th></th>
                        </tr></thead>
                        <tbody>
                            {data.map(d => (
                                <tr key={d.id}>
                                    <td>{d.is_star ? <i className="fas fa-star text-yellow-500"></i> : null}</td>
                                    <td className="row-link" onClick={() => setDetail(d.id)}>
                                        <strong>{d.firstname} {d.lastname}</strong>
                                    </td>
                                    <td className="text-sm">{d.email}<br/><span className="text-gray-500">{d.mobile}</span></td>
                                    <td><Toggle value={d.is_active} onChange={v => toggle(d.id, 'is_active', v)} /></td>
                                    <td><Toggle value={d.is_automatic} onChange={v => toggle(d.id, 'is_automatic', v)} /></td>
                                    <td><Toggle value={d.is_spotted} onChange={v => toggle(d.id, 'is_spotted', v)} /></td>
                                    <td><Toggle value={d.is_star} onChange={v => toggle(d.id, 'is_star', v)} /></td>
                                    <td className="whitespace-nowrap">
                                        <button className="text-gray-500 hover:text-indigo-600 px-2" title="Envoyer magic link"
                                                onClick={() => sendMagic(d.id, 'send-magic')}><i className="fas fa-envelope"></i></button>
                                        <button className="text-gray-500 hover:text-indigo-600 px-2" title="Modifier"
                                                onClick={() => setEditing(d)}><i className="fas fa-pen"></i></button>
                                    </td>
                                </tr>
                            ))}
                        </tbody>
                    </table>
                </div>
            )}
            {editing && (
                <Modal title={editing.id ? 'Modifier chauffeur' : 'Nouveau chauffeur'} onClose={() => setEditing(null)}
                       footer={<>
                           <button className="btn btn-secondary" onClick={() => setEditing(null)}>Annuler</button>
                           <button className="btn btn-primary" onClick={save}>Enregistrer</button>
                       </>}>
                    <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
                        <Field label="Prénom"><TextInput value={editing.firstname} onChange={v => setEditing({ ...editing, firstname: v })} /></Field>
                        <Field label="Nom"><TextInput value={editing.lastname} onChange={v => setEditing({ ...editing, lastname: v })} /></Field>
                        <Field label="Email"><TextInput type="email" value={editing.email} onChange={v => setEditing({ ...editing, email: v })} /></Field>
                        <Field label="Mobile"><TextInput value={editing.mobile} onChange={v => setEditing({ ...editing, mobile: v })} /></Field>
                        <Field label="Adresse"><TextInput value={editing.address} onChange={v => setEditing({ ...editing, address: v })} /></Field>
                        <Field label="Date de naissance"><TextInput type="date" value={editing.birthday} onChange={v => setEditing({ ...editing, birthday: v })} /></Field>
                        <div className="md:col-span-2"><Field label="Commentaire"><TextArea value={editing.comment} onChange={v => setEditing({ ...editing, comment: v })} /></Field></div>
                        <Field label="Actif"><Checkbox value={editing.is_active} onChange={v => setEditing({ ...editing, is_active: v })} /></Field>
                        <Field label="Dispatch automatique"><Checkbox value={editing.is_automatic} onChange={v => setEditing({ ...editing, is_automatic: v })} /></Field>
                        <Field label="Star"><Checkbox value={editing.is_star} onChange={v => setEditing({ ...editing, is_star: v })} /></Field>
                        <Field label="Repéré"><Checkbox value={editing.is_spotted} onChange={v => setEditing({ ...editing, is_spotted: v })} /></Field>
                    </div>
                </Modal>
            )}
            {detail && <DriverDetailModal id={detail} onClose={() => setDetail(null)} />}
        </div>
    );
}

function Toggle({ value, onChange }) {
    return (
        <button onClick={() => onChange(value ? 0 : 1)}
                className={`relative w-10 h-6 rounded-full transition ${value ? 'bg-indigo-600' : 'bg-gray-300'}`}>
            <span className={`absolute top-0.5 left-0.5 w-5 h-5 bg-white rounded-full transition transform ${value ? 'translate-x-4' : ''}`}></span>
        </button>
    );
}

function DriverDetailModal({ id, onClose }) {
    const [data, setData] = useState(null);
    useEffect(() => { MyProAPI.driver(id).then(setData); }, [id]);
    if (!data) return <Modal title="Chauffeur" onClose={onClose}><div className="flex justify-center py-10"><div className="loading-spinner"></div></div></Modal>;
    return (
        <Modal title={`${data.driver.firstname} ${data.driver.lastname}`} onClose={onClose} size="lg">
            <div className="grid grid-cols-2 md:grid-cols-4 gap-3 mb-4">
                <StatCard label="Total courses" value={data.stats?.total} icon="route" color="#4f46e5" />
                <StatCard label="Terminées" value={data.stats?.completed} icon="check" color="#10b981" />
                <StatCard label="Annulées" value={data.stats?.cancelled} icon="ban" color="#ef4444" />
                <StatCard label="Revenu" value={`${data.stats?.revenue || 0} CHF`} icon="coins" color="#f59e0b" />
            </div>
            {[
                ['Email', data.driver.email],
                ['Mobile', data.driver.mobile],
                ['Adresse', data.driver.address],
                ['Naissance', data.driver.birthday],
                ['Commentaire', data.driver.comment],
            ].map(([k, v]) => v ? <div key={k} className="detail-row"><div className="label">{k}</div><div>{v}</div></div> : null)}
            {data.vehicles?.length ? (
                <>
                    <h4 className="font-semibold mt-4 mb-2">Véhicules</h4>
                    <ul className="text-sm space-y-1">
                        {data.vehicles.map(v => <li key={v.id}>{v.brand} {v.model} · {v.plate} · {v.color}</li>)}
                    </ul>
                </>
            ) : null}
        </Modal>
    );
}

// ============================================================================
// CUSTOMERS
// ============================================================================
function PageCustomers() {
    return <CrudView resource="customers" title="Clients"
        fields={[
            { key: 'firstname', label: 'Prénom' },
            { key: 'lastname',  label: 'Nom' },
            { key: 'email',     label: 'Email' },
            { key: 'mobile',    label: 'Mobile' },
            { key: 'address',   label: 'Adresse' },
            { key: 'is_vip',    label: 'VIP', type: 'bool' },
            { key: 'is_blocked',label: 'Bloqué', type: 'bool' },
            { key: 'bookings_count', label: 'Courses' },
            { key: 'total_spent', label: 'CA total' },
            { key: 'notes', label: 'Notes', type: 'textarea' },
        ]}
        listColumns={[
            { key: 'lastname', label: 'Nom' }, { key: 'firstname', label: 'Prénom' },
            { key: 'email', label: 'Email' }, { key: 'mobile', label: 'Mobile' },
            { key: 'bookings_count', label: 'Courses' }, { key: 'total_spent', label: 'CA' },
        ]}
    />;
}

// ============================================================================
// CENTRALE — info / branding / params
// ============================================================================
function PageCentraleForm({ section }) {
    const [w, setW] = useState(null);
    const [edit, setEdit] = useState({});
    const [err, setErr] = useState('');
    useEffect(() => {
        MyProAPI.websiteMe().then(d => { setW(d.website); setEdit(d.website); }).catch(e => setErr(e.message));
    }, []);
    async function save() {
        try {
            const patch = {};
            ALL_FIELDS[section].forEach(f => {
                if (edit[f.key] !== w[f.key]) patch[f.key] = edit[f.key];
            });
            if (!Object.keys(patch).length) { toast('Aucun changement'); return; }
            await MyProAPI.websiteUpdate(patch);
            const fresh = await MyProAPI.websiteMe();
            setW(fresh.website); setEdit(fresh.website);
            toast('Enregistré');
        } catch (e) { toast(e.message, 'error'); }
    }

    if (err) return <div className="card text-red-600">{err}</div>;
    if (!w) return <div className="flex justify-center py-10"><div className="loading-spinner"></div></div>;

    const titles = { info: 'Informations centrale', branding: 'Branding & affichage', params: 'Paramètres' };
    const fields = ALL_FIELDS[section];
    return (
        <div>
            <h1 className="text-2xl font-bold mb-4">{titles[section]}</h1>
            <div className="card">
                <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
                    {fields.map(f => (
                        <Field key={f.key} label={f.label}>
                            {f.type === 'textarea' ? <TextArea value={edit[f.key]} onChange={v => setEdit(s => ({ ...s, [f.key]: v }))} />
                             : f.type === 'bool' ? <Checkbox value={edit[f.key]} onChange={v => setEdit(s => ({ ...s, [f.key]: v }))} />
                             : f.type === 'select' ? <Select value={edit[f.key]} onChange={v => setEdit(s => ({ ...s, [f.key]: v }))} options={f.options} />
                             : f.type === 'color' ? <input type="color" value={edit[f.key] || '#4f46e5'} onChange={e => setEdit(s => ({ ...s, [f.key]: e.target.value }))} className="input" style={{ height: 42 }} />
                             : <TextInput type={f.type || 'text'} value={edit[f.key]} onChange={v => setEdit(s => ({ ...s, [f.key]: v }))} />}
                        </Field>
                    ))}
                </div>
                <button className="btn btn-primary mt-4" onClick={save}><i className="fas fa-save"></i> Enregistrer</button>
            </div>
        </div>
    );
}

const ALL_FIELDS = {
    info: [
        { key: 'company',          label: 'Raison sociale' },
        { key: 'company_name',     label: 'Nom commercial' },
        { key: 'display_name',     label: 'Nom affiché' },
        { key: 'description',      label: 'Description', type: 'textarea' },
        { key: 'address',          label: 'Adresse' },
        { key: 'phone',            label: 'Téléphone' },
        { key: 'phone_booking',    label: 'Téléphone réservation' },
        { key: 'email_management', label: 'Email gestion' },
        { key: 'email_commercial', label: 'Email commercial' },
        { key: 'email_alert',      label: 'Email alertes' },
        { key: 'website_url',      label: 'Site web' },
        { key: 'tva_number',       label: 'Numéro TVA' },
    ],
    branding: [
        { key: 'color',         label: 'Couleur principale', type: 'color' },
        { key: 'logo_url',      label: 'URL logo' },
        { key: 'logo_dark_url', label: 'URL logo (dark)' },
        { key: 'img',           label: 'URL image header' },
        { key: 'booking_widget_url', label: 'URL widget de réservation' },
        { key: 'custom_css',    label: 'CSS personnalisé', type: 'textarea' },
        { key: 'sms_signature', label: 'Signature SMS', type: 'textarea' },
        { key: 'email_signature', label: 'Signature email', type: 'textarea' },
    ],
    params: [
        { key: 'tva_rate',  label: 'Taux TVA (%)', type: 'number' },
        { key: 'currency',  label: 'Devise' },
        { key: 'timezone',  label: 'Fuseau horaire' },
        { key: 'language',  label: 'Langue', type: 'select',
          options: [{ value: 'fr', label: 'Français' }, { value: 'en', label: 'English' },
                    { value: 'de', label: 'Deutsch' }, { value: 'it', label: 'Italiano' }] },
        { key: 'sms_alert', label: 'Alerte SMS bas (seuil)', type: 'number' },
    ],
};

// ============================================================================
// SMS Orders
// ============================================================================
function PageSmsOrders() {
    const [data, setData] = useState(null);
    useEffect(() => { MyProAPI.smsOrders().then(d => setData(d.orders || [])); }, []);
    return (
        <div>
            <h1 className="text-2xl font-bold mb-4">Commandes SMS</h1>
            <div className="card mb-4">
                <div className="flex items-center justify-between">
                    <div>
                        <div className="font-semibold mb-1">Recharger votre compte</div>
                        <div className="text-sm text-gray-500">Choisissez un pack pour augmenter votre solde SMS.</div>
                    </div>
                    <button className="btn btn-primary" onClick={() => toast('Bientôt disponible')}>Choisir un pack</button>
                </div>
            </div>
            {!data ? <div className="flex justify-center py-10"><div className="loading-spinner"></div></div>
             : (
                <div className="card" style={{ padding: 0, overflow: 'auto' }}>
                    <table className="data">
                        <thead><tr><th>Date</th><th>Pack</th><th>Statut</th></tr></thead>
                        <tbody>
                            {data.map(o => (
                                <tr key={o.id}>
                                    <td>{o.created}</td>
                                    <td>{o.sms_count} SMS</td>
                                    <td><span className={`badge ${o.is_payed ? 'badge-success' : 'badge-warn'}`}>{o.is_payed ? 'Payé' : 'En attente'}</span></td>
                                </tr>
                            ))}
                        </tbody>
                    </table>
                </div>
            )}
        </div>
    );
}

// ============================================================================
// History views (SMS, push)
// ============================================================================
function PageHistory({ kind }) {
    const [data, setData] = useState(null);
    const [err, setErr] = useState('');
    useEffect(() => {
        const fn = kind === 'sms' ? MyProAPI.smsHistory : MyProAPI.notificationsHistory;
        fn.call(MyProAPI).then(d => setData(d.items || [])).catch(e => setErr(e.message));
    }, [kind]);

    return (
        <div>
            <h1 className="text-2xl font-bold mb-4">Historique {kind === 'sms' ? 'SMS' : 'notifications push'}</h1>
            {err && <div className="card text-red-600 mb-3">{err}</div>}
            {!data ? <div className="flex justify-center py-10"><div className="loading-spinner"></div></div>
             : data.length === 0 ? <div className="card text-center text-gray-500 py-10">Aucune entrée</div>
             : (
                <div className="card" style={{ padding: 0, overflow: 'auto' }}>
                    <table className="data">
                        <thead><tr><th>Date</th><th>Destinataire</th><th>Message</th><th>Statut</th></tr></thead>
                        <tbody>
                            {data.map(it => (
                                <tr key={it.id}>
                                    <td className="whitespace-nowrap text-sm">{it.created}</td>
                                    <td className="text-sm">{it.to || '—'}</td>
                                    <td className="text-sm">{(it.message || it.body || it.subject || '').slice(0, 80)}</td>
                                    <td><span className={`badge ${it.status === 'delivered' || it.status === 'sent' ? 'badge-success' : it.status === 'failed' ? 'badge-danger' : 'badge-warn'}`}>{it.status}</span></td>
                                </tr>
                            ))}
                        </tbody>
                    </table>
                </div>
            )}
        </div>
    );
}

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

    useEffect(() => {
        (async () => {
            if (MyProAuth.isAuthenticated()) {
                const u = await MyProAuth.refreshUser().catch(() => null);
                if (u && u.type === 'website') setUser(u);
                else MyProAuth.clearAuth();
            }
            setLoading(false);
        })();
    }, []);

    if (loading) return <div className="flex items-center justify-center min-h-screen"><div className="loading-spinner"></div></div>;
    return user ? <Dashboard user={user} /> : <Login onLogged={setUser} />;
}

function Dashboard({ user }) {
    const [page, setPage] = useState('dashboard');

    let body;
    if (page === 'dashboard') body = <PageDashboard user={user} />;
    else if (page === 'calendar') body = <PageCalendar />;
    else if (page.startsWith('bookings.')) body = <PageBookings mode={page.split('.')[1]} />;
    else if (page === 'drivers')   body = <PageDrivers />;
    else if (page === 'customers') body = <PageCustomers />;
    else if (page === 'sms')       body = <PageSmsOrders />;
    else if (page === 'sms-history') body = <PageHistory kind="sms" />;
    else if (page === 'notif-history') body = <PageHistory kind="notif" />;
    else if (page.startsWith('centrale.')) body = <PageCentraleForm section={page.split('.')[1]} />;
    else if (page === 'ranges') body = <CrudView resource="ranges" title="Gammes" fields={[
        { key: 'label', label: 'Libellé' }, { key: 'description', label: 'Description', type: 'textarea' },
        { key: 'seats_max', label: 'Sièges max', type: 'number' }, { key: 'luggage_max', label: 'Bagages max', type: 'number' },
        { key: 'price_per_km', label: 'Prix/km', type: 'number' }, { key: 'price_per_hour', label: 'Prix/heure', type: 'number' },
        { key: 'price_minimum', label: 'Prix mini', type: 'number' }, { key: 'is_active', label: 'Actif', type: 'bool' },
    ]} />;
    else if (page === 'centralprices') body = <CrudView resource="centralprices" title="Tarifs centrale" fields={[
        { key: 'label', label: 'Libellé' }, { key: 'range_id', label: 'Gamme (id)', type: 'number' },
        { key: 'base_price', label: 'Base', type: 'number' }, { key: 'price_per_km', label: 'Prix/km', type: 'number' },
        { key: 'price_per_minute', label: 'Prix/min', type: 'number' }, { key: 'price_per_wait_minute', label: 'Prix/min attente', type: 'number' },
        { key: 'minimum_price', label: 'Prix mini', type: 'number' },
        { key: 'night_extra_percent', label: '% nuit', type: 'number' }, { key: 'weekend_extra_percent', label: '% weekend', type: 'number' },
        { key: 'is_active', label: 'Actif', type: 'bool' },
    ]} />;
    else if (page === 'dispositions') body = <CrudView resource="dispositions" title="Forfaits horaires" fields={[
        { key: 'label', label: 'Libellé' }, { key: 'description', label: 'Description', type: 'textarea' },
        { key: 'range_id', label: 'Gamme (id)', type: 'number' },
        { key: 'duration_hours', label: 'Durée (h)', type: 'number' }, { key: 'distance_included_km', label: 'Km inclus', type: 'number' },
        { key: 'price', label: 'Prix forfait', type: 'number' },
        { key: 'extra_km_price', label: 'Prix km en plus', type: 'number' }, { key: 'extra_hour_price', label: 'Prix heure en plus', type: 'number' },
        { key: 'is_active', label: 'Actif', type: 'bool' },
    ]} />;
    else if (page === 'mixeddiscounts') body = <CrudView resource="mixeddiscounts" title="Forfaits par zones" fields={[
        { key: 'label', label: 'Libellé' }, { key: 'description', label: 'Description', type: 'textarea' },
        { key: 'price', label: 'Prix', type: 'number' }, { key: 'range_id', label: 'Gamme (id)', type: 'number' },
        { key: 'origin_json', label: 'Zone origine (JSON)', type: 'textarea' },
        { key: 'destination_json', label: 'Zone destination (JSON)', type: 'textarea' },
        { key: 'is_active', label: 'Actif', type: 'bool' },
    ]} />;
    else if (page === 'promocodes') body = <CrudView resource="promocodes" title="Codes promo" fields={[
        { key: 'code', label: 'Code' }, { key: 'label', label: 'Libellé' },
        { key: 'discount_type', label: 'Type', type: 'select', options: [{ value: 'percent', label: '%' }, { value: 'amount', label: 'CHF' }] },
        { key: 'discount_value', label: 'Valeur', type: 'number' }, { key: 'min_amount', label: 'Mini course', type: 'number' },
        { key: 'max_uses', label: 'Utilisations max (0=illimité)', type: 'number' },
        { key: 'used_count', label: 'Utilisé', type: 'number' },
        { key: 'valid_from', label: 'Valable du', type: 'date' }, { key: 'valid_until', label: 'Valable au', type: 'date' },
        { key: 'is_active', label: 'Actif', type: 'bool' },
    ]} />;
    else if (page === 'offers') body = <CrudView resource="offers" title="Offres / remises zones" fields={[
        { key: 'label', label: 'Libellé' }, { key: 'description', label: 'Description', type: 'textarea' },
        { key: 'discount_percent', label: 'Remise %', type: 'number' },
        { key: 'zone_zipcodes', label: 'Codes postaux (CSV)' },
        { key: 'is_active', label: 'Actif', type: 'bool' },
    ]} />;
    else if (page === 'options') body = <CrudView resource="options" title="Suppléments" fields={[
        { key: 'label', label: 'Libellé' }, { key: 'description', label: 'Description', type: 'textarea' },
        { key: 'icon', label: 'Icône (Font Awesome)' }, { key: 'price', label: 'Prix', type: 'number' },
        { key: 'is_per_seat', label: 'Par siège', type: 'bool' },
        { key: 'sort_order', label: 'Ordre', type: 'number' }, { key: 'is_active', label: 'Actif', type: 'bool' },
    ]} />;
    else if (page === 'vehicles') body = <CrudView resource="vehicles" title="Véhicules" fields={[
        { key: 'brand', label: 'Marque' }, { key: 'model', label: 'Modèle' },
        { key: 'plate', label: 'Plaque' }, { key: 'color', label: 'Couleur' },
        { key: 'seats', label: 'Sièges', type: 'number' },
        { key: 'driver_id', label: 'Chauffeur (id)', type: 'number' },
        { key: 'is_active', label: 'Actif', type: 'bool' },
    ]} />;
    else if (page === 'invoices') body = <CrudView resource="invoices" title="Factures" fields={[
        { key: 'invoice_number', label: 'N° facture' },
        { key: 'booking_id', label: 'Course (id)', type: 'number' }, { key: 'customer_id', label: 'Client (id)', type: 'number' },
        { key: 'issued_date', label: 'Émise le', type: 'date' }, { key: 'due_date', label: 'Échéance', type: 'date' },
        { key: 'amount_ht', label: 'HT', type: 'number' }, { key: 'amount_tva', label: 'TVA', type: 'number' },
        { key: 'amount_ttc', label: 'TTC', type: 'number' }, { key: 'tva_rate', label: '% TVA', type: 'number' },
        { key: 'currency', label: 'Devise' },
        { key: 'status', label: 'Statut', type: 'select', options: ['draft','sent','paid','overdue','cancelled'].map(s => ({ value: s, label: s })) },
        { key: 'paid_at', label: 'Payée le', type: 'datetime' }, { key: 'pdf_url', label: 'URL PDF' },
        { key: 'notes', label: 'Notes', type: 'textarea' },
    ]}
        listColumns={[
            { key: 'invoice_number', label: 'N°' }, { key: 'issued_date', label: 'Émise', type: 'date' },
            { key: 'amount_ttc', label: 'TTC' }, { key: 'currency', label: '' },
            { key: 'status', label: 'Statut' },
        ]}
    />;
    else if (page === 'payments') body = <CrudView resource="payments" title="Paiements" fields={[
        { key: 'booking_id', label: 'Course (id)', type: 'number' }, { key: 'invoice_id', label: 'Facture (id)', type: 'number' },
        { key: 'provider', label: 'Provider' }, { key: 'transaction_id', label: 'Transaction ID' },
        { key: 'amount', label: 'Montant', type: 'number' }, { key: 'currency', label: 'Devise' },
        { key: 'method', label: 'Méthode' },
        { key: 'status', label: 'Statut', type: 'select', options: ['pending','succeeded','failed','refunded'].map(s => ({ value: s, label: s })) },
        { key: 'paid_at', label: 'Payée le', type: 'datetime' },
        { key: 'error_message', label: 'Erreur', type: 'textarea' },
    ]}
        listColumns={[
            { key: 'created', label: 'Date' }, { key: 'method', label: 'Méthode' },
            { key: 'amount', label: 'Montant' }, { key: 'currency', label: '' }, { key: 'status', label: 'Statut' },
        ]}
    />;
    else if (page === 'partnerships') body = <CrudView resource="partnerships" title="Partenariats" fields={[
        { key: 'slug', label: 'Slug' }, { key: 'label', label: 'Libellé' },
        { key: 'description', label: 'Description', type: 'textarea' },
        { key: 'partner_url', label: 'URL partenaire' },
        { key: 'commission_percent', label: 'Commission %', type: 'number' },
        { key: 'contact_name', label: 'Contact' }, { key: 'contact_email', label: 'Email' }, { key: 'contact_phone', label: 'Téléphone' },
        { key: 'is_active', label: 'Actif', type: 'bool' },
    ]} />;
    else if (page === 'blockdates') body = <CrudView resource="blockdates" title="Dates de fermeture" fields={[
        { key: 'label', label: 'Libellé' },
        { key: 'date_from', label: 'Du', type: 'date' }, { key: 'date_to', label: 'Au', type: 'date' },
        { key: 'reason', label: 'Raison', type: 'textarea' },
    ]} />;
    else if (page === 'texts') body = <CrudView resource="texts" title="Templates emails / SMS / push" fields={[
        { key: 'code', label: 'Code (ex: booking_confirmation)' },
        { key: 'channel', label: 'Canal', type: 'select', options: [{ value: 'email', label: 'Email' }, { value: 'sms', label: 'SMS' }, { value: 'push', label: 'Push' }] },
        { key: 'language', label: 'Langue', type: 'select', options: [{ value: 'fr', label: 'fr' }, { value: 'en', label: 'en' }, { value: 'de', label: 'de' }, { value: 'it', label: 'it' }] },
        { key: 'subject', label: 'Sujet (email)' },
        { key: 'body', label: 'Corps', type: 'textarea', rows: 8 },
        { key: 'is_active', label: 'Actif', type: 'bool' },
    ]}
        listColumns={[
            { key: 'code', label: 'Code' }, { key: 'channel', label: 'Canal' },
            { key: 'language', label: 'Lang' }, { key: 'subject', label: 'Sujet' },
            { key: 'is_active', label: 'Actif', type: 'bool' },
        ]}
    />;
    else body = <div className="card text-gray-500">Page : {page}</div>;

    return <Layout user={user} page={page} setPage={setPage}>{body}</Layout>;
}

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