/**
 * =========================================================================
 * PLATEFORME ECO-PANNEAU.FR - VERSION 1.0.0
 * Composants : Modales complexes B2B (Stripe, Coffre-fort, Équipe, Partage)
 * =========================================================================
 */

const { useState, useMemo } = React;

// =========================================================================
// 1. COMPOSANT STRIPE : FORMULAIRE DE PAIEMENT
// =========================================================================

const StripePaymentForm = ({ clientSecret, onSuccess, onCancel, amountCents }) => {
    const { AlertTriangle, Loader, CreditCard } = window;
    const stripePromise = useMemo(() => window.Stripe(window.ECO_CONFIG.stripePubKey), []);
    const options = useMemo(() => ({ clientSecret, appearance: { theme: 'stripe', variables: { colorPrimary: '#10b981', borderRadius: '12px' } } }), [clientSecret]);

    const CheckoutForm = () => {
        const stripeInstance = window.ReactStripe.useStripe();
        const elements = window.ReactStripe.useElements();
        const [isProcessing, setIsProcessing] = useState(false);
        const [error, setError] = useState(null);

        const handleSubmit = async (e) => {
            e.preventDefault();
            if (!stripeInstance || !elements) return;
            setIsProcessing(true); setError(null);
            
            const { error: submitError } = await elements.submit();
            if (submitError) { setError(submitError.message); setIsProcessing(false); return; }

            const { error: confirmError, paymentIntent } = await stripeInstance.confirmPayment({
                elements, confirmParams: { return_url: window.location.href }, redirect: "if_required"
            });

            if (confirmError) { setError(confirmError.message); setIsProcessing(false); } 
            else if (paymentIntent && paymentIntent.status === "succeeded") { onSuccess(paymentIntent.id); }
            else { setError("Statut de paiement inattendu."); setIsProcessing(false); }
        };

        return (
            <form onSubmit={handleSubmit} className="space-y-6">
                <div className="bg-slate-50 p-4 rounded-xl mb-4 border border-slate-200 relative overflow-hidden">
                    <p className="text-sm font-bold text-slate-700 text-center mt-2">
                        Montant à régler : <span className="text-lg text-emerald-600 font-black">{amountCents ? (amountCents / 100).toFixed(2) : "0.00"} € TTC</span>
                    </p>
                </div>
                <window.ReactStripe.PaymentElement />
                {error && <div className="p-3 bg-red-50 text-red-600 text-sm font-bold rounded-xl border border-red-200 flex items-center gap-2"><AlertTriangle size={16}/> {error}</div>}
                <div className="flex gap-3 pt-4">
                    <button type="button" onClick={onCancel} disabled={isProcessing} title="Annuler le paiement" className="px-6 py-3 rounded-xl font-bold text-slate-500 hover:bg-slate-100 transition disabled:opacity-50">Annuler</button>
                    <button type="submit" disabled={isProcessing || !stripeInstance || !elements} title="Confirmer le paiement" className="flex-1 bg-emerald-600 text-white py-3 rounded-xl font-black uppercase tracking-widest hover:bg-emerald-700 transition shadow-lg flex items-center justify-center gap-2 disabled:opacity-50">
                        {isProcessing ? <Loader className="animate-spin w-5 h-5"/> : <CreditCard size={18}/>} Payer et activer
                    </button>
                </div>
            </form>
        );
    };

    return (
        <window.ReactStripe.Elements stripe={stripePromise} options={options}>
            <CheckoutForm />
        </window.ReactStripe.Elements>
    );
};

// =========================================================================
// 2. MODALE DE CHECKOUT (CHOIX D'OFFRE + PAIEMENT)
// =========================================================================

