// ECO-PANNEAU.FR - _react/clients/_clients_modals_vault.jsx

const { useState, useEffect } = React;

window.pano_ClientLegalVaultModal = ({ panneau, setPanneau, myClientData = {}, onClose, refreshData }) => {
    
    // ZÉRO-DETTE : Utilisation de notre Hook abstrait !
    const { isMounted, safeFetch } = window.pano_useSafeFetch();

    // 1. - Composants et Icônes
    const { LockIcon, ArrowUpIcon, Trash2Icon, LoaderIcon, EyeIcon, AlertTriangleIcon, PlusIcon, CheckCircleIcon, XIcon } = window.pano_getIcons();
    const { 
        Modal, AlertBox, ConfirmModal, Button, 
        VaultDocumentThumbnail, UniversalViewer, CardGrid 
    } = window.pano_getComponents();

    // 2. - États locaux
    const [isSaving, setIsSaving] = useState(false);
    const [uploadStats, setUploadStats] = useState({ current: 0, total: 0 });
    const [uploadDetail, setUploadDetail] = useState('');
    const [deleteStats, setDeleteStats] = useState({ current: 0, total: 0 });
    const [vaultDragging, setVaultDragging] = useState(false);
    
    const [viewingDoc, setViewingDoc] = useState(null);
    const [confirmDialog, setConfirmDialog] = useState(null);
    const [uploadErrors, setUploadErrors] = useState([]);
    
    const [selectedDocs, setSelectedDocs] = useState([]);

    // CHARGEMENT DYNAMIQUE DES QUOTAS DEPUIS LE SERVEUR
    const [quotas, setQuotas] = useState({ privateFile: 10 });
    
    useEffect(() => {
        safeFetch('sync', { silent: true }).then(d => {
            if (!isMounted.current) return; // Sécurité
            if (d?.data?.settings) {
                setQuotas({
                    privateFile: parseInt(d.data.settings.quota_upload_private_mb || 10, 10)
                });
            }
        });
    }, [safeFetch, isMounted]);

    // 3. - Droits d'accès et Sécurité Zéro-Trust Stricte
    const isOwner = String(panneau.client_uid) === String(myClientData?.id);
    const isMe = (uid) => String(uid) === String(myClientData?.id) || String(uid) === String(myClientData?.email_hash);
    
    const myCollab = !isOwner ? panneau.collaborators?.find(c => isMe(c.uid)) : null;
    const canEdit = isOwner || myCollab?.rights?.can_edit;

    if (!canEdit) {
        return (
            <Modal title="Coffre-fort légal" type="error" onClose={onClose}>
                <p className="text-center text-slate-500 py-8 break-words">Vous n'avez pas l'autorisation d'accéder au coffre-fort de ce panneau.</p>
            </Modal>
        );
    }

    const docs = panneau.privateDocs || [];

    // ACCÉLÉRATEUR : Sélection de masse via Ctrl+A (ou Cmd+A)
    useEffect(() => {
        const handleKeyDown = (e) => {
            if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'a') {
                if (e.target.tagName.toLowerCase() === 'input' || e.target.tagName.toLowerCase() === 'textarea') {
                    return;
                }
                
                e.preventDefault();
                
                const selectableIds = docs.filter(doc => {
                    const normalizedName = window.pano_normalizeString ? window.pano_normalizeString(doc.name) : (doc.name || '').toLowerCase();
                    const isProtected = normalizedName.includes('attestation') && normalizedName.includes('activation');
                    return !isProtected;
                }).map(d => d.id);

                if (selectableIds.length > 0 && !isSaving) {
                    setSelectedDocs(selectableIds);
                }
            }
        };

        window.addEventListener('keydown', handleKeyDown);
        return () => window.removeEventListener('keydown', handleKeyDown);
    }, [docs, isSaving]);

    // 4. - Actions métier
    const handleDelete = (docId) => {
        setConfirmDialog({
            title: "Supprimer le document",
            message: "Ce document sera définitivement effacé du coffre-fort et du serveur. Continuer ?",
            confirmText: "Supprimer",
            isDestructive: true,
            onConfirm: async () => {
                setConfirmDialog(null);
                setIsSaving(true);
                
                const newDocs = docs.filter(d => d.id !== docId);
                const updatedPanneau = { ...panneau, privateDocs: newDocs };
                
                try { await safeFetch('file/delete', { body: { id: docId }, silent: true }); } catch(e) {}

                if (!isMounted.current) return; // Sécurité anti-corruption

                if (setPanneau) setPanneau(updatedPanneau);
                setSelectedDocs(prev => prev.filter(id => id !== docId));

                const d = await safeFetch('panneaux', {
                    body: { id: panneau.id, status: panneau.status, offerType: panneau.offerType, currentRate: panneau.currentRate, physicalPanels: panneau.physicalPanels, details: updatedPanneau },
                    silent: true
                });
                
                if (!isMounted.current) return; // Sécurité

                if (d) {
                    if (window.pano_showToast) window.pano_showToast("Document supprimé.", "success");
                    if (refreshData) refreshData();
                }
                setIsSaving(false);
            },
            onCancel: () => setConfirmDialog(null)
        });
    };

    const handleBatchDelete = () => {
        if (selectedDocs.length === 0) return;
        
        setConfirmDialog({
            title: "Supprimer la sélection",
            message: `Vous êtes sur le point de supprimer définitivement ${selectedDocs.length} document(s) du coffre-fort et du serveur. Continuer ?`,
            confirmText: "Supprimer",
            isDestructive: true,
            onConfirm: async () => {
                setConfirmDialog(null);
                setIsSaving(true);
                
                // Copie figée pour le parcours
                const docsToDelete = [...selectedDocs];
                let currentDocs = [...docs];
                
                setDeleteStats({ current: 1, total: docsToDelete.length });

                let currentCount = 1;
                for (const docId of docsToDelete) {
                    if (!isMounted.current) return; // SÉCURITÉ : Coupe la boucle si on quitte
                    
                    setDeleteStats({ current: currentCount, total: docsToDelete.length });
                    
                    try { 
                        await safeFetch('file/delete', { body: { id: docId }, silent: true }); 
                        
                        if (!isMounted.current) return; // Sécurité post-requête

                        // Retrait visuel immédiat du fichier
                        currentDocs = currentDocs.filter(d => d.id !== docId);
                        if (setPanneau) setPanneau({ ...panneau, privateDocs: currentDocs });
                        setSelectedDocs(prev => prev.filter(id => id !== docId));

                    } catch(e) {}
                    
                    currentCount++;
                }

                if (!isMounted.current) return; // Sécurité avant sauvegarde finale

                // Synchronisation finale en base de données avec le tableau nettoyé
                const finalPanneau = { ...panneau, privateDocs: currentDocs };
                const d = await safeFetch('panneaux', {
                    body: { id: panneau.id, status: panneau.status, offerType: panneau.offerType, currentRate: panneau.currentRate, physicalPanels: panneau.physicalPanels, details: finalPanneau },
                    silent: true
                });

                if (!isMounted.current) return; // Sécurité finale

                if (d) {
                    if (window.pano_showToast) window.pano_showToast(`${docsToDelete.length} document(s) supprimé(s).`, "success");
                    if (refreshData) refreshData();
                }
                
                setSelectedDocs([]);
                setDeleteStats({ current: 0, total: 0 });
                setIsSaving(false);
            },
            onCancel: () => setConfirmDialog(null)
        });
    };

    const handleVaultUpload = async (fileList) => {
        if (!fileList || fileList.length === 0) return;
        const files = Array.from(fileList);
        let currentTotalSize = docs.reduce((acc, doc) => acc + (doc.size || 0), 0);
        
        setIsSaving(true);
        setUploadStats({ current: 1, total: files.length });
        setUploadDetail('Préparation...');
        
        let uploadedDocs = [];
        let currentErrors = [];

        for (let i = 0; i < files.length; i++) {
            if (!isMounted.current) return; // SÉCURITÉ : Coupe la boucle si on quitte

            const file = files[i];
            setUploadStats({ current: i + 1, total: files.length });
            
            // VERIFICATION DYNAMIQUE DES QUOTAS ADMIN (Taille de fichier unique)
            if (file.size > quotas.privateFile * 1024 * 1024) { 
                currentErrors.push({ file: file.name, reason: `Taille > ${quotas.privateFile} Mo` }); 
                continue; 
            }

            let strictType = '';
            if (file.type === 'application/pdf') {
                strictType = 'pdf';
            } else if (file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/webp') {
                strictType = 'image';
            } else {
                currentErrors.push({ file: file.name, reason: "Format non supporté (PDF, JPG, PNG, WEBP)" });
                continue;
            }

            try {
                // Utilitaire externe : On garde le coupe-circuit manuel pour lui
                const idObj = await window.pano_uploadFile(
                    file, 
                    strictType, 
                    (msg, pct) => { if (isMounted.current) setUploadDetail(`${msg} (${pct}%)`); }, // Sécurité UI
                    false, 
                    true, 
                    panneau.client_uid, 
                    panneau.id
                );
                
                if (!isMounted.current) return; // Sécurité post-requête

                const actualId = idObj.id || idObj;

                if (actualId) {
                    uploadedDocs.push({
                        id: actualId,
                        type: strictType,
                        name: file.name,
                        date: window.pano_formatDate(new Date().toISOString()),
                        size: file.size,
                        numPages: idObj.numPages || 1
                    });
                    currentTotalSize += file.size;
                }
            } catch (err) {
                currentErrors.push({ file: file.name, reason: err.message || "Erreur de transfert" });
            }
        }

        if (!isMounted.current) return; // Sécurité avant sauvegarde finale

        if (uploadedDocs.length > 0) {
            const newDocs = [...docs, ...uploadedDocs];
            const updatedPanneau = { ...panneau, privateDocs: newDocs };
            
            if (setPanneau) setPanneau(updatedPanneau);

            const d = await safeFetch('panneaux', {
                body: { id: panneau.id, status: panneau.status, offerType: panneau.offerType, currentRate: panneau.currentRate, physicalPanels: panneau.physicalPanels, details: updatedPanneau },
                successMessage: `${uploadedDocs.length} document(s) importé(s).`
            });
            
            if (!isMounted.current) return; // Sécurité finale
            
            if (d && refreshData) refreshData();
        }

        setIsSaving(false);
        setUploadStats({ current: 0, total: 0 });
        setUploadDetail('');
        
        if (currentErrors.length > 0) {
            setUploadErrors(currentErrors);
        }
    };

    // 5. - Rendu UI
    return (
        <>
            <Modal 
                title={`Coffre-fort : ${panneau.name}`} 
                type="purple" 
                onClose={onClose} 
                preventClose={isSaving} 
                actions={(close) => (
                    <div className="flex items-center w-full gap-3 justify-between">
                        <Button variant="secondary" onClick={close} disabled={isSaving} className="flex-1 py-3 justify-center text-xs shadow-sm">
                            Fermer
                        </Button>
                        
                        {selectedDocs.length > 0 && (
                            <div className="flex items-center justify-between gap-2 bg-red-50 text-red-700 px-3 py-1.5 rounded-xl border border-red-200 animate-in fade-in slide-in-from-right-2 shrink-0">
                                <span className="text-xs font-bold hidden sm:inline">{selectedDocs.length} sélectionné(s)</span>
                                <span className="text-xs font-bold sm:hidden">{selectedDocs.length}</span>
                                <Button variant="dangerSolid" onClick={handleBatchDelete} icon={Trash2Icon} disabled={isSaving} className="px-3 py-1.5 text-[10px] shadow-sm ml-1 h-auto">
                                    <span className="hidden sm:inline">Supprimer</span>
                                </Button>
                                <button type="button" onClick={() => setSelectedDocs([])} disabled={isSaving} className="ml-1 text-red-400 hover:text-red-700 p-1 disabled:opacity-50 transition-colors" title="Annuler la sélection">
                                    <XIcon size={14}/>
                                </button>
                            </div>
                        )}
                    </div>
                )}
            >
                <div className="space-y-6 min-w-0">
                    
                    <AlertBox type="purple" icon={LockIcon}>
                        Espace personnel destiné à conserver vos preuves de dépôt, constats d'huissier ou arrêtés. Ces documents ne sont pas accessibles au public.
                    </AlertBox>

                    <div 
                        onDragEnter={(e) => { e.preventDefault(); if(!isSaving) setVaultDragging(true); }}
                        onDragLeave={(e) => { e.preventDefault(); setVaultDragging(false); }}
                        onDragOver={(e) => e.preventDefault()}
                        onDrop={(e) => { e.preventDefault(); setVaultDragging(false); if(!isSaving) handleVaultUpload(e.dataTransfer.files); }}
                        className={`w-full min-h-[160px] border-2 border-dashed rounded-xl flex flex-col items-center justify-center p-6 transition relative ${vaultDragging ? 'border-purple-500 bg-purple-50' : 'border-slate-300 bg-slate-50 hover:bg-slate-100'}`}
                    >
                        {isSaving && uploadStats.total > 0 ? (
                            <div className="flex flex-col items-center text-slate-500 text-center">
                                <LoaderIcon size={32} className="animate-spin mb-2 mx-auto text-purple-600"/> 
                                <span className="text-sm font-bold text-purple-800">Importation en cours...</span>
                                <span className="text-[10px] mt-1 font-bold">Fichier {uploadStats.current}/{uploadStats.total}</span>
                                <span className="text-[9px] text-slate-400 mt-1 max-w-[200px] truncate">{uploadDetail}</span>
                            </div>
                        ) : isSaving && deleteStats.total > 0 ? (
                            <div className="flex flex-col items-center text-slate-500 text-center">
                                <LoaderIcon size={32} className="animate-spin mb-2 mx-auto text-red-600"/> 
                                <span className="text-sm font-bold text-red-800">Suppression en cours...</span>
                                <span className="text-[10px] mt-1 font-bold">Fichier {deleteStats.current}/{deleteStats.total}</span>
                            </div>
                        ) : isSaving ? (
                            <div className="flex flex-col items-center text-slate-500 text-center">
                                <LoaderIcon size={32} className="animate-spin mb-2 mx-auto text-slate-400"/> 
                                <span className="text-sm font-bold text-slate-800">Traitement en cours...</span>
                            </div>
                        ) : (
                            <>
                                <div className="w-12 h-12 bg-white rounded-full flex items-center justify-center shadow-sm mb-3 text-purple-400"><ArrowUpIcon size={24}/></div>
                                <span className="text-sm font-bold text-slate-700">Glissez-déposez vos documents ici</span>
                                <span className="text-xs text-slate-500 mt-1 text-center mb-2">PDF, JPG, PNG (Max {quotas.privateFile} Mo/fichier)</span>
                                
                                <label className="mt-3 flex items-center gap-2 px-6 py-3 rounded-xl font-bold uppercase tracking-widest text-xs transition shadow-md bg-purple-600 text-white hover:bg-purple-700 cursor-pointer">
                                    <PlusIcon size={16} /> Ajouter des documents
                                    <input type="file" multiple accept="application/pdf,image/jpeg,image/png,image/webp" className="hidden" onChange={(e) => handleVaultUpload(e.target.files)} disabled={isSaving} />
                                </label>
                            </>
                        )}
                    </div>

                    {docs.length > 0 ? (
                        <CardGrid minWidth="140px" className="mt-6">
                            {docs.map((doc, idx) => {
                                const normalizedName = window.pano_normalizeString ? window.pano_normalizeString(doc.name) : (doc.name || '').toLowerCase();
                                const isAttestationActivation = normalizedName.includes('attestation') && normalizedName.includes('activation');
                                const isSelected = selectedDocs.includes(doc.id);

                                return (
                                    <div 
                                        key={doc.id || idx} 
                                        onClick={(e) => {
                                            if (selectedDocs.length > 0 && !isAttestationActivation) {
                                                if (isSaving) return;
                                                setSelectedDocs(prev => isSelected ? prev.filter(id => id !== doc.id) : [...prev, doc.id]);
                                            }
                                        }}
                                        className={`relative group rounded-xl border ${isSelected ? 'border-red-400 ring-2 ring-red-400/20 bg-red-50/50' : 'border-slate-200 bg-slate-50 hover:border-purple-300 hover:shadow-md'} shadow-sm flex flex-col transition ${selectedDocs.length > 0 && !isAttestationActivation ? 'cursor-pointer' : ''}`}
                                    >
                                        
                                        {!isAttestationActivation && (
                                            <Button 
                                                variant={isSelected ? "danger" : "secondary"} 
                                                shape="round"
                                                icon={CheckCircleIcon}
                                                onClick={(e) => { 
                                                    e.stopPropagation(); 
                                                    if(isSaving) return;
                                                    setSelectedDocs(prev => isSelected ? prev.filter(id => id !== doc.id) : [...prev, doc.id]); 
                                                }} 
                                                className={`absolute top-2 right-2 z-30 p-1.5 w-7 h-7 transition-all duration-200 ${isSelected ? 'opacity-100 shadow-md scale-110 border-red-300' : 'opacity-0 group-hover:opacity-100 shadow-sm border-transparent bg-white/80 backdrop-blur-sm hover:bg-white'}`}
                                                title={isSelected ? "Désélectionner" : "Sélectionner pour suppression"}
                                            />
                                        )}

                                        <div 
                                            className={`h-24 w-full flex items-center justify-center p-2 shrink-0 rounded-t-xl ${selectedDocs.length > 0 && !isAttestationActivation ? '' : 'cursor-pointer'} ${isSelected ? 'bg-transparent' : 'bg-white'}`}
                                            onClick={(e) => {
                                                if (selectedDocs.length > 0 && !isAttestationActivation) {
                                                    // Événement bubblé géré par le wrapper
                                                } else {
                                                    e.stopPropagation();
                                                    if(!isSaving) setViewingDoc(doc);
                                                }
                                            }}
                                        >
                                            {VaultDocumentThumbnail ? <VaultDocumentThumbnail doc={doc} /> : <div className="text-[10px] font-mono text-slate-400">{doc.type}</div>}
                                        </div>
                                        <div className={`p-3 border-t flex-1 flex flex-col justify-between rounded-b-xl ${isSelected ? 'border-red-200/50 bg-transparent' : 'border-slate-100 bg-white'}`}>
                                            <div>
                                                <p className="text-[11px] font-bold text-slate-700 break-words leading-tight" title={doc.name}>
                                                    {doc.name}
                                                </p>
                                                {isAttestationActivation && <span className="inline-block mt-1 px-1.5 py-0.5 bg-purple-100 text-purple-700 text-[8px] font-black uppercase tracking-widest rounded">Preuve légale</span>}
                                            </div>
                                            <div className="flex justify-between items-end mt-3">
                                                <span className="text-[9px] font-bold text-slate-400">{doc.date}</span>
                                                <div className="flex gap-1 relative z-30">
                                                    <Button variant="secondary" shape="round" icon={EyeIcon} onClick={(e) => { e.stopPropagation(); if(!isSaving) setViewingDoc(doc); }} className={`p-1.5 shadow-none w-7 h-7 ${isSelected ? 'bg-white border-white hover:border-slate-200' : ''}`} title="Consulter" />
                                                    {!isAttestationActivation && (
                                                        <Button variant="danger" shape="round" icon={Trash2Icon} onClick={(e) => { e.stopPropagation(); if(!isSaving) handleDelete(doc.id); }} className={`p-1.5 shadow-none w-7 h-7 hover:bg-red-50 ${isSelected ? 'bg-white border-white hover:border-red-200' : ''}`} title="Supprimer" />
                                                    )}
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                );
                            })}
                        </CardGrid>
                    ) : (
                        <p className="text-center text-sm text-slate-400 py-4 italic">Aucun document stocké.</p>
                    )}
                    
                    <div className="text-right border-t border-slate-100 pt-2">
                        <span className="text-xs font-bold text-slate-400">Espace utilisé : {(docs.reduce((acc, doc) => acc + (doc.size || 0), 0) / (1024*1024)).toFixed(2)} Mo</span>
                    </div>
                </div>
            </Modal>

            {uploadErrors.length > 0 && Modal && (
                <Modal 
                    title="Rapport d'importation" 
                    type="warning" 
                    onClose={() => setUploadErrors([])}
                    actions={(close) => (
                        <Button variant="secondary" onClick={close} className="w-full py-3 justify-center text-xs">Fermer</Button>
                    )}
                >
                    <div className="space-y-3 min-w-0">
                        <p className="text-sm font-bold text-slate-700 break-words">Certains fichiers n'ont pas pu être importés :</p>
                        <ul className="space-y-2">
                            {uploadErrors.map((err, i) => (
                                <li key={i} className="bg-red-50 text-red-800 text-xs p-2 rounded border border-red-100 flex items-start gap-2 break-words">
                                    <AlertTriangleIcon size={14} className="shrink-0 mt-0.5" />
                                    <div className="min-w-0">
                                        <span className="font-bold">{err.file}</span><br/>
                                        <span className="text-[10px] uppercase tracking-wider">{err.reason}</span>
                                    </div>
                                </li>
                            ))}
                        </ul>
                    </div>
                </Modal>
            )}

            {viewingDoc && UniversalViewer && (
                <UniversalViewer 
                    fileId={viewingDoc.id}
                    fileType={viewingDoc.type}
                    fileName={viewingDoc.name}
                    numPages={viewingDoc.numPages}
                    isPrivate={true}
                    useSafePdfMode={true} 
                    onClose={() => setViewingDoc(null)} 
                />
            )}

            {confirmDialog && ConfirmModal && (
                <ConfirmModal 
                    {...confirmDialog} 
                    onCancel={() => setConfirmDialog(null)}
                />
            )}
        </>
    );
};

/* EOF ========== [_react/clients/_clients_modals_vault.jsx] */