import React, { useEffect, useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import Layout from '../components/Layout';
import { api } from '../lib/api';
import { useAuth } from '../context/AuthContext';
import { toast } from 'sonner';
import { ArrowLeft, Upload, PlayCircle, Undo2, Trash2, CheckCircle2, AlertCircle, Loader2, Package, Plus, Pin, PinOff, Pencil, Check, X as XIcon, StickyNote } from 'lucide-react';

const STATUS_COLOR = {
    uploaded:    'bg-slate-100 text-slate-700 border-slate-300',
    installing:  'bg-amber-50 text-amber-700 border-amber-300',
    installed:   'bg-emerald-50 text-emerald-700 border-emerald-300',
    failed:      'bg-rose-50 text-rose-700 border-rose-300',
    rolled_back: 'bg-indigo-50 text-indigo-700 border-indigo-300',
};
const STATUS_LABEL = {
    uploaded:    'Uploadé',
    installing:  'Installation…',
    installed:   'Installé',
    failed:      'Échec',
    rolled_back: 'Rollback',
};

// Mémo : palette de couleurs (clé = valeur DB, libellé pour l'UI)
const MEMO_COLORS = [
    { key: 'slate',  label: 'Info',      dot: 'bg-slate-400',   card: 'border-slate-300 bg-slate-50' },
    { key: 'red',    label: 'Urgent',    dot: 'bg-rose-500',    card: 'border-rose-300 bg-rose-50' },
    { key: 'orange', label: 'Important', dot: 'bg-orange-500',  card: 'border-orange-300 bg-orange-50' },
    { key: 'yellow', label: 'À faire',   dot: 'bg-yellow-400',  card: 'border-yellow-300 bg-yellow-50' },
    { key: 'green',  label: 'Fait',      dot: 'bg-emerald-500', card: 'border-emerald-300 bg-emerald-50' },
    { key: 'blue',   label: 'Idée',      dot: 'bg-sky-500',     card: 'border-sky-300 bg-sky-50' },
    { key: 'purple', label: 'Plus tard', dot: 'bg-purple-500',  card: 'border-purple-300 bg-purple-50' },
];
const colorCfg = (k) => MEMO_COLORS.find((c) => c.key === k) || MEMO_COLORS[0];

function formatSize(b) {
    if (!b) return '—';
    if (b < 1024) return `${b} B`;
    if (b < 1024 * 1024) return `${(b / 1024).toFixed(1)} Ko`;
    return `${(b / 1024 / 1024).toFixed(2)} Mo`;
}
function formatDate(s) {
    if (!s) return '—';
    try {
        const d = new Date(s);
        return d.toLocaleString('fr-FR', { day: '2-digit', month: '2-digit', year: '2-digit', hour: '2-digit', minute: '2-digit' });
    } catch { return s; }
}

// =============================================================================
// Mémo — section "Mes idées / notes"
// =============================================================================
function MemosSection() {
    const [memos, setMemos] = useState([]);
    const [loading, setLoading] = useState(true);
    const [draftContent, setDraftContent] = useState('');
    const [draftColor, setDraftColor] = useState('slate');
    const [editing, setEditing] = useState(null); // id en cours d'édition
    const [editContent, setEditContent] = useState('');

    const load = async () => {
        try {
            const r = await api.get('/admin/memos');
            setMemos(r.data.items || []);
        } catch (e) {
            toast.error('Impossible de charger les mémos');
        } finally { setLoading(false); }
    };
    useEffect(() => { load(); }, []);

    const add = async () => {
        const c = draftContent.trim();
        if (!c) return;
        try {
            await api.post('/admin/memos', { content: c, color: draftColor });
            setDraftContent('');
            await load();
        } catch (e) { toast.error(e.response?.data?.detail || 'Erreur ajout'); }
    };

    const patchMemo = async (id, patch) => {
        try {
            await api.patch(`/admin/memos/${id}`, patch);
            await load();
        } catch (e) { toast.error(e.response?.data?.detail || 'Erreur'); }
    };

    const deleteMemo = async (id) => {
        if (!confirm('Supprimer ce mémo ?')) return;
        try {
            await api.delete(`/admin/memos/${id}`);
            await load();
        } catch (e) { toast.error('Erreur suppression'); }
    };

    const startEdit = (m) => { setEditing(m.id); setEditContent(m.content); };
    const cancelEdit = () => { setEditing(null); setEditContent(''); };
    const saveEdit = async () => {
        if (!editContent.trim()) { cancelEdit(); return; }
        await patchMemo(editing, { content: editContent.trim() });
        cancelEdit();
    };

    return (
        <div data-testid="memos-section" className="rounded-lg border border-slate-200 bg-white overflow-hidden">
            <div className="px-4 py-3 border-b border-slate-200 bg-slate-50 flex items-center gap-2">
                <StickyNote className="h-4 w-4 text-stef" />
                <h2 className="font-bold text-sm text-slate-700">Mes idées / notes pour les futures MAJ</h2>
                <span className="ml-auto text-[11px] text-slate-400">{memos.length} note(s)</span>
            </div>

            {/* Composer */}
            <div className="p-4 border-b border-slate-100 bg-slate-50/30">
                <textarea
                    data-testid="memo-input"
                    value={draftContent}
                    onChange={(e) => setDraftContent(e.target.value)}
                    placeholder="Note rapide : idée, bug à fixer, fonctionnalité à ajouter…"
                    rows={2}
                    className="w-full rounded-md border border-slate-300 bg-white px-3 py-2 text-sm focus:border-stef focus:ring-2 focus:ring-stef/20 outline-none transition resize-none"
                    onKeyDown={(e) => {
                        if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) add();
                    }}
                />
                <div className="flex items-center justify-between gap-2 mt-2 flex-wrap">
                    <div className="flex items-center gap-1.5 flex-wrap">
                        {MEMO_COLORS.map((c) => (
                            <button
                                key={c.key}
                                type="button"
                                data-testid={`color-${c.key}`}
                                onClick={() => setDraftColor(c.key)}
                                title={c.label}
                                className={`h-6 w-6 rounded-full ${c.dot} ring-2 ring-offset-1 transition ${
                                    draftColor === c.key ? 'ring-slate-900' : 'ring-transparent'
                                }`}
                            />
                        ))}
                        <span className="text-[11px] text-slate-500 ml-1.5 font-medium">
                            {colorCfg(draftColor).label}
                        </span>
                    </div>
                    <button
                        type="button"
                        data-testid="memo-add-btn"
                        onClick={add}
                        disabled={!draftContent.trim()}
                        className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-md bg-stef text-white text-xs font-bold hover:bg-stef/90 disabled:opacity-40 disabled:cursor-not-allowed transition"
                    >
                        <Plus className="h-3.5 w-3.5" /> Ajouter
                    </button>
                </div>
                <div className="text-[10px] text-slate-400 mt-1.5">
                    Astuce : Ctrl+Entrée pour ajouter rapidement
                </div>
            </div>

            {/* Liste */}
            {loading ? (
                <div className="p-6 text-center text-slate-400 italic text-sm">Chargement…</div>
            ) : memos.length === 0 ? (
                <div className="p-6 text-center text-slate-400 italic text-sm">
                    Aucune note pour l'instant. Note ta première idée ci-dessus 👆
                </div>
            ) : (
                <div className="p-3 grid grid-cols-1 md:grid-cols-2 gap-2">
                    {memos.map((m) => {
                        const c = colorCfg(m.color);
                        const isEdit = editing === m.id;
                        return (
                            <div
                                key={m.id}
                                data-testid={`memo-${m.id}`}
                                className={`group rounded-md border-2 p-3 ${c.card} transition hover:shadow-sm relative`}
                            >
                                {/* Toolbar */}
                                <div className="absolute top-2 right-2 flex items-center gap-0.5 opacity-0 group-hover:opacity-100 transition">
                                    {!isEdit && (
                                        <>
                                            <button
                                                type="button"
                                                onClick={() => patchMemo(m.id, { pinned: !m.pinned })}
                                                title={m.pinned ? 'Désépingler' : 'Épingler en haut'}
                                                className="h-6 w-6 inline-flex items-center justify-center rounded hover:bg-white/70 text-slate-500 hover:text-stef"
                                            >
                                                {m.pinned ? <Pin className="h-3.5 w-3.5 fill-current" /> : <PinOff className="h-3.5 w-3.5" />}
                                            </button>
                                            <button
                                                type="button"
                                                onClick={() => startEdit(m)}
                                                title="Modifier"
                                                className="h-6 w-6 inline-flex items-center justify-center rounded hover:bg-white/70 text-slate-500 hover:text-stef"
                                            >
                                                <Pencil className="h-3.5 w-3.5" />
                                            </button>
                                            <button
                                                type="button"
                                                onClick={() => deleteMemo(m.id)}
                                                title="Supprimer"
                                                className="h-6 w-6 inline-flex items-center justify-center rounded hover:bg-white/70 text-slate-500 hover:text-rose-600"
                                            >
                                                <Trash2 className="h-3.5 w-3.5" />
                                            </button>
                                        </>
                                    )}
                                </div>

                                {/* Indicateur épinglé */}
                                {m.pinned && !isEdit && (
                                    <div className="absolute top-2 left-2 text-stef" title="Épinglé">
                                        <Pin className="h-3 w-3 fill-current" />
                                    </div>
                                )}

                                {/* Contenu */}
                                {isEdit ? (
                                    <>
                                        <textarea
                                            value={editContent}
                                            onChange={(e) => setEditContent(e.target.value)}
                                            rows={3}
                                            autoFocus
                                            className="w-full rounded-md border border-slate-300 bg-white px-2 py-1.5 text-sm focus:border-stef focus:ring-2 focus:ring-stef/20 outline-none transition resize-none"
                                        />
                                        <div className="flex items-center justify-end gap-1 mt-2">
                                            <button
                                                type="button"
                                                onClick={cancelEdit}
                                                className="inline-flex items-center gap-1 px-2 py-1 rounded text-[11px] font-semibold text-slate-600 hover:bg-white/70"
                                            >
                                                <XIcon className="h-3 w-3" /> Annuler
                                            </button>
                                            <button
                                                type="button"
                                                onClick={saveEdit}
                                                className="inline-flex items-center gap-1 px-2 py-1 rounded text-[11px] font-bold text-white bg-stef hover:bg-stef/90"
                                            >
                                                <Check className="h-3 w-3" /> Sauver
                                            </button>
                                        </div>
                                    </>
                                ) : (
                                    <div className={`whitespace-pre-wrap text-sm text-slate-800 leading-relaxed ${m.pinned ? 'pl-4' : ''}`}>
                                        {m.content}
                                    </div>
                                )}

                                {/* Footer */}
                                <div className="flex items-center justify-between gap-2 mt-2 pt-2 border-t border-slate-200/50">
                                    {/* Color picker inline (mini) */}
                                    <div className="flex items-center gap-1">
                                        {MEMO_COLORS.map((cc) => (
                                            <button
                                                key={cc.key}
                                                type="button"
                                                onClick={() => patchMemo(m.id, { color: cc.key })}
                                                title={cc.label}
                                                className={`h-3 w-3 rounded-full ${cc.dot} ring-1 transition ${
                                                    m.color === cc.key ? 'ring-slate-900 ring-offset-1' : 'ring-transparent hover:ring-slate-300'
                                                }`}
                                            />
                                        ))}
                                    </div>
                                    <div className="text-[10px] text-slate-500">
                                        {formatDate(m.updated_at)}
                                    </div>
                                </div>
                            </div>
                        );
                    })}
                </div>
            )}
        </div>
    );
}

