/**
 * =========================================================================
 * PLATEFORME ECO-PANNEAU.FR - VERSION 1.0.0
 * Composants : Éditeur de Panneaux et Modales de Création
 * =========================================================================
 */

const { useState } = React;
const { 
    GripVertical, Edit, Trash2, Loader, Image, Modal, Plus, MapPin, 
    FileDigit, Check, Palette, ExternalLink, Phone, Clock, Users, Eye, 
    Smartphone, HardHat, Download, X, Settings, ArrowUp, ArrowDown, Zap, AlertTriangle
} = window;

const EntityCard = ({ data, type, index, lotIndex, onEdit, onDelete, onDragStart, onDragOver, onDrop, onDragEnter, onDragLeave, onMoveUp, onMoveDown }) => {
    const isLot = type === 'lot';
    
    // Protection contre les URL blob mortes
    const logoSrc = data.logoId ? `?api=file/download&type=image&id=${data.logoId}` : (data.logoUrl?.startsWith('blob:') ? null : data.logoUrl);
    const [isDragOver, setIsDragOver] = useState(false);

    return (
        <div 
            draggable 
            onDragStart={(e) => onDragStart(e, {type, index, lotIndex})} 
            onDragOver={(e) => { e.preventDefault(); onDragOver(e); }} 
            onDragEnter={(e) => { e.preventDefault(); setIsDragOver(true); if(onDragEnter) onDragEnter(e); }}
            onDragLeave={(e) => { e.preventDefault(); setIsDragOver(false); if(onDragLeave) onDragLeave(e); }}
            onDrop={(e) => { e.preventDefault(); setIsDragOver(false); onDrop(e, {type, index, lotIndex}); }} 
            className={`bg-white border rounded-xl p-3 flex flex-col gap-2 shadow-sm relative group transition ${isDragOver ? 'border-emerald-500 bg-emerald-50/30 ring-2 ring-emerald-500/20' : 'hover:border-slate-300'} ${isLot ? 'border-slate-300 mb-3' : 'border-slate-100'}`}
        >
            <div className="flex items-start justify-between cursor-move" title="Déplacer (Glisser-déposer)">
                <div className="flex items-center gap-2 flex-1 min-w-0">
                    <GripVertical size={16} className="text-slate-300 group-hover:text-slate-500 shrink-0" />
                    {logoSrc && <img src={logoSrc} alt="logo" className="w-8 h-8 object-contain rounded bg-slate-50 border p-0.5 shrink-0" />}
                    <div className="min-w-0 flex-1">
                        <p className="font-bold text-xs text-slate-800 truncate">{data.name || 'Sans nom'}</p>
                        {!isLot && <p className="text-[10px] text-slate-500 truncate">{data.role || 'Rôle non défini'}</p>}
                        {/* CORRECTION 5A : Affichage de l'adresse postale sur la carte */}
                        {data.address && <p className="text-[9px] text-slate-400 truncate flex items-center gap-1 mt-0.5"><MapPin size={10} className="shrink-0"/> {data.address}</p>}
                    </div>
                </div>
                <div className="flex gap-1 shrink-0 ml-2 items-center">
                    {/* Boutons Haut/Bas toujours visibles pour le mobile */}
                    <div className="flex flex-col gap-0.5 mr-2">
                        <button type="button" onClick={(e) => { e.stopPropagation(); onMoveUp({type, index, lotIndex}); }} title="Monter" className="text-slate-400 hover:text-slate-700 bg-slate-50 hover:bg-slate-100 rounded p-0.5 transition"><ArrowUp size={12}/></button>
                        <button type="button" onClick={(e) => { e.stopPropagation(); onMoveDown({type, index, lotIndex}); }} title="Descendre" className="text-slate-400 hover:text-slate-700 bg-slate-50 hover:bg-slate-100 rounded p-0.5 transition"><ArrowDown size={12}/></button>
                    </div>
                    <button type="button" onClick={() => onEdit({type, index, lotIndex}, data)} title="Modifier l'élément" className="p-1.5 text-slate-400 hover:text-blue-600 hover:bg-blue-50 rounded transition"><Edit size={14}/></button>
                    <button type="button" onClick={() => onDelete({type, index, lotIndex})} title="Supprimer cet élément" className="p-1.5 text-slate-400 hover:text-red-600 hover:bg-red-50 rounded transition"><Trash2 size={14}/></button>
                </div>
            </div>
            {isLot && (
                <div className="pl-6 pt-2 border-t border-slate-100 flex flex-col gap-2">
                    {data.entreprises?.map((ent, eIdx) => (
                        <EntityCard key={ent.id || eIdx} data={ent} type="entreprise" index={eIdx} lotIndex={index} onEdit={onEdit} onDelete={onDelete} onDragStart={onDragStart} onDragOver={onDragOver} onDrop={onDrop} onDragEnter={onDragEnter} onDragLeave={onDragLeave} onMoveUp={onMoveUp} onMoveDown={onMoveDown} />
                    ))}
                    <button type="button" onClick={() => onEdit({type: 'entreprise', lotIndex: index}, {name:'', role:'', description:'', phone:'', email:'', website:'', logoId:'', logoUrl:'', address:''})} className="text-[10px] font-bold text-slate-500 hover:text-slate-800 flex items-center gap-1 py-1.5 px-2 bg-slate-50 rounded-lg border border-dashed border-slate-300 w-fit transition"><Plus size={12}/> Ajouter une entreprise à ce lot</button>
                </div>
            )}
        </div>
    );
};

