/* ============================================
   MODULE SPECIFICATION (per module)
   ============================================ */
function renderAllModuleSpecs() {
    const container = document.getElementById('moduleSpecContainer');
    container.innerHTML = data.modules.map(m => renderModuleSpecSection(m)).join('');
    // Bind editable fields in module specs
    container.querySelectorAll('.editable[data-module-field]').forEach(el => {
        el.addEventListener('blur', function() {
            const code = this.dataset.moduleCode;
            const field = this.dataset.moduleField;
            if (data.moduleSpecs[code]) {
                data.moduleSpecs[code][field] = this.textContent.trim();
                autoSave();
            }
        });
    });
    // Restore currently visible section after re-render
    restoreCurrentSection();
    // Re-initialize inline comment buttons on module spec cards
    if (typeof initInlineComments === 'function') initInlineComments();
}

function renderModuleSpecSection(mod) {
    const code = mod.code;
    const spec = data.moduleSpecs[code] || { useCases: [], businessRules: [], entities: [], permissions: [], notes: '' };

    return `
    <div class="section" id="module-spec-${code}" style="display:none;">
        <h2 class="section-title">${escapeHtml(mod.name)}</h2>
        <p class="section-subtitle">${escapeHtml(mod.description || 'Spécification détaillée de ce domaine fonctionnel.')}</p>

        <div class="tab-bar" role="tablist" aria-label="Spécifications du module ${escapeHtml(mod.name)}">
            <button class="tab-btn active" role="tab" aria-selected="true" aria-controls="tab-${code}-uc" onclick="switchTab('${code}', 'uc')">Cas d'utilisation</button>
            <button class="tab-btn" role="tab" aria-selected="false" aria-controls="tab-${code}-br" onclick="switchTab('${code}', 'br')">Règles métier</button>
            <button class="tab-btn" role="tab" aria-selected="false" aria-controls="tab-${code}-ent" onclick="switchTab('${code}', 'ent')">Données</button>
            <button class="tab-btn" role="tab" aria-selected="false" aria-controls="tab-${code}-perm" onclick="switchTab('${code}', 'perm')">Droits d'accès</button>
            <button class="tab-btn" role="tab" aria-selected="false" aria-controls="tab-${code}-mock" onclick="switchTab('${code}', 'mock')">Maquettes</button>
            <button class="tab-btn" role="tab" aria-selected="false" aria-controls="tab-${code}-notes" onclick="switchTab('${code}', 'notes')">Notes</button>
            <button class="tab-btn" role="tab" aria-selected="false" aria-controls="tab-${code}-struct" onclick="switchTab('${code}', 'struct')">Structure</button>
        </div>

        <!-- TAB: Cas d'utilisation -->
        <div class="tab-panel active" id="tab-${code}-uc" role="tabpanel" aria-hidden="false">
            <p style="font-size:0.85rem;color:var(--text-muted);margin-bottom:1rem;">Décrivez ce que chaque type d'utilisateur peut faire dans ce domaine. Un cas d'utilisation = une action concrète.</p>
            <div id="ucList-${code}" class="uc-list">
                ${hasHierarchicalSpecs(mod) ? renderSectionGroupedItems(mod, 'useCases', code, renderUseCase) : ''}
                ${spec.useCases.map((uc, i) => renderUseCase(code, uc, i)).join('')}
            </div>
            <button class="add-btn" onclick="toggleForm('addUcForm-${code}')">+ Ajouter un cas d'utilisation</button>
            <div class="inline-form" id="addUcForm-${code}">
                <div class="inline-form-title">Nouveau cas d'utilisation</div>
                <div class="form-group">
                    <label class="form-label">Que fait l'utilisateur ? (exemple : Créer une commande)</label>
                    <input type="text" class="form-input" id="uc-name-${code}" placeholder="Action concrète de l'utilisateur">
                </div>
                <div class="form-group">
                    <label class="form-label">Qui réalise cette action ? (profil utilisateur)</label>
                    <input type="text" class="form-input" id="uc-actor-${code}" placeholder="Exemple : Responsable de production">
                </div>
                <div class="form-group">
                    <label class="form-label">Déroulement normal, étape par étape (une par ligne)</label>
                    <textarea class="form-textarea" id="uc-steps-${code}" placeholder="1. L'utilisateur ouvre la page de création&#10;2. Il remplit les champs obligatoires&#10;3. Il valide le formulaire&#10;4. Le système enregistre et confirme"></textarea>
                </div>
                <div class="form-group">
                    <label class="form-label">Que se passe-t-il si quelque chose ne va pas ? (optionnel)</label>
                    <textarea class="form-textarea" id="uc-alt-${code}" placeholder="Exemple : Si les données sont incorrectes, le système affiche un message d'erreur" style="min-height:50px;"></textarea>
                </div>
                <div class="form-actions">
                    <button class="btn" onclick="toggleForm('addUcForm-${code}')">Annuler</button>
                    <button class="btn btn-primary" onclick="addUseCase('${code}')">Ajouter</button>
                </div>
            </div>
        </div>

        <!-- TAB: Règles métier -->
        <div class="tab-panel" id="tab-${code}-br" role="tabpanel" aria-hidden="true">
            <p style="font-size:0.85rem;color:var(--text-muted);margin-bottom:1rem;">Les règles que le système doit respecter. Formulez-les sous forme de conditions : "Si... alors... sinon..."</p>
            <div id="brList-${code}">
                ${hasHierarchicalSpecs(mod) ? renderSectionGroupedItems(mod, 'businessRules', code, renderBusinessRule) : ''}
                ${spec.businessRules.map((br, i) => renderBusinessRule(code, br, i)).join('')}
            </div>
            <button class="add-btn" onclick="toggleForm('addBrForm-${code}')">+ Ajouter une règle métier</button>
            <div class="inline-form" id="addBrForm-${code}">
                <div class="inline-form-title">Nouvelle règle métier</div>
                <div class="form-group">
                    <label class="form-label">Nom court de la règle</label>
                    <input type="text" class="form-input" id="br-name-${code}" placeholder="Exemple : Vérification du budget disponible">
                </div>
                <div class="form-group">
                    <label class="form-label">Catégorie</label>
                    <select class="form-select" id="br-cat-${code}">
                        <option value="validation">Vérification (le système vérifie que...)</option>
                        <option value="calculation">Calcul (le système calcule...)</option>
                        <option value="workflow">Processus (quand X se produit, alors...)</option>
                        <option value="security">Sécurité (seul... peut...)</option>
                        <option value="data">Données (les données doivent...)</option>
                    </select>
                </div>
                <div class="form-group">
                    <label class="form-label">Formulation de la règle (Si... alors... sinon...)</label>
                    <textarea class="form-textarea" id="br-statement-${code}" placeholder="Si le montant de la commande dépasse le budget du client, alors la commande est refusée et un message d'erreur s'affiche"></textarea>
                </div>
                <div class="form-group">
                    <label class="form-label">Exemple concret (optionnel)</label>
                    <input type="text" class="form-input" id="br-example-${code}" placeholder="Exemple : Commande de 5000 CHF, budget de 2000 CHF -> refusée">
                </div>
                <div class="form-actions">
                    <button class="btn" onclick="toggleForm('addBrForm-${code}')">Annuler</button>
                    <button class="btn btn-primary" onclick="addBusinessRule('${code}')">Ajouter</button>
                </div>
            </div>
        </div>

        <!-- TAB: Données (Entités) -->
        <div class="tab-panel" id="tab-${code}-ent" role="tabpanel" aria-hidden="true">
            <p style="font-size:0.85rem;color:var(--text-muted);margin-bottom:1rem;">Les types de données que ce domaine gère. Décrivez les informations importantes à enregistrer pour chaque type.</p>
            <div id="entList-${code}">
                ${spec.entities.length > 0
                    ? spec.entities.map((ent, i) => renderEntity(code, ent, i)).join('')
                    : (mod.entities || []).length > 0
                        ? '<div class="card" style="color:var(--text-muted);padding:1.5rem;"><p style="margin-bottom:0.75rem;">Les schémas détaillés ne sont pas encore disponibles. Entités identifiées :</p><ul style="list-style:disc;padding-left:1.5rem;">' + mod.entities.map(e => '<li>' + e + '</li>').join('') + '</ul><p style="font-size:0.8rem;margin-top:0.75rem;font-style:italic;">Utilisez le bouton ci-dessous pour ajouter les schémas détaillés.</p></div>'
                        : ''
                }
            </div>
            <button class="add-btn" onclick="toggleForm('addEntForm-${code}')">+ Ajouter un type de données</button>
            <div class="inline-form" id="addEntForm-${code}">
                <div class="inline-form-title">Nouveau type de données</div>
                <div class="form-group">
                    <label class="form-label">Nom (exemple : Commande, Client, Facture)</label>
                    <input type="text" class="form-input" id="ent-name-${code}" placeholder="Nom du type de données">
                </div>
                <div class="form-group">
                    <label class="form-label">Description : à quoi sert cette donnée ?</label>
                    <textarea class="form-textarea" id="ent-desc-${code}" placeholder="En une ou deux phrases, décrivez ce que représente cette donnée dans votre activité" style="min-height:50px;"></textarea>
                </div>
                <div class="form-group">
                    <label class="form-label">Informations à enregistrer (une par ligne : Nom - Description)</label>
                    <textarea class="form-textarea" id="ent-attrs-${code}" placeholder="Numero - Identifiant unique de la commande&#10;Date - Date de création de la commande&#10;Montant total - Somme des lignes&#10;Statut - Brouillon, Envoyée, Validée, Refusée"></textarea>
                </div>
                <div class="form-group">
                    <label class="form-label">Relations avec d'autres données (optionnel, une par ligne)</label>
                    <textarea class="form-textarea" id="ent-rels-${code}" placeholder="Client - Chaque commande appartient a un client&#10;Ligne de commande - Une commande contient plusieurs lignes" style="min-height:50px;"></textarea>
                </div>
                <div class="form-actions">
                    <button class="btn" onclick="toggleForm('addEntForm-${code}')">Annuler</button>
                    <button class="btn btn-primary" onclick="addEntity('${code}')">Ajouter</button>
                </div>
            </div>
        </div>

        <!-- TAB: Droits d'accès -->
        <div class="tab-panel" id="tab-${code}-perm" role="tabpanel" aria-hidden="true">
            <p style="font-size:0.85rem;color:var(--text-muted);margin-bottom:1rem;">Définissez qui peut faire quoi dans ce domaine. Cochez les actions autorisées pour chaque profil.</p>
            <div id="permGrid-${code}">
                ${renderPermissionGrid(code)}
            </div>
            <div style="display:flex;gap:0.75rem;margin-top:1rem;flex-wrap:wrap;">
                <button class="add-btn" onclick="toggleForm('addRoleForm-${code}')" style="flex:1;min-width:200px;">+ Ajouter un rôle</button>
                <button class="add-btn" onclick="toggleForm('addActionForm-${code}')" style="flex:1;min-width:200px;">+ Ajouter une action</button>
            </div>
            <div class="inline-form" id="addRoleForm-${code}">
                <div class="inline-form-title">Nouveau rôle</div>
                <div class="form-group">
                    <label class="form-label">Nom du rôle</label>
                    <input type="text" class="form-input" id="role-name-${code}" placeholder="Exemple : Superviseur, Auditeur...">
                </div>
                <div class="form-actions">
                    <button class="btn" onclick="toggleForm('addRoleForm-${code}')">Annuler</button>
                    <button class="btn btn-primary" onclick="addCustomRole('${code}')">Ajouter</button>
                </div>
            </div>
            <div class="inline-form" id="addActionForm-${code}">
                <div class="inline-form-title">Nouvelle action</div>
                <div class="form-group">
                    <label class="form-label">Nom de l'action</label>
                    <input type="text" class="form-input" id="action-name-${code}" placeholder="Exemple : Archiver, Imprimer, Approuver...">
                </div>
                <div class="form-actions">
                    <button class="btn" onclick="toggleForm('addActionForm-${code}')">Annuler</button>
                    <button class="btn btn-primary" onclick="addCustomAction('${code}')">Ajouter</button>
                </div>
            </div>
        </div>

        <!-- TAB: Maquettes -->
        <div class="tab-panel" id="tab-${code}-mock" role="tabpanel" aria-hidden="true">
            <p style="font-size:0.85rem;color:var(--text-muted);margin-bottom:1rem;">Maquettes validées lors de l'analyse. Ces wireframes montrent la structure exacte des écrans de ce domaine.</p>
            <div id="mockupContainer-${code}">
                ${renderModuleMockups(code)}
            </div>
        </div>

        <!-- TAB: Notes -->
        <div class="tab-panel" id="tab-${code}-notes" role="tabpanel" aria-hidden="true">
            <p style="font-size:0.85rem;color:var(--text-muted);margin-bottom:1rem;">Notes libres, questions en suspens, éléments à clarifier pour ce domaine.</p>
            <div class="card">
                <div class="editable" contenteditable="true" data-module-code="${code}" data-module-field="notes" data-placeholder="Notez ici tout ce qui concerne ce domaine : questions, précisions, contraintes particulières...">${spec.notes || ''}</div>
            </div>
        </div>

        <!-- TAB: Structure (sections/resources) -->
        <div class="tab-panel" id="tab-${code}-struct" role="tabpanel" aria-hidden="true">
            <p style="font-size:0.85rem;color:var(--text-muted);margin-bottom:1rem;">Organisation des écrans et ressources de ce domaine. Structure hiérarchique : sections regroupant des ressources.</p>
            <div id="structContainer-${code}">
                ${renderModuleStructure(code)}
            </div>
        </div>
    </div>`;
}