// =============================================================================
// UpdatesPanel — réutilisable comme route OU comme tab panel
// =============================================================================
export function UpdatesPanel() {
    const [history, setHistory] = useState([]);
    const [loading, setLoading] = useState(true);
    const [uploading, setUploading] = useState(false);
    const [drag, setDrag] = useState(false);
    const [activeUid, setActiveUid] = useState(null);
    const [logs, setLogs] = useState([]);
    const fileInput = useRef(null);
    const pollTimer = useRef(null);

    const loadHistory = async () => {
        try {
            const r = await api.get('/admin/updates/history');
            setHistory(r.data.items || []);
        } catch (e) { toast.error('Impossible de charger l\'historique'); }
        finally { setLoading(false); }
    };
    useEffect(() => { loadHistory(); }, []);

    useEffect(() => {
        if (!activeUid) return;
        let stopped = false;
        const tick = async () => {
            try {
                const r = await api.get(`/admin/updates/${activeUid}/log`);
                if (stopped) return;
                setLogs(r.data.lines || []);
                if (['installed', 'failed', 'rolled_back'].includes(r.data.status)) {
                    await loadHistory();
                    if (r.data.status === 'installed') {
                        toast.success('✅ Mise à jour installée — l\'app va redémarrer');
                    } else if (r.data.status === 'failed') {
                        toast.error('❌ Échec de l\'installation');
                    }
                    setTimeout(() => { if (!stopped) setActiveUid(null); }, 3000);
                    return;
                }
            } catch (e) { /* backend restart in progress */ }
            pollTimer.current = setTimeout(tick, 1200);
        };
        tick();
        return () => {
            stopped = true;
            if (pollTimer.current) clearTimeout(pollTimer.current);
        };
    }, [activeUid]);

    const handleFile = async (file) => {
        if (!file) return;
        if (!file.name.toLowerCase().endsWith('.zip')) {
            toast.error('Seuls les fichiers ZIP sont acceptés');
            return;
        }
        setUploading(true);
        try {
            const fd = new FormData();
            fd.append('file', file);
            const r = await api.post('/admin/updates/upload', fd, {
                headers: { 'Content-Type': 'multipart/form-data' },
            });
            toast.success(`📦 ${r.data.filename} uploadé (${r.data.files} fichiers détectés)`);
            await loadHistory();
        } catch (e) { toast.error(e.response?.data?.detail || 'Erreur upload'); }
        finally {
            setUploading(false);
            if (fileInput.current) fileInput.current.value = '';
        }
    };

    const onDrop = (e) => {
        e.preventDefault();
        setDrag(false);
        const f = e.dataTransfer.files?.[0];
        if (f) handleFile(f);
    };

    const install = async (uid) => {
        if (!confirm('Lancer l\'installation ? Les services vont redémarrer (~10 sec d\'indisponibilité).')) return;
        try {
            await api.post(`/admin/updates/${uid}/install`);
            setActiveUid(uid); setLogs([]);
            toast.info('🚀 Installation en cours…');
        } catch (e) { toast.error(e.response?.data?.detail || 'Erreur'); }
    };

    const rollback = async (uid) => {
        if (!confirm('Rollback vers la version précédente ? Les services vont redémarrer.')) return;
        try {
            await api.post(`/admin/updates/${uid}/rollback`);
            setActiveUid(uid); setLogs([]);
            toast.info('⏪ Rollback en cours…');
        } catch (e) { toast.error(e.response?.data?.detail || 'Erreur'); }
    };

    const deleteUpdate = async (uid) => {
        if (!confirm('Supprimer cette entrée et son backup ?')) return;
        try {
            await api.delete(`/admin/updates/${uid}`);
            await loadHistory();
            toast.success('Supprimé');
        } catch (e) { toast.error(e.response?.data?.detail || 'Erreur'); }
    };

    return (
        <div className="space-y-6">
            {/* Drop zone */}
            <div
                data-testid="upload-zone"
                onDragOver={(e) => { e.preventDefault(); setDrag(true); }}
                onDragLeave={() => setDrag(false)}
                onDrop={onDrop}
                onClick={() => fileInput.current?.click()}
                className={`rounded-lg border-2 border-dashed p-8 text-center cursor-pointer transition ${
                    drag ? 'border-stef bg-stef/5' : 'border-slate-300 bg-white hover:border-stef/50'
                } ${uploading ? 'opacity-60 pointer-events-none' : ''}`}
            >
                <input
                    ref={fileInput}
                    data-testid="file-input"
                    type="file"
                    accept=".zip,application/zip"
                    className="hidden"
                    onChange={(e) => handleFile(e.target.files?.[0])}
                />
                {uploading ? (
                    <div className="flex items-center justify-center gap-2 text-stef">
                        <Loader2 className="h-5 w-5 animate-spin" /> Upload en cours…
                    </div>
                ) : (
                    <>
                        <Upload className="mx-auto h-10 w-10 text-slate-400" />
                        <p className="mt-2 text-sm font-semibold text-slate-700">
                            Glisse ton ZIP ici, ou clique pour parcourir
                        </p>
                        <p className="text-xs text-slate-500 mt-1">Backup auto · Rollback en 1 clic · Restart auto</p>
                    </>
                )}
            </div>

            {/* Log en direct */}
            {activeUid && (
                <div data-testid="install-log" className="rounded-lg border border-slate-200 bg-slate-900 text-slate-100 p-4 font-mono text-xs">
                    <div className="flex items-center justify-between mb-2">
                        <div className="flex items-center gap-2 text-emerald-400">
                            <Loader2 className="h-4 w-4 animate-spin" />
                            Installation #{activeUid} en direct
                        </div>
                        <button onClick={() => setActiveUid(null)} className="text-slate-400 hover:text-white text-xs">Masquer</button>
                    </div>
                    <div className="max-h-64 overflow-y-auto space-y-0.5">
                        {logs.length === 0 ? (
                            <div className="text-slate-500 italic">En attente du démarrage…</div>
                        ) : (
                            logs.map((l, i) => <div key={i} className="whitespace-pre-wrap">{l}</div>)
                        )}
                    </div>
                </div>
            )}

            {/* Historique */}
            <div className="rounded-lg border border-slate-200 bg-white overflow-hidden">
                <div className="px-4 py-3 border-b border-slate-200 bg-slate-50">
                    <h2 className="font-bold text-sm text-slate-700">Historique des mises à jour</h2>
                </div>
                {loading ? (
                    <div className="p-6 text-center text-slate-400 italic text-sm">Chargement…</div>
                ) : history.length === 0 ? (
                    <div className="p-6 text-center text-slate-400 italic text-sm">Aucune mise à jour pour l'instant.</div>
                ) : (
                    <div className="divide-y divide-slate-100">
                        {history.map((h) => (
                            <div key={h.id} data-testid={`update-row-${h.id}`} className="p-4 flex flex-col sm:flex-row sm:items-center justify-between gap-3 hover:bg-slate-50/50 transition">
                                <div className="min-w-0 flex-1">
                                    <div className="flex items-center gap-2 flex-wrap">
                                        <span className="font-bold text-sm text-slate-900 truncate">{h.filename}</span>
                                        <span className={`px-2 py-0.5 rounded-full text-[10px] font-bold border ${STATUS_COLOR[h.status] || STATUS_COLOR.uploaded}`}>
                                            {STATUS_LABEL[h.status] || h.status}
                                        </span>
                                        {h.status === 'installed' && <CheckCircle2 className="h-4 w-4 text-emerald-500" />}
                                        {h.status === 'failed' && <AlertCircle className="h-4 w-4 text-rose-500" />}
                                    </div>
                                    <div className="text-[11px] text-slate-500 mt-1 font-mono">
                                        #{h.id} · {formatSize(h.size_bytes)} · {h.files_count} fichiers · par <strong>{h.uploaded_by}</strong>
                                    </div>
                                    <div className="text-[11px] text-slate-400 mt-0.5">
                                        Uploadé {formatDate(h.uploaded_at)}{h.finished_at ? ` · Terminé ${formatDate(h.finished_at)}` : ''}
                                    </div>
                                    {h.error && (
                                        <div className="text-[11px] text-rose-600 mt-1 font-mono break-all">⚠ {h.error}</div>
                                    )}
                                </div>
                                <div className="flex items-center gap-1.5 flex-wrap">
                                    {(h.status === 'uploaded' || h.status === 'failed') && (
                                        <button
                                            data-testid={`install-btn-${h.id}`}
                                            onClick={() => install(h.id)}
                                            className="inline-flex items-center gap-1 px-3 py-1.5 rounded-md bg-stef text-white text-xs font-bold hover:bg-stef/90 transition"
                                        >
                                            <PlayCircle className="h-3.5 w-3.5" /> Installer
                                        </button>
                                    )}
                                    {h.has_backup && h.status === 'installed' && (
                                        <button
                                            data-testid={`rollback-btn-${h.id}`}
                                            onClick={() => rollback(h.id)}
                                            className="inline-flex items-center gap-1 px-3 py-1.5 rounded-md bg-indigo-100 text-indigo-700 text-xs font-bold hover:bg-indigo-200 transition"
                                        >
                                            <Undo2 className="h-3.5 w-3.5" /> Rollback
                                        </button>
                                    )}
                                    <button
                                        data-testid={`delete-btn-${h.id}`}
                                        onClick={() => deleteUpdate(h.id)}
                                        className="inline-flex items-center gap-1 px-2 py-1.5 rounded-md text-slate-400 hover:bg-rose-50 hover:text-rose-600 transition"
                                        title="Supprimer cette entrée + backup"
                                    >
                                        <Trash2 className="h-3.5 w-3.5" />
                                    </button>
                                </div>
                            </div>
                        ))}
                    </div>
                )}
            </div>

            {/* Mémo des idées */}
            <MemosSection />

            <div className="rounded-lg border border-amber-200 bg-amber-50 p-3 text-xs text-amber-800">
                <strong>💡 Astuce :</strong> garde toujours la dernière mise à jour <em>installée</em> avec son backup — si ça plante, un seul clic sur <strong>Rollback</strong> remet l'app comme avant et redémarre les containers.
            </div>
        </div>
    );
}