const EntityEditorModal = ({ editingEntity, setEditingEntity, saveEditedEntity, showToast }) => {
    const isLot = editingEntity.location.type === 'lot';
    const [uploadingLogo, setUploadingLogo] = useState(false);
    const [isFetchingSirene, setIsFetchingSirene] = useState(false);
    
    const updateField = (field, val) => setEditingEntity({ ...editingEntity, data: { ...editingEntity.data, [field]: val } });
    
    const handleLogoUpload = async (e) => {
        const file = e.target.files[0]; if(!file) return;
        setUploadingLogo(true);
        try {
            const id = await window.uploadFile(file, 'image');
            updateField('logoId', id); updateField('logoUrl', URL.createObjectURL(file));
        } catch(err) { if (showToast) showToast(err.message, "error"); } finally { setUploadingLogo(false); }
    };

    const handleAutoFillSirene = async () => {
        const num = prompt("Saisissez le SIREN (9 chiffres) ou SIRET (14 chiffres) de l'entreprise :");
        if (!num) return;
        const cleanNum = num.replace(/\D/g, '');
        if (cleanNum.length !== 9 && cleanNum.length !== 14) return showToast("Le numéro doit contenir 9 ou 14 chiffres.", "error");

        setIsFetchingSirene(true);
        try {
            const res = await fetch(window.ECO_CONFIG.apiBaseUrl + 'system/sirene', { method: 'POST', body: JSON.stringify({ q: cleanNum }) });
            const responseData = await res.json();
            if (responseData.status !== 'success') throw new Error(responseData.message);

            const apiData = responseData.data;
            if (apiData.results && apiData.results.length > 0) {
                const company = apiData.results[0];
                updateField('name', company.nom_complet);
                
                const siege = company.siege || {};
                const addressParts = [siege.numero_voie, siege.indice_repetition, siege.type_voie, siege.libelle_voie, siege.code_postal, siege.libelle_commune];
                const fullAddress = addressParts.filter(Boolean).join(' ').replace(/\s+/g, ' ').trim();
                if (fullAddress) updateField('address', fullAddress);

                showToast("Informations récupérées !", "success");
            } else {
                showToast("Aucune entreprise trouvée.", "error");
            }
        } catch (err) {
            showToast("Le service d'annuaire est indisponible.", "error");
        }
        setIsFetchingSirene(false);
    };

    // Protection contre les URL blob mortes
    const logoSrc = editingEntity.data.logoId ? `?api=file/download&type=image&id=${editingEntity.data.logoId}` : (editingEntity.data.logoUrl?.startsWith('blob:') ? null : editingEntity.data.logoUrl);

    return (
        <Modal title={isLot ? "Édition du lot" : "Édition de l'intervenant"} onClose={() => setEditingEntity(null)} preventClose={uploadingLogo || isFetchingSirene}>
            <div className="space-y-4">
                {!isLot && (
                    <div className="flex justify-end mb-2">
                        <button type="button" onClick={handleAutoFillSirene} disabled={isFetchingSirene} className="text-xs bg-blue-50 text-blue-700 hover:bg-blue-100 px-3 py-1.5 rounded-lg flex items-center gap-1 font-bold transition shadow-sm disabled:opacity-50">
                            {isFetchingSirene ? <Loader size={14} className="animate-spin"/> : <Zap size={14}/>} Saisie automatique SIREN ou SIRET
                        </button>
                    </div>
                )}
                
                <div className="space-y-1">
                    <label className="text-xs font-bold text-slate-500 uppercase block">{isLot ? 'Nom du lot' : 'Nom de la société / personne'}</label>
                    <input value={editingEntity.data.name || ''} maxLength="100" onChange={e=>updateField('name', e.target.value)} autoFocus className="w-full border-2 border-slate-200 rounded-xl p-3 text-sm focus:border-slate-800 outline-none transition" />
                </div>
                
                {!isLot && (
                    <>
                        <div className="space-y-1"><label className="text-xs font-bold text-slate-500 uppercase block">Rôle / Mission</label><input value={editingEntity.data.role || ''} maxLength="100" onChange={e=>updateField('role', e.target.value)} className="w-full border-2 border-slate-200 rounded-xl p-3 text-sm focus:border-slate-800 outline-none transition" placeholder="Ex: Architecte D.P.L.G" /></div>
                        <div className="grid grid-cols-2 gap-4">
                            <div className="space-y-1"><label className="text-xs font-bold text-slate-500 uppercase block">Téléphone</label><input value={editingEntity.data.phone || ''} maxLength="30" onChange={e=>updateField('phone', e.target.value)} className="w-full border-2 border-slate-200 rounded-xl p-3 text-sm focus:border-slate-800 outline-none transition" /></div>
                            <div className="space-y-1"><label className="text-xs font-bold text-slate-500 uppercase block">E-mail</label><input value={editingEntity.data.email || ''} maxLength="100" onChange={e=>updateField('email', e.target.value)} className="w-full border-2 border-slate-200 rounded-xl p-3 text-sm focus:border-slate-800 outline-none transition" /></div>
                        </div>
                        <div className="space-y-1 mt-4">
                            <label className="text-xs font-bold text-slate-500 uppercase block">Adresse postale</label>
                            <textarea value={editingEntity.data.address || ''} maxLength="255" rows="2" onChange={e=>updateField('address', e.target.value)} className="w-full border-2 border-slate-200 rounded-xl p-3 text-sm focus:border-slate-800 outline-none transition resize-none"></textarea>
                        </div>
                        <div className="space-y-1 mt-4">
                            <label className="text-xs font-bold text-slate-500 uppercase block">Logo</label>
                            <div className="flex items-center gap-4">
                                {logoSrc && <img src={logoSrc} className="w-16 h-16 object-contain rounded-lg border p-1 bg-white" alt="logo" />}
                                <label className="bg-slate-100 hover:bg-slate-200 text-slate-700 px-4 py-2 rounded-xl text-xs font-bold cursor-pointer transition border border-slate-200 flex items-center gap-2">
                                    {uploadingLogo ? <Loader size={14} className="animate-spin"/> : <Image size={14}/>} Changer le logo
                                    <input type="file" accept="image/png, image/jpeg, image/webp" className="hidden" disabled={uploadingLogo} onChange={handleLogoUpload} />
                                </label>
                                {logoSrc && <button onClick={() => {updateField('logoId',''); updateField('logoUrl','');}} title="Supprimer le logo" className="text-xs text-red-500 font-bold hover:underline">Supprimer</button>}
                            </div>
                        </div>
                    </>
                )}
                <button onClick={saveEditedEntity} disabled={uploadingLogo || isFetchingSirene || !editingEntity.data.name?.trim()} className="w-full bg-slate-900 text-white py-3 rounded-xl font-bold uppercase tracking-widest hover:bg-slate-800 transition shadow-md mt-6 disabled:opacity-50">Valider</button>
            </div>
        </Modal>
    );
};