function renderUseCase(code, uc, index) {
    var preconditions = uc.preconditions || [];
    var postconditions = uc.postconditions || [];
    var errorScenarios = uc.errorScenarios || [];
    var description = uc.description || '';

    return `
        <div class="uc-item">
            <div class="uc-header">
                <span class="uc-id">UC-${String(index + 1).padStart(3, '0')}</span>
                <span class="uc-title">${escapeHtml(uc.name)}</span>
                <div class="uc-actions">
                    <button class="btn btn-sm" onclick="removeUseCase('${code}',${index})">Supprimer</button>
                </div>
            </div>
            <div class="uc-actors"><div class="uc-actor">${escapeHtml(uc.actor)}</div></div>
            ${description ? `<div class="uc-detail-label">Description</div><div class="uc-detail" style="font-style:italic;color:var(--text-muted);">${escapeHtml(description)}</div>` : ''}
            ${preconditions.length > 0 ? `<div class="uc-detail-label">Préconditions</div><div class="uc-detail"><ul style="margin:0;padding-left:1.2rem;">${preconditions.map(p => '<li>' + escapeHtml(typeof p === 'string' ? p : p.description || '') + '</li>').join('')}</ul></div>` : ''}
            ${uc.steps ? `<div class="uc-detail-label">Déroulement principal</div><div class="uc-detail">${escapeHtml(uc.steps).replace(/\n/g, '<br>')}</div>` : ''}
            ${uc.alternative ? `<div class="uc-detail-label">Scénarios alternatifs</div><div class="uc-detail" style="color:var(--warning);">${escapeHtml(uc.alternative)}</div>` : ''}
            ${errorScenarios.length > 0 ? `<div class="uc-detail-label">Scénarios d'erreur</div><div class="uc-detail" style="color:var(--danger);"><ul style="margin:0;padding-left:1.2rem;">${errorScenarios.map(e => '<li><strong>' + escapeHtml(typeof e === 'string' ? e : e.name || '') + '</strong>' + (typeof e === 'object' && e.steps ? ' : ' + escapeHtml(Array.isArray(e.steps) ? e.steps.join(', ') : e.steps) : '') + '</li>').join('')}</ul></div>` : ''}
            ${postconditions.length > 0 ? `<div class="uc-detail-label">Postconditions</div><div class="uc-detail"><ul style="margin:0;padding-left:1.2rem;">${postconditions.map(p => '<li>' + escapeHtml(typeof p === 'string' ? p : p.description || '') + '</li>').join('')}</ul></div>` : ''}
            <div style="padding:0.5rem 0.75rem;border-top:1px solid var(--border);background:var(--bg-input);border-radius:0 0 8px 8px;">
                <label style="font-size:0.75rem;color:var(--text-muted);display:block;margin-bottom:0.25rem;">Commentaire / Feedback :</label>
                <textarea class="form-textarea" placeholder="Ajouter un commentaire sur ce cas d'utilisation..."
                    onblur="updateSpecComment('${code}','uc',${index},this.value)"
                    style="min-height:45px;font-size:0.8rem;resize:vertical;">${escapeHtml(getSpecComment(code, 'uc', index))}</textarea>
            </div>
        </div>`;
}

function addUseCase(code) {
    const name = document.getElementById('uc-name-' + code).value.trim();
    if (!name) return;
    if (!data.moduleSpecs[code]) data.moduleSpecs[code] = { useCases: [], businessRules: [], entities: [], permissions: [], notes: '' };

    data.moduleSpecs[code].useCases.push({
        name: name,
        actor: document.getElementById('uc-actor-' + code).value.trim(),
        steps: document.getElementById('uc-steps-' + code).value.trim(),
        alternative: document.getElementById('uc-alt-' + code).value.trim()
    });

    renderAllModuleSpecs();
    updateCounts();
    autoSave();
}

function removeUseCase(code, index) {
    if (!confirm('Supprimer ce cas d\'utilisation ?')) return;
    data.moduleSpecs[code].useCases.splice(index, 1);
    renderAllModuleSpecs();
    updateCounts();
    autoSave();
}

function renderBusinessRule(code, br, index) {
    const catColors = { validation: 'br-cat-validation', calculation: 'br-cat-calculation', workflow: 'br-cat-workflow', security: 'br-cat-security', data: 'br-cat-data' };
    const catLabels = { validation: 'Vérification', calculation: 'Calcul', workflow: 'Processus', security: 'Sécurité', data: 'Données' };
    return `
        <div style="margin-bottom:0.5rem;">
            <div class="br-item" style="margin-bottom:0;border-radius:8px 8px 0 0;">
                <span class="br-category ${catColors[br.category] || 'br-cat-validation'}">${escapeHtml(catLabels[br.category] || br.category)}</span>
                <div class="br-text" style="flex:1;">
                    <div style="font-weight:600;color:var(--text-bright);margin-bottom:0.2rem;">${escapeHtml(br.name)}</div>
                    <div>${escapeHtml(br.statement)}</div>
                    ${br.example ? `<div style="font-size:0.8rem;color:var(--text-muted);margin-top:0.25rem;font-style:italic;">Exemple : ${escapeHtml(br.example)}</div>` : ''}
                </div>
                <button class="btn btn-sm" onclick="removeBusinessRule('${code}',${index})" style="opacity:0.5;flex-shrink:0;">&#10005;</button>
            </div>
            <div style="padding:0.4rem 0.75rem 0.6rem;background:var(--bg-input);border:1px solid var(--border);border-top:0;border-radius:0 0 8px 8px;">
                <textarea class="form-textarea" placeholder="Commentaire sur cette règle..."
                    onblur="updateSpecComment('${code}','br',${index},this.value)"
                    style="min-height:35px;font-size:0.8rem;resize:vertical;">${escapeHtml(getSpecComment(code, 'br', index))}</textarea>
            </div>
        </div>`;
}

function addBusinessRule(code) {
    const name = document.getElementById('br-name-' + code).value.trim();
    if (!name) return;
    if (!data.moduleSpecs[code]) data.moduleSpecs[code] = { useCases: [], businessRules: [], entities: [], permissions: [], notes: '' };

    data.moduleSpecs[code].businessRules.push({
        name: name,
        category: document.getElementById('br-cat-' + code).value,
        statement: document.getElementById('br-statement-' + code).value.trim(),
        example: document.getElementById('br-example-' + code).value.trim()
    });

    renderAllModuleSpecs();
    autoSave();
}

function removeBusinessRule(code, index) {
    if (!confirm('Supprimer cette règle métier ?')) return;
    data.moduleSpecs[code].businessRules.splice(index, 1);
    renderAllModuleSpecs();
    autoSave();
}

function renderEntity(code, ent, index) {
    var attrFormId = 'addAttrForm-' + code + '-' + index;
    return `
        <div class="entity-block">
            <div class="entity-header">
                <div>
                    <div class="entity-name">${escapeHtml(ent.name)}</div>
                    <div class="entity-desc">${escapeHtml(ent.description || '')}</div>
                </div>
                <button class="btn btn-sm" onclick="removeEntity('${code}',${index})" style="opacity:0.5;">Supprimer</button>
            </div>
            ${(ent.attributes || []).length > 0 ? `
            <table class="attr-table">
                <thead><tr><th>Information</th><th style="width:100px;">Type</th><th>Description</th></tr></thead>
                <tbody>
                    ${ent.attributes.map(a => `<tr><td style="font-weight:500;color:var(--text-bright);">${escapeHtml(a.name)}</td><td style="font-family:monospace;font-size:0.8rem;color:var(--accent);">${escapeHtml(a.type || 'string')}</td><td>${escapeHtml(a.description || '')}</td></tr>`).join('')}
                </tbody>
            </table>` : ''}
            <div style="padding:0.3rem 0.75rem;">
                <button class="add-btn" style="font-size:0.75rem;padding:0.4rem;" onclick="toggleForm('${attrFormId}')">+ Ajouter un attribut</button>
                <div class="inline-form" id="${attrFormId}">
                    <div class="form-group"><label class="form-label">Nom de l'attribut</label><input type="text" class="form-input" id="attr-name-${code}-${index}" placeholder="Nom de l'attribut"></div>
                    <div class="form-group"><label class="form-label">Type</label><input type="text" class="form-input" id="attr-type-${code}-${index}" placeholder="string, guid, int, decimal, date, enum, boolean" value="string"></div>
                    <div class="form-group"><label class="form-label">Description (optionnel)</label><input type="text" class="form-input" id="attr-desc-${code}-${index}" placeholder="Description"></div>
                    <div class="form-actions"><button class="btn" onclick="toggleForm('${attrFormId}')">Annuler</button><button class="btn btn-primary" onclick="addEntityAttribute('${code}',${index})">Ajouter</button></div>
                </div>
            </div>
            ${(ent.relationships || []).length > 0 ? `
            <div style="padding:0.5rem 0.75rem;font-size:0.8rem;color:var(--text-muted);border-top:1px solid var(--border);">
                Relations : ${ent.relationships.map(r => `<span style="color:var(--accent);">${escapeHtml(typeof r === 'string' ? r : (r.target || ''))}</span>`).join(', ')}
            </div>` : ''}
            <div style="padding:0.4rem 0.75rem 0.6rem;background:var(--bg-input);border-top:1px solid var(--border);border-radius:0 0 8px 8px;">
                <label style="font-size:0.75rem;color:var(--text-muted);display:block;margin-bottom:0.25rem;">Commentaire :</label>
                <textarea class="form-textarea" placeholder="Commentaire sur cette entité..."
                    onblur="updateSpecComment('${code}','ent',${index},this.value)"
                    style="min-height:35px;font-size:0.8rem;resize:vertical;">${escapeHtml(getSpecComment(code, 'ent', index))}</textarea>
            </div>
        </div>`;
}

function addEntity(code) {
    const name = document.getElementById('ent-name-' + code).value.trim();
    if (!name) return;
    if (!data.moduleSpecs[code]) data.moduleSpecs[code] = { useCases: [], businessRules: [], entities: [], permissions: [], notes: '' };

    const attrs = document.getElementById('ent-attrs-' + code).value.split('\n').filter(l => l.trim()).map(l => {
        const parts = l.split(' - ');
        return { name: parts[0]?.trim() || l.trim(), type: parts[1]?.trim() || 'string', description: parts.slice(2).join(' - ').trim() || parts.slice(1).join(' - ').trim() };
    });
    const rels = document.getElementById('ent-rels-' + code).value.split('\n').filter(l => l.trim());

    data.moduleSpecs[code].entities.push({
        name: name,
        description: document.getElementById('ent-desc-' + code).value.trim(),
        attributes: attrs,
        relationships: rels
    });

    renderAllModuleSpecs();
    autoSave();
}

function removeEntity(code, index) {
    if (!confirm('Supprimer ce type de données ?')) return;
    data.moduleSpecs[code].entities.splice(index, 1);
    renderAllModuleSpecs();
    autoSave();
}

function addEntityAttribute(code, entityIndex) {
    var attrName = document.getElementById('attr-name-' + code + '-' + entityIndex);
    var attrType = document.getElementById('attr-type-' + code + '-' + entityIndex);
    var attrDesc = document.getElementById('attr-desc-' + code + '-' + entityIndex);
    if (!attrName || !attrName.value.trim()) return;
    if (!data.moduleSpecs[code]?.entities?.[entityIndex]) return;
    if (!data.moduleSpecs[code].entities[entityIndex].attributes) {
        data.moduleSpecs[code].entities[entityIndex].attributes = [];
    }
    data.moduleSpecs[code].entities[entityIndex].attributes.push({ name: attrName.value.trim(), type: (attrType?.value || 'string').trim(), description: (attrDesc?.value || '').trim() });
    renderAllModuleSpecs();
    autoSave();
}

function getSpecComment(code, type, index) {
    const key = code + '.' + type + '.' + index;
    return data.specComments[key] || '';
}

function updateSpecComment(code, type, index, value) {
    const key = code + '.' + type + '.' + index;
    data.specComments[key] = value.trim();
    autoSave();
}

function getWireframeComment(code, screen) {
    return (data.wireframeComments[code] || {})[screen] || '';
}

function updateWireframeComment(code, screen, value) {
    if (!data.wireframeComments[code]) data.wireframeComments[code] = {};
    data.wireframeComments[code][screen] = value.trim();
    autoSave();
}

function renderWireframeMockup(code, wf, i) {
    const hasSvg = !!wf.svgContent;
    const wireframeId = `wf-${code}-${i}`;

    return `
    <div class="mockup-frame" style="${i > 0 ? 'margin-top:1.5rem;' : ''}">
        <div class="mockup-toolbar">
            <div class="mockup-dot mockup-dot-red"></div>
            <div class="mockup-dot mockup-dot-yellow"></div>
            <div class="mockup-dot mockup-dot-green"></div>
            <span class="mockup-title">${escapeHtml(wf.screen || wf.section)}</span>
            ${hasSvg ? `
            <div class="wireframe-toggle">
                <button class="wireframe-toggle-btn active" data-target="${wireframeId}" data-view="svg" onclick="toggleWireframeView('${wireframeId}', 'svg')">SVG</button>
                <button class="wireframe-toggle-btn" data-target="${wireframeId}" data-view="ascii" onclick="toggleWireframeView('${wireframeId}', 'ascii')">ASCII</button>
            </div>` : ''}
        </div>
        <div class="mockup-content" id="${wireframeId}">
            ${hasSvg
                ? `<div class="svg-wireframe wireframe-view active" data-view="svg">${wf.svgContent}</div>
                   <pre class="ascii-wireframe wireframe-view" data-view="ascii" style="display:none;">${wf.content || ''}</pre>`
                : (wf.format === 'ascii'
                    ? `<pre class="ascii-wireframe">${wf.content || ''}</pre>`
                    : `<div class="svg-wireframe">${wf.content || ''}</div>`)}
        </div>
        ${wf.description ? `
        <div class="wireframe-description">
            <strong>Description:</strong> ${escapeHtml(wf.description)}
        </div>` : ''}
        ${(wf.elements || []).length > 0 ? `
        <div class="wireframe-metadata">
            <div><strong>Elements:</strong> ${wf.elements.map(e => escapeHtml(typeof e === 'string' ? e : (e.type || e.label || e.id || ''))).filter(Boolean).join(', ')}</div>
        </div>` : ''}
        ${(() => {
            const cm = wf.componentMapping;
            const mappings = Array.isArray(cm) ? cm
                : (typeof cm === 'object' && cm !== null) ? Object.entries(cm).map(([k,v]) => ({wireframeElement: k, reactComponent: v}))
                : [];
            return mappings.length > 0 ? `
        <details class="wireframe-details">
            <summary>Mapping composants SmartStack</summary>
            <table class="mapping-table">
                <thead><tr><th>Élément maquette</th><th>Composant React</th></tr></thead>
                <tbody>
                    ${mappings.map(m =>
                        '<tr><td>' + escapeHtml(m.wireframeElement || '') + '</td><td><code>' + escapeHtml(m.reactComponent || '') + '</code></td></tr>'
                    ).join('')}
                </tbody>
            </table>
        </details>` : '';
        })()}
        <div class="wireframe-comment">
            <label style="font-size:0.8rem;color:var(--text-muted);display:block;margin-bottom:0.3rem;">Commentaire / Feedback :</label>
            <textarea class="form-textarea"
                data-module="${code}"
                data-screen="${wf.screen}"
                placeholder="Ajouter un commentaire sur cette maquette (ex: déplacer ce bouton, ajouter une colonne...)"
                onblur="updateWireframeComment('${code}', '${wf.screen}', this.value)"
                style="min-height:60px;font-size:0.85rem;resize:vertical;"
            >${getWireframeComment(code, wf.screen)}</textarea>
        </div>
    </div>
    `;
}

function toggleWireframeView(wireframeId, view) {
    const container = document.getElementById(wireframeId);
    if (!container) return;

    // Toggle visibility of wireframe views
    container.querySelectorAll('.wireframe-view').forEach(el => {
        const isTarget = el.dataset.view === view;
        el.style.display = isTarget ? '' : 'none';
        el.classList.toggle('active', isTarget);
    });

    // Toggle button active states
    const toolbar = container.closest('.mockup-frame').querySelector('.wireframe-toggle');
    if (toolbar) {
        toolbar.querySelectorAll('.wireframe-toggle-btn').forEach(btn => {
            btn.classList.toggle('active', btn.dataset.view === view);
        });
    }
}

// Normalize permissions array: handles 3 formats:
// Format 1 (string): "Role|Action" → already correct
// Format 2 (object): {role, permissions: ["Read:all", "Create:all", ...]}
// Format 3 (object): {role, permissions: ["Module.Entity.Read", ...]}
function normalizePermissions(permsArray) {
    if (!permsArray || permsArray.length === 0) return [];
    // If first element is a string with '|', already normalized
    if (typeof permsArray[0] === 'string' && permsArray[0].includes('|')) return permsArray;
    // If first element is a string without '|', return as-is (unknown format)
    if (typeof permsArray[0] === 'string') return permsArray;
    // Format 2/3: objects with {role, permissions[]}
    const actionMap = {
        'read': 'Consulter', 'create': 'Créer', 'update': 'Modifier',
        'delete': 'Supprimer', 'approve': 'Valider', 'validate': 'Valider',
        'export': 'Exporter', 'admin': 'Administrer', 'import': 'Importer',
        'viewsalary': 'Consulter', 'assignteam': 'Modifier', 'cancel': 'Supprimer'
    };
    const normalized = [];
    permsArray.forEach(function(entry) {
        if (typeof entry !== 'object' || !entry) return;
        var role = entry.role || entry.name || '';
        if (!role) return;
        var perms = entry.permissions || entry.actions || [];
        if (perms.length === 0 && entry.permissionPattern && entry.permissionPattern.endsWith('*')) {
            // Wildcard: expand to all standard actions
            ['Consulter', 'Créer', 'Modifier', 'Supprimer', 'Valider', 'Exporter'].forEach(function(a) {
                normalized.push(role + '|' + a);
            });
            return;
        }
        perms.forEach(function(perm) {
            var action = '';
            if (typeof perm === 'string') {
                // "Read:all" → extract "Read"
                var raw = perm.split(':')[0];
                // "Module.Entity.Read" → extract "Read"
                if (raw.includes('.')) raw = raw.split('.').pop();
                action = actionMap[raw.toLowerCase()] || raw;
            }
            if (action) {
                var key = role + '|' + action;
                if (normalized.indexOf(key) === -1) normalized.push(key);
            }
        });
    });
    return normalized;
}

function getPermRoles() {
    // Extract roles from actual permission data (handles multiple formats)
    const rolesFromPerms = [];
    const seen = new Set();
    data.modules.forEach(m => {
        var perms = data.moduleSpecs[m.code]?.permissions || [];
        // Handle object format directly for role extraction
        perms.forEach(p => {
            var role = '';
            if (typeof p === 'string') {
                role = p.split('|')[0];
            } else if (typeof p === 'object' && p) {
                role = p.role || p.name || '';
            }
            if (role && !seen.has(role)) { seen.add(role); rolesFromPerms.push(role); }
        });
    });
    if (rolesFromPerms.length > 0) return [...rolesFromPerms, ...(data.customRoles || [])];
    // Fallback: use stakeholder names if no permission data exists
    const baseRoles = data.cadrage.stakeholders.length > 0
        ? data.cadrage.stakeholders.map(s => s.role)
        : ['Administrateur', 'Responsable', 'Contributeur', 'Lecteur'];
    return [...baseRoles, ...(data.customRoles || [])];
}

function getPermActions() {
    const baseActions = ['Consulter', 'Créer', 'Modifier', 'Supprimer', 'Valider', 'Exporter'];
    return [...baseActions, ...(data.customActions || [])];
}

function renderPermissionGrid(code) {
    const roles = getPermRoles();
    const actions = getPermActions();
    const baseRolesCount = roles.length - (data.customRoles || []).length;
    const baseActionsCount = 6;

    // Normalize permissions to "Role|Action" format (handles object and string formats)
    const rawPerms = data.moduleSpecs[code]?.permissions || [];
    const perms = normalizePermissions(rawPerms);

    return `
        <table class="mock-table" style="background:var(--bg-card);border-radius:8px;overflow:hidden;">
            <thead><tr>
                <th>Profil</th>
                ${actions.map((a, i) => `<th style="text-align:center;">${escapeHtml(a)}${i >= baseActionsCount ? ' <span onclick="removeCustomAction('+`'${code}','${a}'`+')" style="cursor:pointer;color:var(--danger);font-size:0.7rem;" title="Supprimer cette action">&#10005;</span>' : ''}</th>`).join('')}
            </tr></thead>
            <tbody>
                ${roles.map((role, ri) => `
                    <tr>
                        <td style="font-weight:500;color:var(--text-bright);">${escapeHtml(role)}${ri >= baseRolesCount ? ' <span onclick="removeCustomRole('+`'${code}','${role}'`+')" style="cursor:pointer;color:var(--danger);font-size:0.7rem;" title="Supprimer ce rôle">&#10005;</span>' : ''}</td>
                        ${actions.map(action => {
                            const key = role + '|' + action;
                            const wildcardKey = role + '|*';
                            const checked = perms.includes(key) || perms.includes(wildcardKey);
                            return `<td style="text-align:center;"><input type="checkbox" ${checked ? 'checked' : ''} onchange="togglePermission('${code}','${key}',this.checked)" style="cursor:pointer;width:16px;height:16px;"></td>`;
                        }).join('')}
                    </tr>
                `).join('')}
            </tbody>
        </table>`;
}

function togglePermission(code, key, checked) {
    if (!data.moduleSpecs[code]) data.moduleSpecs[code] = { useCases: [], businessRules: [], entities: [], permissions: [], notes: '' };
    if (!data.moduleSpecs[code].permissions) data.moduleSpecs[code].permissions = [];
    if (checked) {
        if (!data.moduleSpecs[code].permissions.includes(key)) data.moduleSpecs[code].permissions.push(key);
    } else {
        data.moduleSpecs[code].permissions = data.moduleSpecs[code].permissions.filter(p => p !== key);
    }
    autoSave();
}

function addCustomRole(code) {
    const input = document.getElementById('role-name-' + code);
    const name = input.value.trim();
    if (!name) return;
    if (!data.customRoles) data.customRoles = [];
    if (!data.customRoles.includes(name) && !getPermRoles().includes(name)) {
        data.customRoles.push(name);
    }
    input.value = '';
    toggleForm('addRoleForm-' + code);
    refreshAllPermGrids();
    autoSave();
}

function addCustomAction(code) {
    const input = document.getElementById('action-name-' + code);
    const name = input.value.trim();
    if (!name) return;
    if (!data.customActions) data.customActions = [];
    if (!data.customActions.includes(name) && !getPermActions().includes(name)) {
        data.customActions.push(name);
    }
    input.value = '';
    toggleForm('addActionForm-' + code);
    refreshAllPermGrids();
    autoSave();
}

function removeCustomRole(code, role) {
    data.customRoles = (data.customRoles || []).filter(r => r !== role);
    data.modules.forEach(m => {
        if (data.moduleSpecs[m.code]?.permissions) {
            data.moduleSpecs[m.code].permissions = data.moduleSpecs[m.code].permissions.filter(p => !p.startsWith(role + '|'));
        }
    });
    refreshAllPermGrids();
    autoSave();
}

function removeCustomAction(code, action) {
    data.customActions = (data.customActions || []).filter(a => a !== action);
    data.modules.forEach(m => {
        if (data.moduleSpecs[m.code]?.permissions) {
            data.moduleSpecs[m.code].permissions = data.moduleSpecs[m.code].permissions.filter(p => !p.endsWith('|' + action));
        }
    });
    refreshAllPermGrids();
    autoSave();
}

function refreshAllPermGrids() {
    data.modules.forEach(m => {
        const container = document.getElementById('permGrid-' + m.code);
        if (container) container.innerHTML = renderPermissionGrid(m.code);
    });
}

function renderModuleStructure(code) {
    const mod = data.modules.find(m => m.code === code);
    const sections = mod ? (mod.anticipatedSections || []).map(function(s) {
        return typeof s === 'string' ? { code: s, name: s, description: '', resources: [] } : s;
    }) : [];

    if (sections.length === 0) {
        return '<div class="card" style="text-align:center;padding:2rem;color:var(--text-muted);">' +
            '<p>Aucune section définie pour ce module.</p>' +
            '<p style="font-size:0.85rem;margin-top:0.5rem;">Les sections et ressources seront identifiées lors de l\'analyse approfondie.</p>' +
            '</div>';
    }

    var legend = '<div class="struct-legend">' +
        '<div class="struct-legend-title">&#9432; Types de sections</div>' +
        '<div class="struct-legend-grid">' +
        '<div class="struct-legend-item"><span class="struct-legend-code">list</span> Page principale — grille de données avec filtres, tri et actions (créer, exporter)</div>' +
        '<div class="struct-legend-item"><span class="struct-legend-code">detail</span> Fiche détaillée — affichée au clic sur une ligne, avec onglets (infos, relations, historique)</div>' +
        '<div class="struct-legend-item"><span class="struct-legend-code">dashboard</span> Tableau de bord — KPIs, graphiques et métriques du module</div>' +
        '<div class="struct-legend-item"><span class="struct-legend-code">approve</span> Workflow — file de validation avec actions (approuver, rejeter, mettre en attente)</div>' +
        '</div></div>';

    return legend + sections.map(function(section) {
        var resources = section.resources || [];
        var sectionUCs = section.useCases || [];
        var sectionBRs = section.businessRules || [];
        var html = '<div class="struct-section">';
        html += '<div class="struct-section-header">';
        html += '<span class="struct-section-code">' + escapeHtml(section.code || section.name || '') + '</span>';
        if (section.description) {
            html += '<span class="struct-section-desc">' + escapeHtml(section.description) + '</span>';
        }
        html += '<span class="struct-section-badge">' + resources.length + ' ressource' + (resources.length !== 1 ? 's' : '') + '</span>';
        html += '</div>';

        // Section metadata (route, permission)
        if (section.route || section.permission) {
            html += '<div style="padding:0.4rem 1rem;font-size:0.75rem;color:var(--text-muted);display:flex;gap:1rem;border-bottom:1px solid var(--border);">';
            if (section.route) html += '<span>Route: <code style="color:var(--accent);background:var(--bg-input);padding:0.1rem 0.3rem;border-radius:3px;">' + escapeHtml(section.route) + '</code></span>';
            if (section.permission) html += '<span>Permission: <code style="color:var(--accent);background:var(--bg-input);padding:0.1rem 0.3rem;border-radius:3px;">' + escapeHtml(section.permission) + '</code></span>';
            html += '</div>';
        }

        // Section-level UC summary
        if (sectionUCs.length > 0) {
            html += '<div style="padding:0.4rem 1rem;font-size:0.8rem;border-bottom:1px solid var(--border);">';
            html += '<span style="color:var(--text-muted);font-weight:500;">' + sectionUCs.length + ' cas d\'utilisation :</span> ';
            html += sectionUCs.map(function(uc) { return '<span style="color:var(--text-bright);">' + escapeHtml(uc.name || '') + '</span>'; }).join(', ');
            html += '</div>';
        }

        // Section-level BR summary
        if (sectionBRs.length > 0) {
            html += '<div style="padding:0.4rem 1rem;font-size:0.8rem;border-bottom:1px solid var(--border);">';
            html += '<span style="color:var(--text-muted);font-weight:500;">' + sectionBRs.length + ' règle' + (sectionBRs.length > 1 ? 's' : '') + ' métier :</span> ';
            html += sectionBRs.map(function(br) { return '<span style="color:var(--text-bright);">' + escapeHtml(br.name || '') + '</span>'; }).join(', ');
            html += '</div>';
        }

        if (resources.length > 0) {
            html += '<div class="struct-resources">';
            resources.forEach(function(res) {
                var resName = typeof res === 'string' ? res : (res.code || res.name || '');
                var resType = typeof res === 'object' ? (res.type || '') : '';
                var resDesc = typeof res === 'object' ? (res.description || '') : '';
                html += '<div class="struct-resource">';
                html += '<span class="struct-resource-icon">&#8226;</span>';
                html += '<span class="struct-resource-name">' + escapeHtml(resName) + '</span>';
                if (resType) html += '<span style="font-size:0.7rem;color:var(--accent);background:rgba(6,182,212,0.1);padding:0.1rem 0.3rem;border-radius:3px;">' + escapeHtml(resType) + '</span>';
                if (resDesc) html += '<span class="struct-resource-desc">' + escapeHtml(resDesc) + '</span>';
                html += '</div>';
            });
            html += '</div>';
        }

        html += '</div>';
        return html;
    }).join('');
}

/* ---------- Section-Grouped Rendering (Hierarchical Mode) ---------- */

function renderSectionGroupedItems(mod, itemsKey, code, renderFn) {
    var sections = (mod.anticipatedSections || []).map(function(s) {
        return typeof s === 'string' ? { code: s, name: s, resources: [] } : s;
    });
    var html = '';
    sections.forEach(function(section) {
        var items = section[itemsKey] || [];
        if (items.length === 0) return;
        html += '<div class="section-group">';
        html += '<div class="section-group-header">';
        html += '<span class="section-group-icon">&#9655;</span> ';
        html += '<span class="section-group-label">' + escapeHtml(section.code || section.name || '') + '</span>';
        if (section.route) html += '<span class="section-group-route">' + escapeHtml(section.route) + '</span>';
        html += '<span class="nav-badge">' + items.length + '</span>';
        html += '</div>';
        html += items.map(function(item, i) { return renderFn(code, item, i); }).join('');
        html += '</div>';
    });
    return html;
}

function renderModuleMockups(code) {
    var spec = data.moduleSpecs[code] || {};
    var screens = spec.screens || [];
    var wireframes = EMBEDDED_ARTIFACTS?.wireframes?.[code] || [];
    var mod = data.modules.find(function(m) { return m.code === code; });
    var sections = mod ? (mod.anticipatedSections || []).map(function(s) {
        return typeof s === 'string' ? { code: s, name: s, resources: [] } : s;
    }) : [];

    // Priority 1: HTML mockups from screens[] specs (wireframes NOT shown when screens exist)
    var hasResources = screens.some(function(s) { return (s.resources || []).length > 0; });
    if (screens.length > 0 && hasResources) {
        var html = '';
        if (typeof renderScreenMockups === 'function') {
            html = renderScreenMockups(code);
        }
        return html;
    }

    // Priority 2: Wireframes grouped by section (if sections exist)
    if (wireframes.length > 0 && sections.length > 1) {
        var grouped = {};
        var ungrouped = [];
        wireframes.forEach(function(wf, i) {
            var sectionCode = wf.section || wf.sectionCode || '';
            var matchingSection = sections.find(function(s) { return s.code === sectionCode; });
            if (matchingSection) {
                if (!grouped[sectionCode]) grouped[sectionCode] = { section: matchingSection, items: [] };
                grouped[sectionCode].items.push({ wf: wf, index: i });
            } else {
                ungrouped.push({ wf: wf, index: i });
            }
        });

        var html = '';
        Object.keys(grouped).forEach(function(sectionCode) {
            var group = grouped[sectionCode];
            html += '<div class="section-group">';
            html += '<div class="section-group-header">';
            html += '<span class="section-group-icon">&#9655;</span> ';
            html += '<span class="section-group-label">' + escapeHtml(group.section.code || '') + '</span>';
            html += '<span class="nav-badge">' + group.items.length + '</span>';
            html += '</div>';
            group.items.forEach(function(item) {
                html += renderWireframeMockup(code, item.wf, item.index);
            });
            html += '</div>';
        });
        ungrouped.forEach(function(item) {
            html += renderWireframeMockup(code, item.wf, item.index);
        });
        return html;
    }

    // Priority 3: Flat wireframe list
    if (wireframes.length === 0) {
        return '<div class="card" style="text-align:center;padding:2rem;color:var(--text-muted);"><p>Aucune maquette disponible pour ce module.</p><p style="font-size:0.85rem;margin-top:0.5rem;">Les maquettes seront générées lors de la spécification détaillée.</p></div>';
    }
    return wireframes.map(function(wf, i) { return renderWireframeMockup(code, wf, i); }).join('');
}

function switchTab(code, tabId) {
    const section = document.getElementById('module-spec-' + code);
    if (!section) return;
    section.querySelectorAll('.tab-btn').forEach(function(btn) {
        btn.classList.remove('active');
        btn.setAttribute('aria-selected', 'false');
    });
    section.querySelectorAll('.tab-panel').forEach(function(panel) {
        panel.classList.remove('active');
        panel.setAttribute('aria-hidden', 'true');
    });
    const targetPanel = document.getElementById('tab-' + code + '-' + tabId);
    if (targetPanel) {
        targetPanel.classList.add('active');
        targetPanel.setAttribute('aria-hidden', 'false');
    }
    const buttons = section.querySelectorAll('.tab-btn');
    const tabIndex = { uc: 0, br: 1, ent: 2, perm: 3, mock: 4, notes: 5, struct: 6 }[tabId];
    if (buttons[tabIndex]) {
        buttons[tabIndex].classList.add('active');
        buttons[tabIndex].setAttribute('aria-selected', 'true');
    }
}