// Route page (accessible via /admin/updates, optionnelle — la tab dans Paramètres
// reste le moyen principal d'accès).
export default function AdminUpdates() {
    const navigate = useNavigate();
    const { user } = useAuth();
    const canAccess = (user?.username || '').toLowerCase() === 'mathieu.u';

    if (!canAccess) {
        return (
            <Layout>
                <div className="max-w-2xl mx-auto p-6">
                    <div className="rounded-lg border border-rose-200 bg-rose-50 p-4 text-rose-700">
                        <strong>Accès refusé</strong> — page réservée au super-admin.
                    </div>
                </div>
            </Layout>
        );
    }
    return (
        <Layout>
            <div className="max-w-5xl mx-auto p-4 lg:p-6">
                <button
                    data-testid="back-btn"
                    onClick={() => navigate('/settings')}
                    className="mb-5 inline-flex items-center gap-2 text-sm font-semibold text-slate-600 hover:text-stef transition"
                >
                    <ArrowLeft className="h-4 w-4" /> Retour aux paramètres
                </button>
                <div className="mb-6">
                    <h1 className="text-2xl font-bold text-slate-900 flex items-center gap-2">
                        <Package className="h-6 w-6 text-stef" />
                        Mises à jour MyTruck
                    </h1>
                </div>
                <UpdatesPanel />
            </div>
        </Layout>
    );
}