const PanneauEditorForm = ({ panneau, setPanneau, managingPanneau, onCancel, onSaveDraft, onPublish, onSaveActive, onPreview, onEditEntity, draggedItem, handleDragStart, handleDragOver, handleDrop, deleteEntity, isSaving, uiMode = 'simplifie', lockedFields = [], validationErrors = [], settings = {}, showToast }) => {
    const [touched, setTouched] = useState({});
    const [uploadingStates, setUploadingStates] = useState({ image: false, pdf: false, moaLogo: false });
    const [confirmDialog, setConfirmDialog] = useState(null);
    const [blacklistWarning, setBlacklistWarning] = useState(null);

    const updateField = (field, val) => setPanneau(prev => ({ ...prev, [field]: val }));
    const handleBlur = (field) => setTouched(prev => ({ ...prev, [field]: true }));
    const isError = (field) => validationErrors.length > 0 && (!panneau[field] || String(panneau[field]).trim() === '');
    const isLocked = (field) => uiMode === 'delege' && lockedFields.includes(field);

    const handleImageUpload = async (e) => {
        const file = e.target.files[0]; if(!file) return;
        setUploadingStates(p => ({...p, image: true}));
        try { const id = await window.uploadFile(file, 'image'); updateField('imageId', id); updateField('imageUrl', URL.createObjectURL(file)); setTouched(p => ({...p, imageId: true})); } 
        catch(err) { if (showToast) showToast(err.message, "error"); } finally { setUploadingStates(p => ({...p, image: false})); e.target.value = null; }
    };
    const handlePdfUpload = async (e) => {
        const file = e.target.files[0]; if(!file) return;
        setUploadingStates(p => ({...p, pdf: true}));
        try { const id = await window.uploadFile(file, 'pdf'); updateField('pdfId', id); setTouched(p => ({...p, pdfId: true})); } 
        catch(err) { if (showToast) showToast(err.message, "error"); } finally { setUploadingStates(p => ({...p, pdf: false})); e.target.value = null; }
    };
    const handleMoaLogoUpload = async (e) => {
        const file = e.target.files[0]; if(!file) return;
        setUploadingStates(p => ({...p, moaLogo: true}));
        try { const id = await window.uploadFile(file, 'image'); updateField('maitreOuvrageLogoId', id); updateField('maitreOuvrageLogoUrl', URL.createObjectURL(file)); setTouched(p => ({...p, moaLogo: true})); } 
        catch(err) { if (showToast) showToast(err.message, "error"); } finally { setUploadingStates(p => ({...p, moaLogo: false})); e.target.value = null; }
    };

    const isUploading = Object.values(uploadingStates).some(v => v);
    
    // Protection stricte contre les URL blob
    const moaLogoSrc = panneau.maitreOuvrageLogoId ? `?api=file/download&type=image&id=${panneau.maitreOuvrageLogoId}` : (panneau.maitreOuvrageLogoUrl?.startsWith('blob:') ? null : panneau.maitreOuvrageLogoUrl);
    const mainImgSrc = panneau.imageId ? `?api=file/download&type=image&id=${panneau.imageId}` : (panneau.imageUrl?.startsWith('blob:') ? null : panneau.imageUrl);

    const handleCancelClick = () => {
        if (Object.keys(touched).length > 0 && !isSaving) {
            setConfirmDialog({
                title: "Annuler les modifications",
                message: "Vous avez des modifications non sauvegardées. Êtes-vous sûr de vouloir annuler et perdre ces changements ?",
                confirmText: "Oui, annuler",
                isDestructive: true,
                onConfirm: onCancel
            });
        } else {
            onCancel();
        }
    };

    const checkForBlacklistedWords = () => {
        if (!settings?.blacklist) return null;
        const words = settings.blacklist.split(',').map(w => w.trim().toLowerCase()).filter(w => w);
        const fieldsToCheck = [
            { name: 'Nom du chantier', val: panneau.name },
            { name: 'Lieu', val: panneau.location },
            { name: 'Maître d\'ouvrage', val: panneau.maitreOuvrage },
            { name: 'Description', val: panneau.description }
        ];

        for (let field of fieldsToCheck) {
            if (!field.val) continue;
            const content = field.val.toLowerCase();
            for (let word of words) {
                if (content.includes(word)) {
                    return { word, field: field.name };
                }
            }
        }
        return null;
    };

    const cleanPayload = () => {
        // PURGE LES URLS BLOB TEMPORAIRES AVANT SAUVEGARDE EN BDD
        const cleanDetails = { ...managingPanneau, name: managingPanneau.name?.trim() || 'Brouillon sans nom', location: managingPanneau.location?.trim() || '' };
        delete cleanDetails.imageUrl;
        delete cleanDetails.maitreOuvrageLogoUrl;
        if (cleanDetails.intervenants) {
            cleanDetails.intervenants = cleanDetails.intervenants.map(i => { const ci = {...i}; delete ci.logoUrl; return ci; });
        }
        if (cleanDetails.lots) {
            cleanDetails.lots = cleanDetails.lots.map(l => {
                const cl = {...l};
                if (cl.entreprises) cl.entreprises = cl.entreprises.map(e => { const ce = {...e}; delete ce.logoUrl; return ce; });
                return cl;
            });
        }
        return cleanDetails;
    };

    const executeSaveAction = (actionFn) => {
        const detected = checkForBlacklistedWords();
        if (detected) {
            setBlacklistWarning({
                detected,
                onConfirm: () => {
                    setBlacklistWarning(null);
                    // On transmet la fonction de sauvegarde, l'appelant s'occupera d'utiliser cleanPayload()
                    actionFn();
                }
            });
        } else {
            actionFn();
        }
    };

    const handleMoveUp = (loc) => {
        let newInter = [...(panneau.intervenants || [])];
        let newLots = JSON.parse(JSON.stringify(panneau.lots || []));
        if (loc.type === 'intervenant' && loc.index > 0) {
            const item = newInter.splice(loc.index, 1)[0];
            newInter.splice(loc.index - 1, 0, item);
        } else if (loc.type === 'lot' && loc.index > 0) {
            const item = newLots.splice(loc.index, 1)[0];
            newLots.splice(loc.index - 1, 0, item);
        } else if (loc.type === 'entreprise' && loc.index > 0) {
            const arr = newLots[loc.lotIndex].entreprises;
            const item = arr.splice(loc.index, 1)[0];
            arr.splice(loc.index - 1, 0, item);
        }
        setPanneau({ ...panneau, intervenants: newInter, lots: newLots });
        handleBlur('order');
    };

    const handleMoveDown = (loc) => {
        let newInter = [...(panneau.intervenants || [])];
        let newLots = JSON.parse(JSON.stringify(panneau.lots || []));
        if (loc.type === 'intervenant' && loc.index < newInter.length - 1) {
            const item = newInter.splice(loc.index, 1)[0];
            newInter.splice(loc.index + 1, 0, item);
        } else if (loc.type === 'lot' && loc.index < newLots.length - 1) {
            const item = newLots.splice(loc.index, 1)[0];
            newLots.splice(loc.index + 1, 0, item);
        } else if (loc.type === 'entreprise' && loc.index < newLots[loc.lotIndex].entreprises.length - 1) {
            const arr = newLots[loc.lotIndex].entreprises;
            const item = arr.splice(loc.index, 1)[0];
            arr.splice(loc.index + 1, 0, item);
        }
        setPanneau({ ...panneau, intervenants: newInter, lots: newLots });
        handleBlur('order');
    };

    const allSimpOptionsActive = 
        settings?.simp_opt_description === '1' &&
        settings?.simp_opt_image === '1' &&
        settings?.simp_opt_theme === '1' &&
        settings?.simp_opt_link === '1' &&
        settings?.simp_opt_emergency === '1' &&
        settings?.simp_opt_schedule === '1';

    const isAdvancedMode = uiMode !== 'simplifie' || allSimpOptionsActive;

    const showOpt = (key) => {
        if (uiMode !== 'simplifie') return true;
        return settings?.[`simp_opt_${key}`] === '1';
    };

    return (
        <div className="flex flex-col h-full bg-white relative">
            <div className="flex-1 overflow-y-auto p-4 sm:p-8 custom-scrollbar pb-32 space-y-8">
                
                <div className="bg-slate-50 p-4 sm:p-6 rounded-2xl border border-slate-100 space-y-6 shadow-sm">
                    <h3 className="font-black text-slate-800 border-b pb-2 flex items-center gap-2"><MapPin size={18} className="text-emerald-600"/> Identité du panneau</h3>
                    
                    <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                        <div className="space-y-1">
                            <label className="text-xs font-bold text-slate-500 uppercase block">Nom du chantier <span className="text-red-500">*</span></label>
                            <input value={panneau.name || ''} maxLength="120" onChange={e=>updateField('name', e.target.value)} onBlur={() => handleBlur('name')} onFocus={(e) => setTimeout(() => e.target.scrollIntoView({ behavior: 'smooth', block: 'center' }), 300)} disabled={isLocked('name') || (managingPanneau?.status === 'Actif' && managingPanneau?.offerType === 'purchase')} className={`w-full border-2 rounded-xl p-3 text-sm outline-none transition disabled:bg-slate-100 disabled:text-slate-400 disabled:cursor-not-allowed ${isError('name') ? 'border-red-500 bg-red-50' : 'border-slate-200 focus:border-emerald-500'}`} placeholder="Ex: Résidence Cambon" />
                        </div>
                        <div className="space-y-1">
                            <label className="text-xs font-bold text-slate-500 uppercase block">Ville / Lieu <span className="text-red-500">*</span></label>
                            <input value={panneau.location || ''} maxLength="150" onChange={e=>updateField('location', e.target.value)} onBlur={() => handleBlur('location')} onFocus={(e) => setTimeout(() => e.target.scrollIntoView({ behavior: 'smooth', block: 'center' }), 300)} disabled={isLocked('location') || (managingPanneau?.status === 'Actif' && managingPanneau?.offerType === 'purchase')} className={`w-full border-2 rounded-xl p-3 text-sm outline-none transition disabled:bg-slate-100 disabled:text-slate-400 disabled:cursor-not-allowed ${isError('location') ? 'border-red-500 bg-red-50' : 'border-slate-200 focus:border-emerald-500'}`} placeholder="Ex: Fréjus" />
                        </div>
                    </div>

                    <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                        <div className="space-y-1">
                            <label className="text-xs font-bold text-slate-500 uppercase block">Maître d'ouvrage</label>
                            <div className="flex gap-2">
                                <input value={panneau.maitreOuvrage || ''} maxLength="120" onChange={e=>{updateField('maitreOuvrage', e.target.value); handleBlur('maitreOuvrage');}} onFocus={(e) => setTimeout(() => e.target.scrollIntoView({ behavior: 'smooth', block: 'center' }), 300)} disabled={isLocked('maitreOuvrage')} className="flex-1 border-2 border-slate-200 rounded-xl p-3 text-sm focus:border-emerald-500 outline-none transition disabled:bg-slate-100 disabled:text-slate-400 disabled:cursor-not-allowed" placeholder="Société ou nom" />
                                {isAdvancedMode && (
                                    <label className={`h-[46px] bg-slate-100 border border-slate-200 text-slate-600 rounded-xl px-3 flex items-center justify-center transition shrink-0 ${isLocked('maitreOuvrage') ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer hover:bg-slate-200'}`} title="Ajouter un logo pour le maître d'ouvrage">
                                        {uploadingStates.moaLogo ? <Loader size={16} className="animate-spin" /> : <><Image size={16} className="sm:mr-1" /><span className="hidden sm:block text-xs font-bold">Logo</span></>}
                                        <input type="file" accept="image/png, image/jpeg, image/webp" className="hidden" disabled={uploadingStates.moaLogo || isLocked('maitreOuvrage')} onChange={handleMoaLogoUpload} />
                                    </label>
                                )}
                            </div>
                            {moaLogoSrc && (
                                <div className="flex items-center gap-2 mt-2 bg-white p-2 rounded-xl border border-slate-200 w-fit shadow-sm">
                                    <img src={moaLogoSrc} alt="Logo MOA" className="h-8 object-contain" />
                                    {!isLocked('maitreOuvrage') && <button type="button" onClick={() => {updateField('maitreOuvrageLogoId',''); updateField('maitreOuvrageLogoUrl',''); setTouched(p => ({...p, moaLogo: true}));}} title="Supprimer le logo" className="text-red-500 hover:text-red-700 p-1"><Trash2 size={14}/></button>}
                                </div>
                            )}
                        </div>
                        <div className="space-y-1">
                            <label className="text-xs font-bold text-slate-500 uppercase block">N° de permis / DP</label>
                            <input value={panneau.permitNumber || ''} maxLength="50" onChange={e=>{updateField('permitNumber', e.target.value); handleBlur('permitNumber');}} onFocus={(e) => setTimeout(() => e.target.scrollIntoView({ behavior: 'smooth', block: 'center' }), 300)} disabled={isLocked('permitNumber')} className="w-full border-2 border-slate-200 rounded-xl p-3 text-sm focus:border-emerald-500 outline-none transition uppercase disabled:bg-slate-100 disabled:text-slate-400 disabled:cursor-not-allowed" placeholder="PC 000 000 00 00000" />
                        </div>
                    </div>
                </div>

                <div className={`p-4 rounded-2xl border space-y-4 shadow-sm ${(!panneau.pdfId && validationErrors.length > 0) ? 'bg-red-50 border-red-300' : 'bg-blue-50 border-blue-100'}`}>
                    <h3 className={`font-black flex items-center gap-2 ${(!panneau.pdfId && validationErrors.length > 0) ? 'text-red-900' : 'text-blue-900'}`}><FileDigit size={18}/> Arrêté légal <span className="text-red-500">*</span></h3>
                    <div className="space-y-1">
                        <label className="text-xs font-bold text-slate-500 uppercase block flex items-center gap-1">Permis de construire (PDF - max 5 Mo)</label>
                        <input type="file" accept="application/pdf" disabled={uploadingStates.pdf || isLocked('pdfId')} onChange={handlePdfUpload} className={`w-full text-xs file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-xs file:font-bold file:bg-white ${(!panneau.pdfId && validationErrors.length > 0) ? 'file:text-red-700 hover:file:bg-red-100' : 'file:text-blue-700 hover:file:bg-blue-100'} ${isLocked('pdfId') ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}`} />
                        {uploadingStates.pdf && <p className="text-xs text-blue-600 font-bold flex items-center gap-1 mt-2"><Loader size={12} className="animate-spin"/> Upload en cours...</p>}
                        {panneau.pdfId && !uploadingStates.pdf && (
                            <div className="flex items-center gap-2 mt-2 bg-white p-2 rounded-xl border border-blue-200 shadow-sm w-fit">
                                <span className="text-xs text-emerald-600 font-bold flex items-center gap-1 px-2"><Check size={14}/> PDF Actif</span>
                                {!isLocked('pdfId') && <button type="button" onClick={() => {updateField('pdfId', ''); setTouched(p => ({...p, pdfId: true}));}} className="text-xs text-red-500 hover:text-red-700 font-bold px-2 border-l" title="Supprimer le PDF">Supprimer</button>}
                            </div>
                        )}
                    </div>
                </div>

                {(showOpt('description') || showOpt('image') || showOpt('theme') || showOpt('link') || showOpt('emergency') || showOpt('schedule')) && (
                    <div className="bg-slate-50 p-4 sm:p-6 rounded-2xl border border-slate-100 space-y-6 shadow-sm">
                        <h3 className="font-black text-slate-800 border-b pb-2 flex items-center gap-2"><Settings size={18} className="text-emerald-600"/> Options avancées</h3>
                        
                        {showOpt('description') && <div className="space-y-1"><label className="text-xs font-bold text-slate-500 uppercase block">Description des travaux</label><textarea value={panneau.description || ''} maxLength="800" onChange={e=>{updateField('description', e.target.value); handleBlur('description');}} onFocus={(e) => setTimeout(() => e.target.scrollIntoView({ behavior: 'smooth', block: 'center' }), 300)} disabled={isLocked('description')} className="w-full border-2 border-slate-200 rounded-xl p-3 text-sm focus:border-emerald-500 outline-none transition resize-none disabled:bg-slate-100 disabled:text-slate-400 disabled:cursor-not-allowed" placeholder="Ex: Rénovation de la façade et isolation thermique" /></div>}
                        
                        <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
                            {showOpt('image') && (
                                <div className="space-y-1">
                                    <label className="text-xs font-bold text-slate-500 uppercase block flex items-center gap-1">Image du panneau (max 5 Mo)</label>
                                    <input type="file" accept="image/png, image/jpeg, image/webp" disabled={uploadingStates.image || isLocked('imageId')} onChange={handleImageUpload} className={`w-full text-xs file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-xs file:font-bold file:bg-emerald-50 file:text-emerald-700 hover:file:bg-emerald-100 ${isLocked('imageId') ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}`} />
                                    {uploadingStates.image && <p className="text-xs text-emerald-600 font-bold mt-2">Upload en cours...</p>}
                                    {mainImgSrc && !uploadingStates.image && (
                                        <div className="flex flex-col items-center justify-center mt-2 border p-2 rounded-xl bg-white shadow-sm w-fit">
                                            <img src={mainImgSrc} alt="Aperçu" className="h-16 object-contain mb-2 rounded" />
                                            {!isLocked('imageId') && <button type="button" onClick={() => {updateField('imageId', ''); updateField('imageUrl', ''); setTouched(p => ({...p, imageId: true}));}} className="text-xs text-red-500 font-bold" title="Supprimer l'image">Supprimer</button>}
                                        </div>
                                    )}
                                </div>
                            )}
                            {showOpt('theme') && (
                                <div className="space-y-2">
                                    <label className="text-xs font-bold text-slate-500 uppercase block flex items-center gap-1"><Palette size={12} /> Couleur du thème</label>
                                    <div className={`flex flex-wrap gap-2 ${isLocked('themeColor') ? 'opacity-50 pointer-events-none' : ''}`}>
                                        {window.predefinedThemes.map(c => (<button key={c} type="button" onClick={() => {updateField('themeColor', c); handleBlur('themeColor');}} title={`Couleur ${c}`} className={`w-8 h-8 rounded-full border-2 transition-transform ${panneau.themeColor === c ? 'border-slate-800 scale-110' : 'border-white shadow-sm'}`} style={{backgroundColor: c}}></button>))}
                                    </div>
                                </div>
                            )}
                        </div>

                        <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
                            {showOpt('link') && <div className="space-y-1"><label className="text-xs font-bold text-slate-500 uppercase block flex items-center gap-1"><ExternalLink size={12}/> Lien promoteur</label><input value={panneau.promoterLink || ''} maxLength="255" onChange={e=>{updateField('promoterLink', e.target.value); handleBlur('promoterLink');}} onFocus={(e) => setTimeout(() => e.target.scrollIntoView({ behavior: 'smooth', block: 'center' }), 300)} disabled={isLocked('promoterLink')} className="w-full border-2 border-slate-200 rounded-xl p-3 text-sm focus:border-emerald-500 outline-none transition disabled:bg-slate-100 disabled:text-slate-400 disabled:cursor-not-allowed" /></div>}
                            {showOpt('emergency') && <div className="space-y-1"><label className="text-xs font-bold text-slate-500 uppercase block flex items-center gap-1"><Phone size={12}/> N° d'urgence</label><input value={panneau.emergencyPhone || ''} maxLength="30" onChange={e=>{updateField('emergencyPhone', e.target.value); handleBlur('emergencyPhone');}} onFocus={(e) => setTimeout(() => e.target.scrollIntoView({ behavior: 'smooth', block: 'center' }), 300)} disabled={isLocked('emergencyPhone')} className="w-full border-2 border-slate-200 rounded-xl p-3 text-sm outline-none focus:border-emerald-500 transition disabled:bg-slate-100 disabled:text-slate-400 disabled:cursor-not-allowed" placeholder="06XXXXXXXX" /></div>}
                        </div>
                        
                        {showOpt('schedule') && <div className="space-y-1"><label className="text-xs font-bold text-slate-500 uppercase block flex items-center gap-1"><Clock size={12}/> Horaires des nuisances</label><input value={panneau.noiseSchedule || ''} maxLength="100" onChange={e=>{updateField('noiseSchedule', e.target.value); handleBlur('noiseSchedule');}} onFocus={(e) => setTimeout(() => e.target.scrollIntoView({ behavior: 'smooth', block: 'center' }), 300)} disabled={isLocked('noiseSchedule')} className="w-full border-2 border-slate-200 rounded-xl p-3 text-sm focus:border-emerald-500 outline-none transition disabled:bg-slate-100 disabled:text-slate-400 disabled:cursor-not-allowed" placeholder="8h à 17h" /></div>}
                        
                        {isAdvancedMode && (
                            <div className="space-y-1 mt-4 pt-4 border-t border-slate-200">
                                <label className={`flex items-center gap-3 p-2 rounded-lg transition w-fit ${isLocked('hasNoAds') ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer hover:bg-slate-100'}`}>
                                    <input type="checkbox" checked={panneau.hasNoAds || false} disabled={isLocked('hasNoAds')} onChange={(e) => updateField('hasNoAds', e.target.checked)} className="w-5 h-5 accent-emerald-600 cursor-pointer" />
                                    <div>
                                        <span className="text-sm font-bold text-slate-800">Option marque blanche (sans mention d'eco-panneau.fr)</span>
                                    </div>
                                </label>
                            </div>
                        )}
                    </div>
                )}

                {isAdvancedMode && (
                    <div className="bg-slate-50 p-4 sm:p-6 rounded-2xl border border-slate-100 shadow-sm">
                        <div className="flex justify-between items-center mb-6 border-b pb-2">
                            <h3 className="font-black text-slate-800 flex items-center gap-2"><Users size={18} className="text-emerald-600"/> L'équipe du projet</h3>
                        </div>
                        
                        <div className="space-y-6">
                            <div>
                                <h4 className="text-xs font-black text-slate-500 uppercase mb-3 tracking-wider">Intervenants principaux</h4>
                                <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
                                    {panneau.intervenants?.map((inter, idx) => (
                                        <EntityCard key={inter.id || idx} data={inter} type="intervenant" index={idx} onEdit={onEditEntity} onDelete={(loc) => {deleteEntity(loc); handleBlur('intervenants');}} onDragStart={handleDragStart} onDragOver={handleDragOver} onDrop={(e, loc) => {handleDrop(e, loc); handleBlur('intervenants');}} onMoveUp={handleMoveUp} onMoveDown={handleMoveDown} />
                                    ))}
                                </div>
                                <button type="button" onClick={() => onEditEntity({type: 'intervenant'}, {name:'', role:'', description:'', phone:'', email:'', website:'', logoId:'', logoUrl:''})} className="mt-3 text-xs font-bold text-emerald-600 hover:text-emerald-800 flex items-center gap-1 py-2 px-3 bg-emerald-50 rounded-lg transition border border-emerald-200 shadow-sm"><Plus size={14}/> Ajouter un intervenant</button>
                            </div>
                            
                            <div className="border-t border-slate-200 pt-6">
                                <h4 className="text-xs font-black text-slate-500 uppercase mb-3 tracking-wider">Sous-traitants par lot</h4>
                                <div className="space-y-4">
                                    {panneau.lots?.map((lot, lIdx) => (
                                        <EntityCard key={lot.id || lIdx} data={lot} type="lot" index={lIdx} onEdit={onEditEntity} onDelete={(loc) => {deleteEntity(loc); handleBlur('lots');}} onDragStart={handleDragStart} onDragOver={handleDragOver} onDrop={(e, loc) => {handleDrop(e, loc); handleBlur('lots');}} onMoveUp={handleMoveUp} onMoveDown={handleMoveDown} />
                                    ))}
                                </div>
                                <button type="button" onClick={() => onEditEntity({type: 'lot'}, {name:'', entreprises:[]})} className="mt-3 text-xs font-bold text-blue-600 hover:text-blue-800 flex items-center gap-1 py-2 px-3 bg-blue-50 rounded-lg transition border border-blue-200 shadow-sm"><Plus size={14}/> Créer un nouveau lot</button>
                            </div>
                        </div>
                    </div>
                )}
                
                <div className="text-right">
                    <p className="text-[10px] font-bold text-slate-400 inline-block px-2 py-1 bg-slate-50 rounded border border-slate-100">
                        <span className="text-red-500 mr-1">*</span> Champs obligatoires
                    </p>
                </div>

            </div>

            <div className="shrink-0 p-4 bg-white border-t border-slate-200 flex justify-between gap-4 z-10 shadow-[0_-10px_20px_-10px_rgba(0,0,0,0.05)]">
                <button id="editor-cancel-btn" type="button" onClick={handleCancelClick} disabled={isSaving || isUploading} title="Annuler les modifications" className="px-4 sm:px-6 py-3 rounded-xl font-bold text-slate-500 hover:bg-slate-100 transition disabled:opacity-50">Annuler</button>
                <div className="flex gap-2 w-full justify-end">
                    {onPreview && (
                        <button type="button" onClick={onPreview} disabled={isSaving || isUploading} title="Aperçu du panneau" className="hidden sm:flex bg-blue-50 text-blue-700 py-3 px-6 rounded-xl font-black uppercase tracking-widest hover:bg-blue-100 transition disabled:opacity-50 items-center gap-2">
                            <Eye size={18}/> Aperçu
                        </button>
                    )}
                    {onSaveDraft && (
                        <button type="button" onClick={() => executeSaveAction(() => onSaveDraft(cleanPayload()))} disabled={isSaving || isUploading} title="Enregistrer en tant que brouillon (hors ligne)" className="bg-slate-100 text-slate-600 py-3 px-4 sm:px-6 rounded-xl font-black uppercase tracking-widest hover:bg-slate-200 transition disabled:opacity-50 flex items-center gap-2">
                            {isSaving ? <Loader className="animate-spin w-5 h-5"/> : 'Enregistrer (brouillon)'}
                        </button>
                    )}
                    {(onPublish || onSaveActive) && (
                        <button type="button" onClick={() => executeSaveAction(() => (onPublish || onSaveActive)(cleanPayload()))} disabled={isSaving || isUploading} title="Publier ce panneau et le rendre visible" className="bg-emerald-600 text-white py-3 px-4 sm:px-8 rounded-xl font-black uppercase tracking-widest hover:bg-emerald-700 transition shadow-lg disabled:opacity-50 flex items-center justify-center gap-2">
                            {isSaving ? <Loader className="animate-spin w-5 h-5"/> : (managingPanneau?.status === 'Actif' ? 'Publier (actif)' : 'Publier')}
                        </button>
                    )}
                </div>
            </div>

            {blacklistWarning && (
                <window.ConfirmModal 
                    title="Avertissement de modération" 
                    message={`L'utilisation du terme "${blacklistWarning.detected.word}" dans le champ "${blacklistWarning.detected.field}" a été détectée. Votre panneau fera l'objet d'un contrôle automatique par le support technique. En publiant, vous acceptez de porter la responsabilité des propos tenus sur cet affichage légal.`}
                    confirmText="J'accepte la responsabilité" 
                    onConfirm={blacklistWarning.onConfirm} 
                    onCancel={() => setBlacklistWarning(null)} 
                    isDestructive={false}
                    zIndex="z-[260]"
                />
            )}

            {confirmDialog && <window.ConfirmModal {...confirmDialog} zIndex="z-[250]" onCancel={() => setConfirmDialog(null)} />}
        </div>
    );
};

const PreviewModal = ({ panneau, onClose, initialType = 'virtual', showToast, interactions = [], refreshData }) => {
    const [viewType, setViewType] = useState(initialType);
    const [generatingA1, setGeneratingA1] = useState(false);
    return (
        <div className="fixed inset-0 bg-slate-900/90 z-[300] flex items-center justify-center p-2 sm:p-4 backdrop-blur-md animate-in fade-in" onMouseDown={onClose}>
            <div className="bg-slate-100 rounded-3xl w-full max-w-5xl h-[95vh] flex flex-col shadow-2xl overflow-hidden border border-slate-200" onMouseDown={e => e.stopPropagation()}>
                <div className="p-4 bg-white border-b flex justify-between items-center shrink-0">
                    <div className="flex bg-slate-100 p-1 rounded-xl">
                        <button onClick={()=>setViewType('virtual')} title="Aperçu smartphone" className={`px-4 py-2 rounded-lg text-xs font-bold transition flex items-center gap-2 ${viewType === 'virtual' ? 'bg-white shadow-sm text-slate-900' : 'text-slate-500 hover:text-slate-700'}`}><Smartphone size={14}/> Virtuel</button>
                        <button onClick={()=>setViewType('physical')} title="Aperçu panneau physique" className={`px-4 py-2 rounded-lg text-xs font-bold transition flex items-center gap-2 ${viewType === 'physical' ? 'bg-white shadow-sm text-slate-900' : 'text-slate-500 hover:text-slate-700'}`}><HardHat size={14}/> Panneau A1</button>
                    </div>
                    <button onClick={onClose} title="Fermer l'aperçu" className="p-2 hover:bg-slate-100 rounded-xl text-slate-500 transition"><X size={20}/></button>
                </div>
                <div className="flex-1 overflow-auto flex items-center justify-center p-4 relative bg-slate-200/50">
                    {viewType === 'virtual' ? (
                        // MOCKUP IPHONE 17 (393x852) - Strictement délimité pour empêcher la fuite du composant
                        <div className="w-[393px] h-[852px] bg-white rounded-[3rem] shadow-2xl border-[8px] border-slate-900 relative shrink-0 scale-[0.7] sm:scale-100 origin-top flex flex-col overflow-hidden">
                            <div className="absolute top-0 inset-x-0 h-6 bg-slate-900 rounded-b-3xl w-40 mx-auto z-[60]"></div>
                            <div className="flex-1 w-full h-full relative rounded-[2rem] overflow-hidden">
                                <window.RiverainView panneau={{...panneau, id: 'demo-panneau'}} showToast={showToast} interactions={interactions} refreshData={refreshData} isPreview={true} />
                            </div>
                        </div>
                    ) : (
                        <div className="w-full h-full flex flex-col items-center justify-center gap-6">
                            <div className="w-full max-w-3xl bg-white shadow-2xl border border-slate-200 shrink-0 pointer-events-none">
                                <window.PrintA1View panneau={panneau} />
                            </div>
                            <button onClick={async () => {
                                setGeneratingA1(true);
                                try { const blob = await window.generateA1PDF(panneau); const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = `panneau_A1.pdf`; link.click(); } catch(e) { showToast("Erreur PDF", "error"); }
                                setGeneratingA1(false);
                            }} disabled={generatingA1} title="Générer et télécharger le PDF haute définition" className="bg-slate-900 text-white px-6 py-3 rounded-xl font-bold flex items-center gap-2 shadow-lg hover:bg-slate-800 disabled:opacity-50 z-10">{generatingA1 ? <Loader className="animate-spin" size={16}/> : <Download size={16}/>} Télécharger le PDF A1 haute définition</button>
                        </div>
                    )}
                </div>
            </div>
        </div>
    );
};

Object.assign(window, { EntityCard, EntityEditorModal, PanneauEditorForm, PreviewModal });

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