window.ClientCheckoutModal = ({ managingPanneau, setManagingPanneau, data, myClientData, profileData, onClose, onBackToEditor, refreshData, showToast }) => {
    const { X, AlertTriangle, Package, Loader, CreditCard } = window;
    
    const [step, setStep] = useState('select'); // 'select' ou 'payment'
    const [paymentData, setPaymentData] = useState(null);
    const [waiverAccepted, setWaiverAccepted] = useState(false);
    const [isSaving, setIsSaving] = useState(false);

    const isSuspended = myClientData.paymentStatus === 'suspended';
    const purchasesAllowed = data.settings?.allow_new_purchases !== '0';

    const pRental = data.prices?.rentalMo ?? 180;
    const pPurchase = data.prices?.purchase ?? 850;
    const pHosting = data.prices?.hostingYr ?? 1;
    const pBoardFirst = data.prices?.boardFirst ?? 250;
    const pBoardAdd = data.prices?.boardAdd ?? 150;
    const pNoAds = data.prices?.noAds ?? 150;

    const originalPanneau = data.panneaux?.find(p => p.id === managingPanneau?.id);
    const isActif = originalPanneau?.status === 'Actif';
    const originalOfferType = originalPanneau?.offerType || 'rental';
    const originalPanels = originalPanneau?.physicalPanels || 0;
    const originalHasNoAds = originalPanneau?.hasNoAds || false;

    const currentOfferType = managingPanneau?.offerType || 'rental';
    const currentPanels = managingPanneau?.physicalPanels || 0;
    const currentHasNoAds = managingPanneau?.hasNoAds || false;

    let addedPanelsCost = 0;
    if (currentPanels > originalPanels) {
        const costNew = currentPanels > 0 ? pBoardFirst + (currentPanels - 1) * pBoardAdd : 0;
        const costOld = originalPanels > 0 ? pBoardFirst + (originalPanels - 1) * pBoardAdd : 0;
        addedPanelsCost = Math.max(0, costNew - costOld);
    }

    let upfrontHT = 0;
    if (!isActif) {
        upfrontHT = (currentPanels > 0 ? pBoardFirst + (currentPanels - 1) * pBoardAdd : 0) + (currentHasNoAds ? pNoAds : 0) + (currentOfferType === 'rental' ? pRental : pPurchase + pHosting);
    } else {
        if (originalOfferType === 'rental' && currentOfferType === 'purchase') upfrontHT += pPurchase + pHosting;
        if (currentHasNoAds && !originalHasNoAds) upfrontHT += pNoAds;
        upfrontHT += addedPanelsCost;
    }

    const discountPct = myClientData.discount || 0;
    const priceMultiplier = Math.max(0, (100 - discountPct) / 100);
    const platformHasTva = data.settings?.billing_has_tva !== '0';
    const tvaMult = platformHasTva ? 1.20 : 1.00;
    const finalUpfrontTTC = upfrontHT * priceMultiplier * tvaMult;
    const finalMonthlyTTC = pRental * priceMultiplier * tvaMult;
    const remainingToPay = Math.max(0, finalUpfrontTTC - (myClientData.wallet_balance || 0));

    const handleActivationRequest = async () => {
        if(isSuspended) return showToast("Votre compte est suspendu. Veuillez régulariser vos factures.", "error");
        
        if(remainingToPay > 0 && (!waiverAccepted || !purchasesAllowed)) {
            if (!purchasesAllowed) return showToast("Les nouvelles commandes sont suspendues.", "error");
            return showToast("Veuillez accepter les conditions de rétractation.", "error");
        }
        
        setIsSaving(true);
        try {
            const payload = { panneau_id: managingPanneau.id, offer_type: managingPanneau.offerType, physical_panels: managingPanneau.physicalPanels, hasNoAds: managingPanneau.hasNoAds };
            const res = await fetch(window.ECO_CONFIG.apiBaseUrl + 'stripe/intent', { method: 'POST', body: JSON.stringify(payload) });
            const d = await res.json();
            
            if(d.status === 'success') {
                if(d.data.free_activation_required) {
                    const freeRes = await fetch(window.ECO_CONFIG.apiBaseUrl + 'panneaux/activate_free', { method: 'POST', body: JSON.stringify({ ...payload, id: managingPanneau.id, offerType: managingPanneau.offerType, physicalPanels: managingPanneau.physicalPanels, details: managingPanneau, name: managingPanneau.name }) });
                    if((await freeRes.json()).status === 'success') { 
                        showToast("Mise à jour et activation réussie !"); 
                        onClose(); 
                        refreshData(); 
                    }
                    else showToast("Erreur d'activation", "error");
                } else {
                    setPaymentData({ secret: d.data.clientSecret, subId: d.data.subscription_id, amountCents: d.data.amountCents });
                    setStep('payment');
                }
            } else showToast(d.message, 'error');
        } catch(e) { showToast("Erreur de communication", "error"); }
        setIsSaving(false);
    };

    const handlePaymentSuccess = async (pi_id) => {
        setIsSaving(true);
        try {
            const payload = { payment_intent_id: pi_id, subscription_id: paymentData?.subId, id: managingPanneau.id, offerType: managingPanneau.offerType, currentRate: managingPanneau.currentRate, physicalPanels: managingPanneau.physicalPanels, details: managingPanneau, name: managingPanneau.name };
            const res = await fetch(window.ECO_CONFIG.apiBaseUrl + 'panneaux/activate_paid', { method: 'POST', body: JSON.stringify(payload) });
            const d = await res.json();
            if(d.status === 'success') { showToast("Paiement validé !"); onClose(); refreshData(); }
            else showToast(d.message, 'error');
        } catch(e) { showToast("Erreur", "error"); }
        setIsSaving(false);
    };

    if (step === 'payment' && paymentData) {
        return (
            <window.Modal title="Activation de l'option" onClose={onClose} preventClose={isSaving} zIndex="z-[250]">
                <StripePaymentForm clientSecret={paymentData.secret} amountCents={paymentData.amountCents} onSuccess={handlePaymentSuccess} onCancel={onClose} />
            </window.Modal>
        );
    }

    return (
        <div className="fixed inset-0 bg-slate-900/80 backdrop-blur-md z-[200] animate-in fade-in duration-300 flex items-center justify-center p-4">
            <div className="w-full max-w-2xl bg-white rounded-3xl shadow-2xl flex flex-col relative overflow-hidden">
                <div className="p-6 border-b border-slate-100 bg-slate-50 flex justify-between items-center">
                    <div><h2 className="text-xl font-black text-slate-800">Choix de l'offre</h2><p className="text-xs text-slate-500 font-medium">Sélectionnez le type d'abonnement et les options matérielles.</p></div>
                    <button onClick={onBackToEditor} className="text-slate-400 hover:bg-white hover:text-slate-700 p-2 rounded-xl border border-transparent hover:border-slate-200 transition" title="Retour à l'édition"><X size={24}/></button>
                </div>
                <div className="p-6 space-y-8 overflow-y-auto custom-scrollbar max-h-[80vh]">
                    
                    <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                        <div 
                            onClick={() => setManagingPanneau({...managingPanneau, offerType: 'rental'})}
                            className={`p-6 rounded-2xl border-2 cursor-pointer transition flex flex-col justify-between ${currentOfferType === 'rental' ? 'border-emerald-500 bg-emerald-50 shadow-md' : 'border-slate-200 hover:border-emerald-200'} ${(isActif && originalOfferType === 'purchase') ? 'opacity-50 pointer-events-none' : ''}`}
                        >
                            <div>
                                <div className="flex items-center gap-2 mb-2"><div className={`w-4 h-4 rounded-full border-2 flex items-center justify-center ${currentOfferType === 'rental' ? 'border-emerald-600' : 'border-slate-300'}`}><div className={`w-2 h-2 rounded-full bg-emerald-600 transition-opacity ${currentOfferType === 'rental' ? 'opacity-100' : 'opacity-0'}`}></div></div><h4 className="font-black text-slate-800">Abonnement mensuel</h4></div>
                                <p className="text-3xl font-black text-emerald-600 my-4">{pRental} € <span className="text-sm font-bold text-slate-500">HT / mois</span></p>
                                <p className="text-sm text-slate-600 leading-relaxed font-medium">Paiement mensuel automatisé. Résiliable à tout moment, en un clic, à la fin de vos travaux. Engagement mensuel, tout mois entamé est dû.</p>
                            </div>
                        </div>
                        <div 
                            onClick={() => setManagingPanneau({...managingPanneau, offerType: 'purchase'})}
                            className={`p-6 rounded-2xl border-2 cursor-pointer transition flex flex-col justify-between ${currentOfferType === 'purchase' ? 'border-emerald-500 bg-emerald-50 shadow-md' : 'border-slate-200 hover:border-emerald-200'}`}
                        >
                            <div>
                                <div className="flex items-center gap-2 mb-2"><div className={`w-4 h-4 rounded-full border-2 flex items-center justify-center ${currentOfferType === 'purchase' ? 'border-emerald-600' : 'border-slate-300'}`}><div className={`w-2 h-2 rounded-full bg-emerald-600 transition-opacity ${currentOfferType === 'purchase' ? 'opacity-100' : 'opacity-0'}`}></div></div><h4 className="font-black text-slate-800">Achat définitif</h4></div>
                                <p className="text-3xl font-black text-emerald-600 my-4">{pPurchase} € <span className="text-sm font-bold text-slate-500">HT</span></p>
                                <p className="text-sm text-slate-600 leading-relaxed font-medium">Paiement unique sans abonnement. Le panneau numérique reste actif indéfiniment.</p>
                            </div>
                        </div>
                    </div>

                    <div className="bg-slate-50 p-6 rounded-2xl border border-slate-200 shadow-sm">
                        <h4 className="font-black text-slate-800 mb-2 flex items-center gap-2"><Package size={18} className="text-blue-600"/> Commander des panneaux physiques</h4>
                        <p className="text-sm text-slate-600 mb-6">Recevez votre panneau pré-imprimé (Format A1) sur un support rigide Akilux résistant aux intempéries, livré directement au cabinet.</p>
                        
                        <div className="flex items-center justify-between bg-white p-4 rounded-xl border border-slate-200 mb-4">
                            <div>
                                <p className="text-sm font-bold text-slate-800">Quantité souhaitée</p>
                                <p className="text-xs text-slate-500 mt-1 font-medium">{pBoardFirst}€ HT le premier, {pBoardAdd}€ HT l'unité supplémentaire.</p>
                            </div>
                            <div className="flex items-center gap-4 bg-slate-50 border border-slate-200 rounded-xl p-1 shadow-inner">
                                <button onClick={() => setManagingPanneau({...managingPanneau, physicalPanels: Math.max(originalPanels, currentPanels - 1)})} className="w-10 h-10 flex items-center justify-center rounded-lg bg-white text-slate-600 hover:text-emerald-600 shadow-sm transition font-black text-xl">-</button>
                                <span className="font-black text-xl w-6 text-center text-slate-800">{currentPanels}</span>
                                <button onClick={() => setManagingPanneau({...managingPanneau, physicalPanels: currentPanels + 1})} className="w-10 h-10 flex items-center justify-center rounded-lg bg-white text-slate-600 hover:text-emerald-600 shadow-sm transition font-black text-xl">+</button>
                            </div>
                        </div>
                        
                        {currentPanels > 0 && (
                            <div className="bg-white p-4 rounded-xl border border-slate-200 animate-in fade-in slide-in-from-top-2">
                                <label className="text-sm font-bold text-slate-800 block mb-1">Adresse de livraison</label>
                                <p className="text-[10px] text-slate-500 mb-3">Laissez vide pour utiliser l'adresse de votre société.</p>
                                <textarea 
                                    value={managingPanneau.shippingAddress || ''} 
                                    onChange={e => setManagingPanneau({...managingPanneau, shippingAddress: e.target.value})} 
                                    className="w-full border border-slate-200 rounded-lg p-3 text-sm focus:border-blue-500 outline-none transition resize-none bg-slate-50 focus:bg-white" 
                                    rows="2" 
                                    placeholder={profileData.address || "Bâtiment, rue, code postal, ville..."}
                                ></textarea>
                            </div>
                        )}
                    </div>

                    <div className="bg-slate-900 rounded-2xl p-5 text-white shadow-xl">
                        <h4 className="text-sm font-bold text-slate-300 uppercase tracking-widest mb-3 border-b border-slate-700 pb-2">Résumé de votre commande</h4>
                        <div className="space-y-2 text-sm font-medium">
                            {!isActif && (
                                <>
                                    <div className="flex justify-between"><span className="text-slate-300">{currentOfferType === 'rental' ? 'Abonnement mensuel (1er mois inclus)' : 'Achat définitif'}</span><span>{(currentOfferType === 'rental' ? pRental : pPurchase).toFixed(2)} € HT</span></div>
                                    {currentOfferType === 'purchase' && <div className="flex justify-between items-center"><span className="text-slate-300">Hébergement annuel (1ère année offerte)</span><span>0.00 € HT <span className="line-through text-slate-500 text-xs ml-1">{pHosting.toFixed(2)} €</span></span></div>}
                                    {currentPanels > 0 && <div className="flex justify-between"><span className="text-slate-300">Panneaux physiques ({currentPanels}x)</span><span>{(currentPanels > 0 ? pBoardFirst + (currentPanels - 1) * pBoardAdd : 0).toFixed(2)} € HT</span></div>}
                                    {currentHasNoAds && <div className="flex justify-between"><span className="text-slate-300">Option marque blanche (Sans mentions de eco-panneau.fr)</span><span>{pNoAds.toFixed(2)} € HT</span></div>}
                                </>
                            )}
                            {isActif && (
                                <>
                                    {originalOfferType === 'rental' && currentOfferType === 'purchase' && <div className="flex justify-between"><span className="text-slate-300">Passage à l'achat définitif</span><span>{pPurchase.toFixed(2)} € HT</span></div>}
                                    {currentPanels > originalPanels && <div className="flex justify-between"><span className="text-slate-300">Panneaux physiques supp. ({currentPanels - originalPanels}x)</span><span>{addedPanelsCost.toFixed(2)} € HT</span></div>}
                                    {currentHasNoAds && !originalHasNoAds && <div className="flex justify-between"><span className="text-slate-300">Option marque blanche (Sans mentions de eco-panneau.fr)</span><span>{pNoAds.toFixed(2)} € HT</span></div>}
                                </>
                            )}
                            
                            {discountPct > 0 && upfrontHT > 0 && (
                                <div className="flex justify-between text-emerald-400">
                                    <span>Remise client ({discountPct}%)</span>
                                    <span>-{(upfrontHT * (discountPct / 100)).toFixed(2)} € HT</span>
                                </div>
                            )}

                            {myClientData.wallet_balance > 0 && upfrontHT > 0 && (
                                <div className="flex justify-between text-emerald-400 border-t border-slate-700/50 mt-2 pt-2">
                                    <span>Payé avec votre solde (Avoir)</span>
                                    <span>-{Math.min(finalUpfrontTTC, myClientData.wallet_balance).toFixed(2)} € TTC</span>
                                </div>
                            )}

                            <div className="border-t border-slate-700 mt-3 pt-3 flex justify-between items-end">
                                <div>
                                    <p className="text-lg font-black">Reste à payer aujourd'hui</p>
                                    <p className="text-[10px] text-slate-400 uppercase tracking-wider mt-1">{platformHasTva ? 'TVA 20% incluse' : 'TVA non applicable'}</p>
                                </div>
                                <div className="text-right">
                                    <p className="text-2xl font-black text-emerald-400">{Math.max(0, finalUpfrontTTC - (myClientData.wallet_balance || 0)).toFixed(2)} €</p>
                                    {currentOfferType === 'rental' && <p className="text-xs text-slate-400 mt-1">Puis {finalMonthlyTTC.toFixed(2)} € TTC / mois</p>}
                                    {currentOfferType === 'purchase' && <p className="text-xs text-slate-400 mt-1">Puis { (pHosting * priceMultiplier * tvaMult).toFixed(2) } € TTC / an</p>}
                                </div>
                            </div>
                        </div>
                    </div>
                    
                    {(!purchasesAllowed && remainingToPay > 0) && (
                        <div className="bg-orange-50 text-orange-800 p-4 rounded-xl text-sm font-bold border border-orange-200 mt-4 flex items-start gap-3">
                            <AlertTriangle size={24} className="shrink-0" />
                            <p>L'administration a temporairement suspendu la validation de nouvelles commandes payantes sur la plateforme. Veuillez réessayer ultérieurement.</p>
                        </div>
                    )}

                    {remainingToPay > 0 && purchasesAllowed && (
                        <label className="flex items-start gap-3 p-4 bg-slate-50 border border-slate-200 rounded-xl cursor-pointer hover:bg-slate-100 transition mt-4">
                            <input type="checkbox" checked={waiverAccepted} onChange={(e) => setWaiverAccepted(e.target.checked)} className="mt-0.5 w-5 h-5 accent-emerald-600 shrink-0 cursor-pointer" />
                            <span className="text-xs font-bold text-slate-700 leading-relaxed cursor-pointer select-none">
                                J'accepte que l'exécution du service et la fourniture du contenu numérique commencent immédiatement, et je renonce expressément à mon droit de rétractation de 14 jours. <span className="text-red-500 font-bold">(obligatoire)</span>
                            </span>
                        </label>
                    )}

                    <div className="flex gap-3 pt-2 mt-4">
                        <button type="button" onClick={onBackToEditor} disabled={isSaving} className="px-6 py-3 rounded-xl font-bold text-slate-500 hover:bg-slate-100 transition disabled:opacity-50">Retour</button>
                        <button onClick={handleActivationRequest} disabled={isSaving || (remainingToPay > 0 && (!waiverAccepted || !purchasesAllowed))} className="flex-1 bg-emerald-600 text-white py-3 rounded-xl font-black uppercase tracking-widest hover:bg-emerald-700 transition shadow-lg flex items-center justify-center gap-2 disabled:opacity-50">
                            {isSaving ? <Loader className="animate-spin w-5 h-5"/> : <CreditCard size={18}/>} Confirmer et payer
                        </button>
                    </div>
                </div>
            </div>
        </div>
    );
};

// =========================================================================
// 3. MODALE DU COFFRE-FORT LÉGAL
// =========================================================================

window.ClientLegalVaultModal = ({ managingPanneau, setManagingPanneau, onClose, refreshData, showToast }) => {
    const { Lock, ArrowUp, Trash2, Loader, ArrowLeft, Download } = window;
    
    const [isSaving, setIsSaving] = useState(false);
    const [vaultDragging, setVaultDragging] = useState(false);
    const [viewingDoc, setViewingDoc] = useState(null);

    const handleVaultUpload = async (files) => {
        if (!files || files.length === 0) return;
        let currentTotalSize = managingPanneau.privateDocs?.reduce((acc, doc) => acc + (doc.size || 0), 0) || 0;
        
        setIsSaving(true);
        let newDocs = [...(managingPanneau.privateDocs || [])];
        
        for (let i = 0; i < files.length; i++) {
            const file = files[i];
            if (file.size > 100 * 1024 * 1024) { showToast(`Le fichier ${file.name} dépasse 100 Mo.`, "error"); continue; }
            if (currentTotalSize + file.size > 500 * 1024 * 1024) { showToast("La limite totale de 500 Mo du coffre-fort serait dépassée.", "error"); break; }
            try {
                const type = file.type.includes('pdf') ? 'pdf' : 'image';
                const fd = new FormData(); fd.append('file', file); fd.append('type', type); fd.append('is_private', 'true');
                const res = await fetch(window.ECO_CONFIG.apiBaseUrl + 'upload/file', { method: 'POST', body: fd });
                const d = await res.json();
                if (d.status === 'success') {
                    newDocs.push({ id: d.data.fileId, type, name: file.name, date: new Date().toLocaleDateString('fr-FR'), size: d.data.size || file.size });
                    currentTotalSize += (d.data.size || file.size);
                } else showToast(d.message, "error");
            } catch(err) { showToast("Erreur upload", "error"); }
        }
        
        const updatedPanneau = {...managingPanneau, privateDocs: newDocs};
        setManagingPanneau(updatedPanneau);
        await fetch(window.ECO_CONFIG.apiBaseUrl + 'panneaux', { method: 'POST', body: JSON.stringify({ id: updatedPanneau.id, status: updatedPanneau.status, offerType: updatedPanneau.offerType, physicalPanels: updatedPanneau.physicalPanels, details: updatedPanneau }) });
        refreshData(); setIsSaving(false);
    };

    return (
        <>
            <window.Modal title="Coffre-fort légal privé" onClose={onClose} preventClose={isSaving} zIndex="z-[200]">
                <div className="space-y-6">
                    <div className="bg-slate-50 p-4 rounded-xl border border-slate-200 flex gap-4 items-start">
                        <Lock size={24} className="text-slate-400 shrink-0"/>
                        <div>
                            <p className="text-sm font-bold text-slate-800">Preuves et constats d'huissier</p>
                            <p className="text-xs text-slate-500 mt-1">Ces documents sont chiffrés et inaccessibles au public. Ils seront inclus dans l'archive D.O.E lors de la clôture du panneau.</p>
                        </div>
                    </div>

                    <div 
                        onDragEnter={(e) => { e.preventDefault(); setVaultDragging(true); }}
                        onDragLeave={(e) => { e.preventDefault(); setVaultDragging(false); }}
                        onDragOver={(e) => e.preventDefault()}
                        onDrop={(e) => { e.preventDefault(); setVaultDragging(false); handleVaultUpload(e.dataTransfer.files); }}
                        className={`w-full min-h-[150px] border-2 border-dashed rounded-xl flex flex-col items-center justify-center p-6 transition relative ${vaultDragging ? 'border-emerald-500 bg-emerald-50/50' : 'border-slate-300 bg-slate-50 hover:bg-slate-100'}`}
                        title="Vous pouvez également coller vos fichiers (Ctrl+V) directement sur cette fenêtre."
                    >
                        {isSaving ? (
                            <div className="flex flex-col items-center text-slate-500"><Loader size={32} className="animate-spin mb-2"/> <span className="text-sm font-bold">Chiffrement en cours...</span></div>
                        ) : (
                            <>
                                <div className="w-12 h-12 bg-white rounded-full flex items-center justify-center shadow-sm mb-3 text-slate-400"><ArrowUp size={24}/></div>
                                <span className="text-sm font-bold text-slate-700">Glissez-déposez vos preuves ici (ou Ctrl+V)</span>
                                <span className="text-xs text-slate-500 mt-1 text-center">Images ou PDF (Max 100 Mo/fichier, 500 Mo au total)</span>
                                <label className="mt-4 px-4 py-2 bg-white border border-slate-200 text-slate-700 rounded-lg text-xs font-bold shadow-sm hover:bg-slate-50 cursor-pointer transition">
                                    Parcourir les fichiers
                                    <input type="file" multiple accept="application/pdf,image/*" className="hidden" onChange={(e) => { if(e.target.files) handleVaultUpload(e.target.files); e.target.value = null; }} />
                                </label>
                            </>
                        )}
                    </div>

                    {managingPanneau.privateDocs && managingPanneau.privateDocs.length > 0 ? (
                        <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4 mt-6">
                            {managingPanneau.privateDocs.map((doc, idx) => (
                                <div key={idx} className="relative group rounded-xl border border-slate-200 overflow-hidden bg-slate-50 shadow-sm flex flex-col cursor-pointer transition hover:border-emerald-300 hover:shadow-md" onClick={() => setViewingDoc(doc)}>
                                    <div className="h-24 w-full bg-white flex items-center justify-center p-2 shrink-0">
                                        {doc.type === 'image' ? (
                                            <img src={`?api=file/download_private&type=image&id=${doc.id}`} className="max-h-full max-w-full object-contain" alt="aperçu" />
                                        ) : (
                                            <img src={`?api=file/preview&type=pdf&id=${doc.id}&private=1`} className="max-h-full max-w-full object-contain" alt="aperçu pdf" onError={(e) => { e.target.style.display = 'none'; e.target.parentElement.innerHTML = '<div class="flex flex-col items-center text-slate-300"><svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"></path><polyline points="14 2 14 8 20 8"></polyline></svg><span class="text-[9px] font-bold mt-1 text-slate-400 uppercase tracking-widest">PDF</span></div>'; }} />
                                        )}
                                    </div>
                                    <div className="p-2 border-t border-slate-100 flex-1 flex flex-col justify-between">
                                        <p className="text-[10px] font-bold text-slate-700 truncate" title={doc.name}>{doc.name}</p>
                                        <div className="flex justify-between items-center mt-2">
                                            <span className="text-[9px] font-bold text-slate-400">{doc.date}</span>
                                            <button onClick={async (e) => { 
                                                e.stopPropagation();
                                                if(!confirm("Voulez-vous vraiment supprimer ce document privé ?")) return;
                                                const newDocs = [...managingPanneau.privateDocs]; newDocs.splice(idx, 1);
                                                const updatedPanneau = {...managingPanneau, privateDocs: newDocs};
                                                setManagingPanneau(updatedPanneau); setIsSaving(true);
                                                await fetch(window.ECO_CONFIG.apiBaseUrl + 'panneaux', { method: 'POST', body: JSON.stringify({ id: updatedPanneau.id, status: updatedPanneau.status, offerType: updatedPanneau.offerType, physicalPanels: updatedPanneau.physicalPanels, details: updatedPanneau }) });
                                                refreshData(); setIsSaving(false);
                                            }} className="text-red-400 hover:text-red-600 bg-red-50 hover:bg-red-100 p-1 rounded transition" title="Supprimer">
                                                <Trash2 size={12}/>
                                            </button>
                                        </div>
                                    </div>
                                </div>
                            ))}
                        </div>
                    ) : (
                        <p className="text-center text-sm text-slate-400 py-4 italic">Aucun document privé stocké.</p>
                    )}
                    
                    <div className="text-right">
                        <span className="text-xs font-bold text-slate-400">Total utilisé : {((managingPanneau.privateDocs?.reduce((acc, doc) => acc + (doc.size || 0), 0) || 0) / (1024*1024)).toFixed(2)} Mo / 500 Mo</span>
                    </div>
                </div>
            </window.Modal>

            {/* Visualiseur Plein Écran Coffre-Fort */}
            {viewingDoc && (
                <div className="fixed inset-0 z-[999999] bg-slate-900/95 backdrop-blur-sm flex flex-col animate-in fade-in duration-200" onClick={() => setViewingDoc(null)}>
                    <div className="flex justify-between items-center p-4 bg-slate-900/50 text-white shrink-0 border-b border-white/10" onClick={e => e.stopPropagation()}>
                        <button onClick={() => setViewingDoc(null)} className="flex items-center gap-2 px-4 py-2 hover:bg-white/10 rounded-xl transition text-sm font-bold">
                            <ArrowLeft size={18}/> Retour
                        </button>
                        <div className="flex items-center gap-3">
                            <span className="text-xs font-mono text-slate-400 hidden sm:inline">{viewingDoc.name}</span>
                            <a href={`?api=file/download_private&type=${viewingDoc.type}&id=${viewingDoc.id}`} download className="flex items-center gap-2 px-4 py-2 bg-emerald-600 hover:bg-emerald-700 rounded-xl transition text-sm font-bold shadow-lg">
                                <Download size={18}/> <span className="hidden sm:inline">Télécharger</span>
                            </a>
                        </div>
                    </div>
                    <div className="flex-1 flex flex-col items-center justify-start p-2 sm:p-4 min-h-0 relative w-full overflow-y-auto custom-scrollbar">
                        {viewingDoc.type === 'image' ? (
                            <img src={`?api=file/download_private&type=image&id=${viewingDoc.id}`} className="max-w-full max-h-full object-contain rounded-xl shadow-2xl shrink-0" alt="Aperçu" onClick={e => e.stopPropagation()} />
                        ) : (
                            <img src={`?api=file/preview&type=pdf&id=${viewingDoc.id}&private=1`} className="w-full max-w-3xl rounded-xl shadow-2xl" alt="Aperçu PDF" onClick={e => e.stopPropagation()} />
                        )}
                    </div>
                </div>
            )}
        </>
    );
};

// =========================================================================
// 4. MODALE DE GESTION DES LIENS DÉLÉGUÉS
// =========================================================================

window.ClientDelegateShareModal = ({ managingPanneau, setManagingPanneau, onClose, refreshData, showToast }) => {
    const { Plus, Lock, Copy, Trash2 } = window;
    const [newLink, setNewLink] = useState({ name: '', expDays: 7, lockedFields: [] });
    const [isSaving, setIsSaving] = useState(false);

    return (
        <window.Modal title="Saisie déléguée multicomptes" onClose={onClose} zIndex="z-[200]">
            <div className="space-y-6">
                <div className="bg-blue-50 p-4 rounded-xl border border-blue-100 text-blue-800 text-sm leading-relaxed">
                    Créez des liens sécurisés pour confier la saisie d'informations ou le dépôt de documents (PDF) à d'autres membres de l'équipe du chantier sans leur donner accès à votre compte ou à votre facturation.
                </div>

                <div className="bg-white p-4 rounded-xl border border-slate-200 shadow-sm space-y-4">
                    <h4 className="font-bold text-slate-800 text-sm flex items-center gap-2"><Plus size={16}/> Créer un nouveau lien</h4>
                    <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
                        <div className="space-y-1">
                            <label className="text-xs font-bold text-slate-500 uppercase block">Nom du destinataire *</label>
                            <input value={newLink.name} onChange={e=>setNewLink({...newLink, name: e.target.value})} placeholder="Ex: Architecte Dupont" className="w-full border border-slate-200 rounded-lg p-2 text-sm outline-none focus:border-blue-500" />
                        </div>
                        <div className="space-y-1">
                            <label className="text-xs font-bold text-slate-500 uppercase block">Validité (jours)</label>
                            <input type="number" min="1" max="90" value={newLink.expDays} onChange={e=>setNewLink({...newLink, expDays: parseInt(e.target.value)||7})} className="w-full border border-slate-200 rounded-lg p-2 text-sm outline-none focus:border-blue-500" />
                        </div>
                    </div>
                    <div className="space-y-2 pt-2">
                        <label className="text-xs font-bold text-slate-500 uppercase block">Verrouiller la saisie de ces champs (lecture seule) :</label>
                        <div className="flex flex-wrap gap-2">
                            {[
                                { id: 'name', label: 'Nom du chantier' }, { id: 'location', label: 'Lieu' },
                                { id: 'maitreOuvrage', label: "Maître d'ouvrage" }, { id: 'permitNumber', label: 'N° de permis' },
                                { id: 'description', label: 'Description' }, { id: 'promoterLink', label: 'Lien promoteur' },
                                { id: 'emergencyPhone', label: 'N° d\'urgence' }, { id: 'noiseSchedule', label: 'Horaires' },
                                { id: 'intervenants', label: 'Intervenants' }, { id: 'lots', label: 'Lots' }, { id: 'pdfId', label: 'Arrêté (PDF)' }
                            ].map(f => (
                                <button key={f.id} onClick={() => setNewLink(p => ({...p, lockedFields: p.lockedFields.includes(f.id) ? p.lockedFields.filter(x=>x!==f.id) : [...p.lockedFields, f.id]}))} className={`px-2 py-1 rounded-lg text-xs font-bold transition border ${newLink.lockedFields.includes(f.id) ? 'bg-red-50 text-red-600 border-red-200' : 'bg-slate-50 text-slate-500 border-slate-200 hover:bg-slate-100'}`}>
                                    {newLink.lockedFields.includes(f.id) && <Lock size={10} className="inline mr-1"/>}{f.label}
                                </button>
                            ))}
                        </div>
                    </div>
                    <button onClick={async () => {
                        if (!newLink.name.trim()) return showToast("Le nom du lien est obligatoire.", "error");
                        setIsSaving(true);
                        try {
                            const linkId = crypto.randomUUID();
                            const expTime = Math.floor(Date.now() / 1000) + (newLink.expDays * 86400);
                            const linkObj = { id: linkId, name: newLink.name.trim(), exp: expTime, active: true, lockedFields: newLink.lockedFields };
                            const updatedPanneau = { ...managingPanneau, delegate_links: [...(managingPanneau.delegate_links || []), linkObj] };
                            await fetch(window.ECO_CONFIG.apiBaseUrl + 'panneaux', { method: 'POST', body: JSON.stringify({ id: updatedPanneau.id, status: updatedPanneau.status, offerType: updatedPanneau.offerType, physicalPanels: updatedPanneau.physicalPanels, details: updatedPanneau }) });
                            setManagingPanneau(updatedPanneau);
                            setNewLink({ name: '', expDays: 7, lockedFields: [] });
                            refreshData();
                            showToast("Nouveau lien de saisie créé.", "success");
                        } catch(e) { showToast("Erreur", "error"); }
                        setIsSaving(false);
                    }} disabled={isSaving || !newLink.name.trim()} className="w-full bg-blue-600 text-white py-2 rounded-lg font-bold text-sm hover:bg-blue-700 transition flex items-center justify-center gap-2">
                        <Plus size={16}/> Créer le lien
                    </button>
                </div>

                <div className="space-y-3">
                    <h4 className="font-bold text-slate-800 text-sm">Liens générés pour ce panneau</h4>
                    {(!managingPanneau.delegate_links || managingPanneau.delegate_links.length === 0) && (
                        <p className="text-slate-500 text-xs italic text-center py-4">Aucun lien n'a encore été créé pour ce panneau.</p>
                    )}
                    {managingPanneau.delegate_links?.map((link, idx) => {
                        const isExpired = link.exp < Date.now() / 1000;
                        return (
                            <div key={idx} className={`p-4 rounded-xl border ${link.active && !isExpired ? 'bg-white border-slate-200 shadow-sm' : 'bg-slate-50 border-slate-200 opacity-75'}`}>
                                <div className="flex justify-between items-start mb-2">
                                    <div>
                                        <p className="font-bold text-slate-800 text-sm">{link.name}</p>
                                        <p className="text-xs text-slate-500">Exp. : {new Date(link.exp * 1000).toLocaleDateString('fr-FR')} {isExpired && <span className="text-red-500 font-bold ml-1">(Expiré)</span>}</p>
                                    </div>
                                    <div className="flex items-center gap-2">
                                        <label className="flex items-center cursor-pointer mr-2" title="Activer / Désactiver ce lien">
                                            <div className={`w-8 h-4 rounded-full transition-colors relative shrink-0 ${link.active ? 'bg-emerald-500' : 'bg-slate-300'}`}>
                                                <div className={`absolute top-[2px] bg-white w-3 h-3 rounded-full transition-transform ${link.active ? 'translate-x-4' : 'translate-x-1'}`}></div>
                                            </div>
                                            <input type="checkbox" className="hidden" checked={link.active} onChange={async (e) => {
                                                const newVal = e.target.checked;
                                                setIsSaving(true);
                                                try {
                                                    const links = [...managingPanneau.delegate_links];
                                                    links[idx] = { ...links[idx], active: newVal };
                                                    const updatedPanneau = { ...managingPanneau, delegate_links: links };
                                                    await fetch(window.ECO_CONFIG.apiBaseUrl + 'panneaux', { method: 'POST', body: JSON.stringify({ id: updatedPanneau.id, status: updatedPanneau.status, offerType: updatedPanneau.offerType, physicalPanels: updatedPanneau.physicalPanels, details: updatedPanneau }) });
                                                    setManagingPanneau(updatedPanneau); refreshData();
                                                } catch(e) {}
                                                setIsSaving(false);
                                            }} />
                                        </label>
                                        <button onClick={async () => {
                                            setIsSaving(true);
                                            try {
                                                const res = await fetch(window.ECO_CONFIG.apiBaseUrl + 'panneaux/delegate_link', { method: 'POST', body: JSON.stringify({ id: managingPanneau.id, link_id: link.id }) });
                                                const d = await res.json();
                                                if (d.status === 'success') { navigator.clipboard.writeText(d.data.link); showToast("Lien copié !"); }
                                            } catch(e) { showToast("Erreur", "error"); }
                                            setIsSaving(false);
                                        }} disabled={!link.active || isExpired || isSaving} className="bg-slate-100 text-slate-700 px-3 py-1.5 rounded-lg text-xs font-bold hover:bg-slate-200 transition shadow-sm disabled:opacity-50 flex items-center gap-1">
                                            <Copy size={12}/> Copier URL
                                        </button>
                                        <button onClick={async () => {
                                            if(!confirm("Supprimer ce lien ?")) return;
                                            setIsSaving(true);
                                            try {
                                                const links = [...managingPanneau.delegate_links];
                                                links.splice(idx, 1);
                                                const updatedPanneau = { ...managingPanneau, delegate_links: links };
                                                await fetch(window.ECO_CONFIG.apiBaseUrl + 'panneaux', { method: 'POST', body: JSON.stringify({ id: updatedPanneau.id, status: updatedPanneau.status, offerType: updatedPanneau.offerType, physicalPanels: updatedPanneau.physicalPanels, details: updatedPanneau }) });
                                                setManagingPanneau(updatedPanneau); refreshData();
                                            } catch(e) {}
                                            setIsSaving(false);
                                        }} className="text-red-500 hover:bg-red-50 p-1.5 rounded-lg transition" title="Supprimer">
                                            <Trash2 size={16}/>
                                        </button>
                                    </div>
                                </div>
                                {link.lockedFields && link.lockedFields.length > 0 && (
                                    <p className="text-[10px] text-slate-500 mt-2 border-t border-slate-100 pt-2 flex items-center gap-1">
                                        <Lock size={10} className="text-red-400"/> Bloqué : {link.lockedFields.join(', ')}
                                    </p>
                                )}
                            </div>
                        );
                    })}
                </div>
            </div>
        </window.Modal>
    );
};

/* EOF ===== [_clients_modals.jsx] =============== */