/**
 * Fichier  : assets/js/pages/admin-mobile.js
 * Auteur   : KREMER Régis
 * Version  : 2.6.119
 * Date     : 2026-07-21
 * Description : Administration mobile/tablette — Utilisateurs, Fournisseurs et Paramètres.
 *
 * Changelog :
 *   v2.6.84 (2026-07-20) — ADMIN COMPLEX FORMS8 : cartes métier, assistants,
 *                          pages à sections, confirmations renforcées et hub Paramètres.
 *   v2.6.102 (2026-07-21) — Comptes LDAP en lecture administrée et accès au réglage LDAP depuis le hub mobile.
 *   v2.6.119 (2026-07-25) — Jeton de récupération pour comptes locaux et politique de mot de passe alignée.
 */
(function adminComplexMobile(global, document) {
    'use strict';

    if (!global || !document || global.MageStockAdminMobile) return;

    const VERSION = '2.6.119';
    const UserPageRef = typeof UsrPage !== 'undefined' ? UsrPage : null;
    const SupplierPageRef = typeof SupplierPage !== 'undefined' ? SupplierPage : null;
    const SettingsPageRef = typeof SetPage !== 'undefined' ? SetPage : null;
    const UI = () => global.MageStockMobileUI || null;
    const isAdaptive = () => {
        const profile = UI()?.device?.profile;
        return profile ? profile !== 'desktop' : (global.innerWidth || 0) < 1200;
    };
    const esc = (value) => String(value == null ? '' : value)
        .replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;').replace(/'/g, '&#039;');
    const money = (value) => {
        const amount = Number(value || 0);
        return amount > 0 && global.Locale ? global.Locale.formatMoney(amount) : '—';
    };
    const announce = (message, priority) => UI()?.announce?.(message, priority || 'polite');

    const DEFAULT_USER_PERMS = {
        'products.read': true,
        'stock.read': true,
        'movements.read': true,
        'movements.create': true,
        'movements.delete': false,
        'inventory.read': true,
        'inventory.write': false,
        'kits.read': false,
        'lots.read': true,
        'reservations.read': true,
        'analytics.read': true,
        'product.versions.read': false,
        'price.read': false,
        'valuation.read': false,
        'locations.manage': false,
        'warehouses.manage': false,
        'settings.write': false,
        'users.manage': false,
        'admin.access': false
    };

    const Confirm = {
        request(options) {
            const opts = Object.assign({
                title: 'Confirmer l’action',
                description: '',
                phrase: 'CONFIRMER',
                actionLabel: 'Confirmer',
                actionClass: 'btn btn-danger',
                details: [],
                trigger: document.activeElement
            }, options || {});
            return new Promise((resolve) => {
                let settled = false;
                const finish = (value) => {
                    if (settled) return;
                    settled = true;
                    resolve(!!value);
                };
                const content = document.createElement('div');
                content.className = 'admin-confirm';
                content.innerHTML = `
                    <div class="admin-confirm__warning" role="alert">
                        <strong>${esc(opts.description || 'Cette action modifie des données importantes.')}</strong>
                        ${opts.details.length ? `<ul>${opts.details.map((item) => `<li>${esc(item)}</li>`).join('')}</ul>` : ''}
                    </div>
                    <label class="admin-field">
                        <span>Saisissez <strong>${esc(opts.phrase)}</strong> pour continuer</span>
                        <input type="text" class="inp admin-confirm__input" autocomplete="off" autocapitalize="characters" spellcheck="false" aria-describedby="adminConfirmHint">
                    </label>
                    <p class="admin-confirm__hint" id="adminConfirmHint">La validation reste désactivée tant que la phrase n’est pas exacte.</p>`;

                const validate = ({ handle, close }) => {
                    const input = content.querySelector('.admin-confirm__input');
                    if ((input?.value || '').trim() !== opts.phrase) {
                        input?.setCustomValidity?.(`Saisissez exactement ${opts.phrase}.`);
                        input?.reportValidity?.();
                        announce(`Saisissez exactement ${opts.phrase}.`, 'assertive');
                        return false;
                    }
                    finish(true);
                    close('confirmed');
                    return false;
                };

                const onClose = () => finish(false);
                if (global.MobileDetailPage) {
                    const handle = global.MobileDetailPage.open({
                        title: opts.title,
                        description: 'Confirmation renforcée',
                        content,
                        trigger: opts.trigger,
                        closeOnBackdrop: false,
                        actions: [
                            { label: 'Annuler', cls: 'btn btn-secondary', onClick: ({ close }) => { finish(false); close('cancel'); return false; } },
                            { label: opts.actionLabel, cls: opts.actionClass, close: false, onClick: validate }
                        ],
                        onClose
                    });
                    global.setTimeout(() => handle?.body?.querySelector('.admin-confirm__input')?.focus(), 100);
                    return;
                }

                Modal.show(opts.title, content.outerHTML, [
                    { label: 'Annuler', cls: 'btn-secondary', onclick: () => { finish(false); Modal.close(); } },
                    { label: opts.actionLabel, cls: opts.actionClass.replace(/^btn\s+/, ''), onclick: () => {
                        const input = document.querySelector('.modal .admin-confirm__input');
                        if ((input?.value || '').trim() !== opts.phrase) {
                            input?.setCustomValidity?.(`Saisissez exactement ${opts.phrase}.`);
                            input?.reportValidity?.();
                            return;
                        }
                        finish(true); Modal.close();
                    } }
                ], 'danger');
            });
        },

        simple(options) {
            const opts = Object.assign({ title: 'Confirmer', description: '', actionLabel: 'Continuer', actionClass: 'btn btn-primary' }, options || {});
            return new Promise((resolve) => {
                let settled = false;
                const finish = (value) => { if (!settled) { settled = true; resolve(!!value); } };
                const content = document.createElement('div');
                content.className = 'admin-confirm';
                content.innerHTML = `<div class="admin-confirm__summary"><p>${esc(opts.description)}</p></div>`;
                if (global.ActionSheet) {
                    global.ActionSheet.open({
                        title: opts.title,
                        content,
                        trigger: opts.trigger || document.activeElement,
                        actions: [
                            { label: 'Annuler', cls: 'btn btn-secondary', onClick: ({ close }) => { finish(false); close('cancel'); return false; } },
                            { label: opts.actionLabel, cls: opts.actionClass, onClick: ({ close }) => { finish(true); close('confirmed'); return false; } }
                        ],
                        onClose: () => finish(false)
                    });
                } else {
                    Modal.show(opts.title, content.outerHTML, [
                        { label: 'Annuler', cls: 'btn-secondary', onclick: () => { finish(false); Modal.close(); } },
                        { label: opts.actionLabel, cls: opts.actionClass.replace(/^btn\s+/, ''), onclick: () => { finish(true); Modal.close(); } }
                    ], 'warning');
                }
            });
        }
    };

    const Users = {
        state: { originalRender: null, originalOpen: null, originalDelete: null, controller: null, panel: null },
        install() {
            if (!UserPageRef || this.state.originalRender) return;
            const Page = UserPageRef;
            this.state.originalRender = Page.renderTable.bind(Page);
            this.state.originalOpen = Page.openModal.bind(Page);
            this.state.originalDelete = Page.delUser.bind(Page);

            Page.renderTable = (items) => {
                this.state.originalRender(items);
                this.renderCards(items);
            };
            Page.openModal = (id) => isAdaptive() ? this.openEditor(id) : this.state.originalOpen(id);
            Page.delUser = (id) => this.deleteUser(id);

            const originalInit = Page.init.bind(Page);
            Page.init = async () => {
                await originalInit();
                this.syncMode();
            };
            document.addEventListener('magestock:devicechange', () => this.syncMode());
        },
        syncMode() {
            const cards = document.getElementById('userMobileCards');
            const table = document.querySelector('#pgUsers .admin-desktop-table');
            if (!cards || !table) return;
            cards.hidden = !isAdaptive();
            table.hidden = isAdaptive();
            if (isAdaptive()) this.renderCards(UserPageRef?.users || []);
        },
        warehouseNames(user) {
            if (user.role === 'admin') return ['Tous les magasins'];
            const allowed = Array.isArray(user.allowedWarehouses) ? user.allowedWarehouses : [];
            if (!allowed.length) return ['Tous les magasins'];
            return allowed.map((id) => UserPageRef.warehouses.find((warehouse) => String(warehouse.id) === String(id))?.name).filter(Boolean);
        },
        renderCards(items) {
            const container = document.getElementById('userMobileCards');
            if (!container || !isAdaptive()) return;
            container.hidden = false;
            container.innerHTML = '';
            if (!items.length) {
                container.innerHTML = '<div class="admin-mobile-empty"><strong>Aucun utilisateur</strong><span>Créez un compte ou modifiez la recherche.</span></div>';
                return;
            }
            const fragment = document.createDocumentFragment();
            items.forEach((user) => {
                const warehouseNames = this.warehouseNames(user);
                const card = global.MobileEntityCard?.create({
                    id: user.id,
                    title: user.name || 'Utilisateur',
                    eyebrow: user.username || 'Sans identifiant',
                    meta: `${user.role === 'admin' ? 'Administrateur' : (user.role === 'magasinier' ? 'Magasinier' : 'Utilisateur')} · ${user.authSource === 'ldap' ? 'LDAP' : 'Local'}`,
                    badge: user.active === false ? 'Inactif' : 'Actif',
                    badgeClass: user.active === false ? 'admin-badge--danger' : 'admin-badge--success',
                    state: user.active === false ? 'danger' : 'success',
                    fields: [
                        { label: 'Rôle', value: user.role === 'admin' ? 'Accès complet' : (user.role === 'magasinier' ? 'Métier complet · système exclu' : 'Accès personnalisable') },
                        { label: 'Magasins', value: warehouseNames.length <= 2 ? warehouseNames.join(' · ') : `${warehouseNames.slice(0, 2).join(' · ')} +${warehouseNames.length - 2}` },
                        { label: 'Créé le', value: user.createdAt && global.Locale ? global.Locale.formatDate(user.createdAt, { day: '2-digit', month: 'short', year: 'numeric' }) : '—' }
                    ],
                    actions: [
                        { label: 'Consulter / modifier', className: 'btn btn-primary', onClick: ({ event }) => this.openEditor(user.id, event.currentTarget) },
                        { label: 'Actions', className: 'btn btn-secondary', onClick: ({ event }) => this.openActions(user, event.currentTarget) }
                    ]
                });
                if (card) fragment.appendChild(card);
            });
            container.appendChild(fragment);
        },
        openActions(user, trigger) {
            if (!global.ActionSheet) return this.openEditor(user.id, trigger);
            global.ActionSheet.open({
                title: user.name || 'Utilisateur',
                description: user.username || '',
                trigger,
                html: `<div class="admin-action-summary"><span>Rôle</span><strong>${user.role === 'admin' ? 'Administrateur' : (user.role === 'magasinier' ? 'Magasinier' : 'Utilisateur')}</strong><span>Authentification</span><strong>${user.authSource === 'ldap' ? 'LDAP / Annuaire' : 'Compte local'}</strong><span>Statut</span><strong>${user.active === false ? 'Inactif' : 'Actif'}</strong></div>`,
                actions: [
                    { label: 'Modifier', cls: 'btn btn-primary', onClick: ({ close }) => { close('edit'); this.openEditor(user.id, trigger); return false; } },
                    ...(user.recoveryEligible ? [{ label: 'Créer un jeton de récupération', cls: 'btn btn-secondary', onClick: ({ close }) => { close('recovery'); UserPageRef.openRecoveryModal(user.id); return false; } }] : []),
                    { label: 'Supprimer', cls: 'btn btn-danger', onClick: ({ close }) => { close('delete'); this.deleteUser(user.id, trigger); return false; } }
                ]
            });
        },
        async loadPermissionState(user) {
            if (!user?.id || user.role === 'admin') return { rolePerms: DEFAULT_USER_PERMS, overrides: {} };
            try {
                const result = await Api.userPerms(user.id);
                return { rolePerms: Object.assign({}, DEFAULT_USER_PERMS, result.rolePerms || {}), overrides: result.userOverrides || {} };
            } catch (_) {
                return { rolePerms: DEFAULT_USER_PERMS, overrides: {} };
            }
        },
        permissionGroups(rolePerms, overrides) {
            const groups = {};
            UserPageRef.PERM_DEFS.forEach((definition) => {
                (groups[definition.group] ||= []).push(definition);
            });
            return Object.entries(groups).map(([group, definitions]) => `
                <fieldset class="admin-permission-group">
                    <legend>${esc(group)}</legend>
                    ${definitions.map((definition) => {
                        const value = Object.prototype.hasOwnProperty.call(overrides, definition.key)
                            ? !!overrides[definition.key] : !!rolePerms[definition.key];
                        const sensitive = definition.sensitive ? 'data-sensitive-permission="1"' : '';
                        return `<label class="admin-choice-row">
                            <input type="checkbox" name="permissions" value="${esc(definition.key)}" ${sensitive} ${value ? 'checked' : ''}>
                            <span><strong>${esc(definition.label)}</strong><small>${definition.sensitive ? 'Permission système protégée' : (value ? 'Autorisé' : 'Non autorisé') + ' · modifiable'}</small></span>
                        </label>`;
                    }).join('')}
                </fieldset>`).join('');
        },
        async openEditor(id, trigger) {
            const Page = UserPageRef;
            const user = id ? (Page.users || []).find((item) => String(item.id) === String(id)) : null;
            const permissionState = await this.loadPermissionState(user);
            const isEdit = !!user;
            const isLdap = user?.authSource === 'ldap';
            const warehouseChecks = (Page.warehouses || []).map((warehouse) => {
                const selected = !isEdit ? false : (user.allowedWarehouses || []).map(String).includes(String(warehouse.id));
                return `<label class="admin-choice-row"><input type="checkbox" name="allowedWarehouses" value="${warehouse.id}" ${selected ? 'checked' : ''} ${isLdap ? 'disabled' : ''}><span><strong>${esc(warehouse.name)}</strong><small>Autoriser l’accès à ce magasin</small></span></label>`;
            }).join('') || '<p class="text-muted">Aucun magasin disponible.</p>';
            const root = document.createElement('div');
            root.className = 'admin-mobile-flow';
            root.innerHTML = `
                ${isLdap ? `<div class="ldap-security-banner"><strong>Compte géré par LDAP</strong><span>Le profil et les droits sont synchronisés depuis l’annuaire. Seule la suspension locale peut être modifiée.</span></div>` : ''}
                <div class="ms-flow" data-ms-flow data-ms-flow-storage="${isEdit ? '' : 'magestock.admin.user.create.v1'}">
                    <header class="ms-flow__header">
                        <p class="ms-flow__kicker">Compte utilisateur</p>
                        <h2 class="ms-flow__title">${isEdit ? 'Modifier le compte' : 'Nouvel utilisateur'}</h2>
                        <div class="ms-flow__progress" data-ms-flow-progress></div>
                        <ol class="ms-flow__steps" data-ms-flow-indicators>
                            <li><button type="button" data-ms-flow-indicator="1">Identité</button></li>
                            <li><button type="button" data-ms-flow-indicator="2">Périmètre</button></li>
                            <li><button type="button" data-ms-flow-indicator="3">Droits</button></li>
                            <li><button type="button" data-ms-flow-indicator="4">Vérification</button></li>
                        </ol>
                    </header>
                    <section data-ms-flow-step>
                        <h3 data-ms-flow-title>Identité et rôle</h3>
                        <label class="admin-field"><span>Nom complet *</span><input class="inp" id="amuName" name="name" required value="${esc(user?.name || '')}" ${isLdap ? 'disabled' : ''} autocomplete="name"></label>
                        <label class="admin-field"><span>Identifiant *</span><input class="inp" id="amuUsername" name="username" required value="${esc(user?.username || '')}" ${isEdit ? 'disabled' : ''} autocomplete="username"></label>
                        ${isLdap ? `<div class="admin-info">Mot de passe géré par l’annuaire — aucune valeur LDAP n’est stockée dans MageStock.</div><input id="amuPassword" type="hidden" value="">` : `<label class="admin-field"><span>Mot de passe ${isEdit ? '(laisser vide pour conserver)' : '*'}</span><input class="inp" id="amuPassword" type="password" ${isEdit ? '' : 'required'} minlength="14" maxlength="255" autocomplete="new-password"></label>`}
                        <fieldset class="admin-segmented"><legend>Rôle</legend><label><input type="radio" name="role" value="user" ${(user?.role || 'user') === 'user' ? 'checked' : ''} ${isLdap ? 'disabled' : ''}><span>Utilisateur</span></label><label><input type="radio" name="role" value="magasinier" ${user?.role === 'magasinier' ? 'checked' : ''} ${isLdap ? 'disabled' : ''}><span>Magasinier</span></label><label><input type="radio" name="role" value="admin" ${user?.role === 'admin' ? 'checked' : ''} ${isLdap ? 'disabled' : ''}><span>Administrateur</span></label></fieldset>
                        <div class="ms-flow__actions"><button class="btn btn-primary" data-ms-flow-next>Suivant</button></div>
                    </section>
                    <section data-ms-flow-step>
                        <h3 data-ms-flow-title>Périmètre d’accès</h3>
                        <p class="admin-flow-help">Un administrateur voit tous les magasins. Pour un utilisateur, aucune sélection signifie également tous les magasins.</p>
                        <div id="amuWarehouseChoices" class="admin-choice-list">${warehouseChecks}</div>
                        ${isEdit ? `<fieldset class="admin-segmented"><legend>Statut du compte</legend><label><input type="radio" name="active" value="1" ${user.active !== false ? 'checked' : ''}><span>Actif</span></label><label><input type="radio" name="active" value="0" ${user.active === false ? 'checked' : ''}><span>Inactif</span></label></fieldset>` : ''}
                        <div class="ms-flow__actions ms-flow__actions--split"><button class="btn btn-secondary" data-ms-flow-back>Retour</button><button class="btn btn-primary" data-ms-flow-next>Suivant</button></div>
                    </section>
                    <section data-ms-flow-step>
                        <h3 data-ms-flow-title>Permissions fines</h3>
                        <div id="amuAdminPermissionNotice" class="admin-info" hidden>Le rôle Administrateur dispose de tous les droits. Les réglages ci-dessous ne seront pas appliqués.</div>
                        <div id="amuPermissionGroups" class="admin-permission-list">${this.permissionGroups(permissionState.rolePerms, permissionState.overrides)}</div>
                        <div class="ms-flow__actions ms-flow__actions--split"><button class="btn btn-secondary" data-ms-flow-back>Retour</button><button class="btn btn-primary" data-ms-flow-next>Vérifier</button></div>
                    </section>
                    <section data-ms-flow-step>
                        <h3 data-ms-flow-title>Vérification</h3>
                        <div id="amuReview" class="admin-review"></div>
                        <div class="ms-flow__actions ms-flow__actions--split"><button class="btn btn-secondary" data-ms-flow-back>Modifier</button><button class="btn btn-primary" id="amuSave">${isEdit ? 'Enregistrer' : 'Créer le compte'}</button></div>
                    </section>
                </div>`;
            if (isLdap) root.querySelectorAll('input[name="permissions"]').forEach((input) => { input.disabled = true; });

            const panel = global.MobileDetailPage.open({
                title: isEdit ? user.name : 'Nouvel utilisateur',
                description: isEdit ? user.username : 'Assistant de création',
                content: root,
                trigger,
                closeOnBackdrop: false,
                onClose: () => { this.state.controller?.destroy?.(); this.state.controller = null; this.state.panel = null; }
            });
            this.state.panel = panel;
            const flow = root.querySelector('[data-ms-flow]');
            const applyRoleDefaults = (role) => {
                const defaults = UserPageRef.ROLE_DEFAULTS?.[role];
                if (!defaults) return;
                root.querySelectorAll('input[name="permissions"]').forEach((input) => {
                    if (Object.prototype.hasOwnProperty.call(defaults, input.value)) input.checked = !!defaults[input.value];
                });
            };
            const updateRoleVisibility = () => {
                const role = root.querySelector('input[name="role"]:checked')?.value || 'user';
                const admin = role === 'admin';
                const magasinier = role === 'magasinier';
                root.querySelector('#amuWarehouseChoices')?.toggleAttribute('inert', admin);
                root.querySelector('#amuWarehouseChoices')?.classList.toggle('is-disabled', admin);
                root.querySelector('#amuPermissionGroups')?.toggleAttribute('inert', admin);
                root.querySelector('#amuPermissionGroups')?.classList.toggle('is-disabled', admin);
                root.querySelector('#amuAdminPermissionNotice').hidden = !admin;
                root.querySelectorAll('input[name="permissions"][data-sensitive-permission="1"]').forEach((input) => {
                    input.disabled = isLdap || magasinier;
                    if (magasinier) input.checked = false;
                    input.closest('label')?.classList.toggle('is-role-locked', magasinier);
                });
            };
            const updateReview = () => {
                const role = root.querySelector('input[name="role"]:checked')?.value || 'user';
                const warehouseNames = Array.from(root.querySelectorAll('input[name="allowedWarehouses"]:checked')).map((input) => input.closest('label')?.querySelector('strong')?.textContent || 'Magasin');
                const allowedCount = root.querySelectorAll('input[name="permissions"]:checked').length;
                root.querySelector('#amuReview').innerHTML = `
                    <dl><div><dt>Nom</dt><dd>${esc(root.querySelector('#amuName').value)}</dd></div><div><dt>Identifiant</dt><dd>${esc(root.querySelector('#amuUsername').value)}</dd></div><div><dt>Authentification</dt><dd>${isLdap ? 'LDAP / Annuaire' : 'Compte local'}</dd></div><div><dt>Rôle</dt><dd>${role === 'admin' ? 'Administrateur — accès complet' : (role === 'magasinier' ? 'Magasinier — métier complet, système exclu' : 'Utilisateur')}</dd></div><div><dt>Magasins</dt><dd>${role === 'admin' ? 'Tous' : (warehouseNames.length ? esc(warehouseNames.join(' · ')) : 'Tous')}</dd></div><div><dt>Permissions actives</dt><dd>${role === 'admin' ? 'Toutes' : allowedCount}</dd></div></dl>`;
            };
            this.state.controller = global.MobileFlow.create(flow, {
                restore: !isEdit,
                validateStep: ({ stepIndex }) => {
                    if (stepIndex === 0 && !isEdit && !root.querySelector('#amuUsername').value.trim()) return false;
                    return true;
                },
                onChange: ({ index }) => { updateRoleVisibility(); if (index === 3) updateReview(); }
            });
            root.addEventListener('change', (event) => { if (event.target.name === 'role') { applyRoleDefaults(event.target.value); updateRoleVisibility(); } });
            root.querySelector('#amuSave').addEventListener('click', async () => {
                const name = root.querySelector('#amuName').value.trim();
                const username = root.querySelector('#amuUsername').value.trim();
                const password = root.querySelector('#amuPassword').value;
                const role = root.querySelector('input[name="role"]:checked')?.value || 'user';
                if (!name || (!isEdit && (!username || password.length < 14)) || (isEdit && password && password.length < 14)) {
                    announce('Vérifiez le nom, l’identifiant et le mot de passe.', 'assertive');
                    return;
                }
                const body = isLdap ? {
                    id: Number(user.id),
                    active: root.querySelector('input[name="active"]:checked')?.value !== '0'
                } : {
                    name, role,
                    allowedWarehouses: role === 'admin' ? [] : Array.from(root.querySelectorAll('input[name="allowedWarehouses"]:checked')).map((input) => Number(input.value))
                };
                if (!isLdap && !isEdit) { body.username = username; body.password = password; }
                else if (!isLdap) {
                    body.id = Number(user.id);
                    body.active = root.querySelector('input[name="active"]:checked')?.value !== '0';
                    if (password) body.password = password;
                }
                const button = root.querySelector('#amuSave');
                button.disabled = true;
                try {
                    const saved = isEdit ? await Api.userEdit(body) : await Api.userAdd(body);
                    if (!isLdap && role !== 'admin') {
                        const permissions = {};
                        root.querySelectorAll('input[name="permissions"]').forEach((input) => { permissions[input.value] = input.checked; });
                        await Api.userPermsEdit({ userId: String(user?.id || saved?.id), permissions });
                    }
                    this.state.controller?.clearDraft?.();
                    panel.close('saved');
                    toast(isEdit ? 'Utilisateur mis à jour' : 'Utilisateur créé', 'success');
                    await Page.load();
                } catch (error) {
                    toast(error.message || 'Enregistrement impossible', 'error');
                } finally { button.disabled = false; }
            });
            updateRoleVisibility();
        },
        async deleteUser(id, trigger) {
            const user = (UserPageRef?.users || []).find((item) => String(item.id) === String(id));
            const phrase = user?.username ? `SUPPRIMER ${user.username}` : 'SUPPRIMER';
            const confirmed = await Confirm.request({
                title: 'Supprimer le compte', phrase,
                description: `Le compte ${user?.name || ''} sera supprimé définitivement.`,
                details: ['Les historiques métier restent conservés.', 'Votre propre compte ne peut pas être supprimé.'],
                actionLabel: 'Supprimer le compte', trigger
            });
            if (!confirmed) return;
            try { await Api.userDel(id); toast('Utilisateur supprimé', 'success'); this.state.panel?.close?.('deleted'); await UserPageRef.load(); }
            catch (error) { toast(error.message || 'Suppression impossible', 'error'); }
        }
    };

    const Suppliers = {
        state: { originalRender: null, originalOpen: null, originalDelete: null, panel: null, controller: null },
        install() {
            if (!SupplierPageRef || this.state.originalRender) return;
            const Page = SupplierPageRef;
            this.state.originalRender = Page.renderTable.bind(Page);
            this.state.originalOpen = Page.openModal.bind(Page);
            this.state.originalDelete = Page.deleteSupplier.bind(Page);
            Page.renderTable = (items) => { this.state.originalRender(items); this.renderCards(items); };
            Page.openModal = (id) => isAdaptive() ? this.openEditor(id) : this.state.originalOpen(id);
            Page.deleteSupplier = (id) => this.deleteSupplier(id);
            const originalInit = Page.init.bind(Page);
            Page.init = async () => { await originalInit(); this.syncMode(); };
            document.addEventListener('magestock:devicechange', () => this.syncMode());
        },
        syncMode() {
            const cards = document.getElementById('supplierMobileCards');
            const table = document.querySelector('#pgSuppliers .admin-desktop-table');
            if (!cards || !table) return;
            cards.hidden = !isAdaptive(); table.hidden = isAdaptive();
            if (isAdaptive()) this.renderCards(SupplierPageRef?.suppliers || []);
        },
        renderCards(items) {
            const container = document.getElementById('supplierMobileCards');
            if (!container || !isAdaptive()) return;
            container.hidden = false; container.innerHTML = '';
            if (!items.length) { container.innerHTML = '<div class="admin-mobile-empty"><strong>Aucun fournisseur</strong><span>Créez un partenaire ou modifiez la recherche.</span></div>'; return; }
            const fragment = document.createDocumentFragment();
            items.forEach((raw) => {
                const supplier = SupplierPageRef.normalizeSupplier(raw);
                const linked = SupplierPageRef.brands.filter((brand) => supplier.linkedBrands.map(String).includes(String(brand.id)));
                const card = global.MobileEntityCard?.create({
                    id: supplier.id,
                    title: supplier.name || 'Fournisseur',
                    eyebrow: supplier.companyName || supplier.siret || 'Partenaire',
                    meta: supplier.contact || supplier.email || 'Aucun contact principal',
                    badge: SupplierPageRef.statusLabel(supplier.status),
                    badgeClass: `admin-badge--${supplier.status}`,
                    state: supplier.status === 'blocked' ? 'danger' : (supplier.status === 'watch' ? 'warning' : 'success'),
                    fields: [
                        { label: 'Délai', value: supplier.leadTime ? `${supplier.leadTime} jours` : '—' },
                        { label: 'Minimum', value: money(supplier.minimumOrderAmount) },
                        { label: 'Franco', value: money(supplier.freeShippingThreshold) },
                        { label: 'Marques', value: linked.length ? (linked.slice(0, 2).map((brand) => brand.name).join(' · ') + (linked.length > 2 ? ` +${linked.length - 2}` : '')) : '—' },
                        { label: 'Contacts', value: `${supplier.contacts.length} contact${supplier.contacts.length > 1 ? 's' : ''}` }
                    ],
                    actions: [
                        { label: 'Consulter / modifier', className: 'btn btn-primary', onClick: ({ event }) => this.openEditor(supplier.id, event.currentTarget) },
                        { label: 'Actions', className: 'btn btn-secondary', onClick: ({ event }) => this.openActions(supplier, event.currentTarget) }
                    ]
                });
                if (card) fragment.appendChild(card);
            });
            container.appendChild(fragment);
        },
        openActions(supplier, trigger) {
            global.ActionSheet?.open({
                title: supplier.name, description: SupplierPageRef.statusLabel(supplier.status), trigger,
                html: `<div class="admin-action-summary"><span>Contact</span><strong>${esc(supplier.contact || supplier.email || 'Non renseigné')}</strong><span>Conditions</span><strong>${supplier.leadTime ? `${supplier.leadTime} j` : '—'} · ${money(supplier.minimumOrderAmount)}</strong></div>`,
                actions: [
                    { label: 'Modifier', cls: 'btn btn-primary', onClick: ({ close }) => { close('edit'); this.openEditor(supplier.id, trigger); return false; } },
                    { label: 'Supprimer', cls: 'btn btn-danger', onClick: ({ close }) => { close('delete'); this.deleteSupplier(supplier.id, trigger); return false; } }
                ]
            });
        },
        contactRow(contact, index) {
            const c = contact || {};
            return `<article class="admin-contact-card" data-contact-index="${index}">
                <div class="admin-contact-card__head"><strong>Contact ${index + 1}</strong><button type="button" class="btn btn-ghost admin-contact-remove">Retirer</button></div>
                <div class="admin-form-grid">
                    <label class="admin-field"><span>Type</span><select class="inp admin-contact-type">${['commercial','sav','logistique','facturation','support'].map((value) => `<option value="${value}" ${(c.type || 'commercial') === value ? 'selected' : ''}>${value.charAt(0).toUpperCase() + value.slice(1)}</option>`).join('')}</select></label>
                    <label class="admin-field"><span>Nom</span><input class="inp admin-contact-name" value="${esc(c.name || '')}"></label>
                    <label class="admin-field"><span>Fonction</span><input class="inp admin-contact-role" value="${esc(c.role || '')}"></label>
                    <label class="admin-field"><span>Téléphone</span><input class="inp admin-contact-phone" type="tel" value="${esc(c.phone || '')}"></label>
                    <label class="admin-field"><span>Email</span><input class="inp admin-contact-email" type="email" value="${esc(c.email || '')}"></label>
                </div>
            </article>`;
        },
        supplierFields(supplier, createMode) {
            const Page = SupplierPageRef;
            const brandChoices = Page.brands.map((brand) => `<label class="admin-choice-row"><input type="checkbox" name="linkedBrands" value="${brand.id}" ${supplier.linkedBrands.map(String).includes(String(brand.id)) ? 'checked' : ''}><span><strong>${esc(brand.name)}</strong><small>Associer cette marque au fournisseur</small></span></label>`).join('') || '<p class="text-muted">Aucune marque disponible.</p>';
            const identity = `<div class="admin-form-grid"><label class="admin-field"><span>Nom fournisseur *</span><input class="inp" id="amsName" required value="${esc(supplier.name)}"></label><label class="admin-field"><span>Raison sociale</span><input class="inp" id="amsCompany" value="${esc(supplier.companyName)}"></label><label class="admin-field"><span>Statut</span><select class="inp" id="amsStatus"><option value="active" ${supplier.status === 'active' ? 'selected' : ''}>Actif</option><option value="watch" ${supplier.status === 'watch' ? 'selected' : ''}>À surveiller</option><option value="inactive" ${supplier.status === 'inactive' ? 'selected' : ''}>Inactif</option><option value="blocked" ${supplier.status === 'blocked' ? 'selected' : ''}>Bloqué</option></select></label><label class="admin-field"><span>Contact principal</span><input class="inp" id="amsContact" value="${esc(supplier.contact)}"></label><label class="admin-field"><span>Email</span><input class="inp" id="amsEmail" type="email" value="${esc(supplier.email)}"></label><label class="admin-field"><span>Téléphone</span><input class="inp" id="amsPhone" type="tel" value="${esc(supplier.phone)}"></label><label class="admin-field"><span>Site web</span><input class="inp" id="amsWebsite" type="url" value="${esc(supplier.website)}"></label><label class="admin-field"><span>SIRET</span><input class="inp" id="amsSiret" value="${esc(supplier.siret)}"></label><label class="admin-field"><span>TVA intracom</span><input class="inp" id="amsVat" value="${esc(supplier.vatNumber)}"></label></div><label class="admin-field"><span>Adresse</span><textarea class="inp" id="amsAddress" rows="3">${esc(supplier.address)}</textarea></label>`;
            const commercial = `<div class="admin-form-grid"><label class="admin-field"><span>Délai moyen (jours)</span><input class="inp" id="amsLead" type="number" min="0" value="${supplier.leadTime || 0}"></label><label class="admin-field"><span>Minimum de commande</span><input class="inp" id="amsMin" type="number" min="0" step="0.01" value="${supplier.minimumOrderAmount || 0}"></label><label class="admin-field"><span>Franco de port</span><input class="inp" id="amsFree" type="number" min="0" step="0.01" value="${supplier.freeShippingThreshold || 0}"></label><label class="admin-field"><span>Conditions de paiement</span><input class="inp" id="amsPayment" value="${esc(supplier.paymentTerms)}"></label></div><h4>Marques liées</h4><div id="amsBrands" class="admin-choice-list admin-choice-list--compact">${brandChoices}</div>`;
            const contacts = `<div class="admin-section-heading"><div><h4>Contacts fournisseur</h4><p>Commercial, SAV, logistique, facturation ou support.</p></div><button type="button" class="btn btn-secondary" id="amsAddContact">Ajouter</button></div><div id="amsContacts">${supplier.contacts.map((contact, index) => this.contactRow(contact, index)).join('')}</div><label class="admin-field"><span>Notes internes</span><textarea class="inp" id="amsNotes" rows="4">${esc(supplier.notes)}</textarea></label>`;
            return { identity, commercial, contacts, createMode };
        },
        collect(root) {
            const contacts = Array.from(root.querySelectorAll('.admin-contact-card')).map((row) => ({
                type: row.querySelector('.admin-contact-type')?.value || 'commercial',
                name: row.querySelector('.admin-contact-name')?.value.trim() || '',
                role: row.querySelector('.admin-contact-role')?.value.trim() || '',
                phone: row.querySelector('.admin-contact-phone')?.value.trim() || '',
                email: row.querySelector('.admin-contact-email')?.value.trim() || ''
            })).filter((contact) => contact.name || contact.role || contact.phone || contact.email);
            return {
                name: root.querySelector('#amsName')?.value.trim() || '',
                companyName: root.querySelector('#amsCompany')?.value.trim() || '',
                status: root.querySelector('#amsStatus')?.value || 'active',
                contact: root.querySelector('#amsContact')?.value.trim() || '',
                email: root.querySelector('#amsEmail')?.value.trim() || '',
                phone: root.querySelector('#amsPhone')?.value.trim() || '',
                website: root.querySelector('#amsWebsite')?.value.trim() || '',
                siret: root.querySelector('#amsSiret')?.value.trim() || '',
                vatNumber: root.querySelector('#amsVat')?.value.trim() || '',
                address: root.querySelector('#amsAddress')?.value.trim() || '',
                leadTime: Number(root.querySelector('#amsLead')?.value || 0),
                minimumOrderAmount: Number(root.querySelector('#amsMin')?.value || 0),
                freeShippingThreshold: Number(root.querySelector('#amsFree')?.value || 0),
                paymentTerms: root.querySelector('#amsPayment')?.value.trim() || '',
                linkedBrands: Array.from(root.querySelectorAll('input[name="linkedBrands"]:checked')).map((input) => Number(input.value)),
                contacts,
                notes: root.querySelector('#amsNotes')?.value.trim() || ''
            };
        },
        bindContacts(root) {
            const rebind = () => root.querySelectorAll('.admin-contact-remove').forEach((button) => button.onclick = () => button.closest('.admin-contact-card')?.remove());
            root.querySelector('#amsAddContact')?.addEventListener('click', () => {
                const list = root.querySelector('#amsContacts');
                list.insertAdjacentHTML('beforeend', this.contactRow({}, list.children.length));
                rebind();
                list.lastElementChild?.querySelector('input')?.focus();
            });
            rebind();
        },
        async openEditor(id, trigger) {
            const Page = SupplierPageRef;
            const supplier = Page.normalizeSupplier(id ? Page.suppliers.find((item) => String(item.id) === String(id)) || {} : {});
            const isEdit = !!id;
            const fields = this.supplierFields(supplier, !isEdit);
            const root = document.createElement('div');
            root.className = 'admin-mobile-flow admin-supplier-editor';
            if (!isEdit) {
                root.innerHTML = `<div class="ms-flow" data-ms-flow data-ms-flow-storage="magestock.admin.supplier.create.v1"><header class="ms-flow__header"><p class="ms-flow__kicker">Partenaire achats</p><h2 class="ms-flow__title">Nouveau fournisseur</h2><div class="ms-flow__progress" data-ms-flow-progress></div><ol class="ms-flow__steps" data-ms-flow-indicators><li><button data-ms-flow-indicator="1">Identité</button></li><li><button data-ms-flow-indicator="2">Commercial</button></li><li><button data-ms-flow-indicator="3">Contacts</button></li><li><button data-ms-flow-indicator="4">Vérification</button></li></ol></header><section data-ms-flow-step><h3 data-ms-flow-title>Identité et coordonnées</h3>${fields.identity}<div class="ms-flow__actions"><button class="btn btn-primary" data-ms-flow-next>Suivant</button></div></section><section data-ms-flow-step><h3 data-ms-flow-title>Conditions commerciales</h3>${fields.commercial}<div class="ms-flow__actions ms-flow__actions--split"><button class="btn btn-secondary" data-ms-flow-back>Retour</button><button class="btn btn-primary" data-ms-flow-next>Suivant</button></div></section><section data-ms-flow-step><h3 data-ms-flow-title>Contacts et notes</h3>${fields.contacts}<div class="ms-flow__actions ms-flow__actions--split"><button class="btn btn-secondary" data-ms-flow-back>Retour</button><button class="btn btn-primary" data-ms-flow-next>Vérifier</button></div></section><section data-ms-flow-step><h3 data-ms-flow-title>Vérification</h3><div id="amsReview" class="admin-review"></div><div class="ms-flow__actions ms-flow__actions--split"><button class="btn btn-secondary" data-ms-flow-back>Modifier</button><button class="btn btn-primary" id="amsSave">Créer le fournisseur</button></div></section></div>`;
            } else {
                root.innerHTML = `<div class="admin-edit-sections"><details open><summary>Identité et coordonnées</summary><div class="admin-edit-section__body">${fields.identity}</div></details><details><summary>Conditions commerciales et marques</summary><div class="admin-edit-section__body">${fields.commercial}</div></details><details><summary>Contacts et notes</summary><div class="admin-edit-section__body">${fields.contacts}</div></details><div class="admin-edit-actions" data-ms-sticky-actions><button class="btn btn-primary" id="amsSave">Enregistrer</button><button class="btn btn-secondary" id="amsMore">Autres actions</button></div></div>`;
            }
            const panel = global.MobileDetailPage.open({ title: isEdit ? supplier.name : 'Nouveau fournisseur', description: isEdit ? Page.statusLabel(supplier.status) : 'Assistant de création', content: root, trigger, closeOnBackdrop: false, onClose: () => { this.state.controller?.destroy?.(); this.state.controller = null; this.state.panel = null; } });
            this.state.panel = panel;
            this.bindContacts(root);
            const updateReview = () => {
                const data = this.collect(root);
                const review = root.querySelector('#amsReview');
                if (review) review.innerHTML = `<dl><div><dt>Fournisseur</dt><dd>${esc(data.name || 'À renseigner')}</dd></div><div><dt>Statut</dt><dd>${esc(Page.statusLabel(data.status))}</dd></div><div><dt>Contact principal</dt><dd>${esc(data.contact || data.email || 'Non renseigné')}</dd></div><div><dt>Délai</dt><dd>${data.leadTime || 0} jour(s)</dd></div><div><dt>Minimum / Franco</dt><dd>${money(data.minimumOrderAmount)} / ${money(data.freeShippingThreshold)}</dd></div><div><dt>Marques</dt><dd>${data.linkedBrands.length}</dd></div><div><dt>Contacts</dt><dd>${data.contacts.length}</dd></div></dl>`;
            };
            if (!isEdit) this.state.controller = global.MobileFlow.create(root.querySelector('[data-ms-flow]'), { onChange: ({ index }) => { if (index === 3) updateReview(); } });
            root.querySelector('#amsSave').addEventListener('click', async () => {
                const data = this.collect(root);
                if (!data.name) { toast('Nom fournisseur obligatoire', 'error'); root.querySelector('#amsName')?.focus(); return; }
                if (isEdit) data.id = Number(id);
                const button = root.querySelector('#amsSave'); button.disabled = true;
                try {
                    if (isEdit) await Api.supplierEdit(data); else await Api.supplierAdd(data);
                    this.state.controller?.clearDraft?.(); panel.close('saved');
                    toast(isEdit ? 'Fournisseur mis à jour' : 'Fournisseur créé', 'success');
                    await Page.load();
                } catch (error) { toast(error.message || 'Enregistrement impossible', 'error'); }
                finally { button.disabled = false; }
            });
            root.querySelector('#amsMore')?.addEventListener('click', (event) => this.openActions(supplier, event.currentTarget));
        },
        async deleteSupplier(id, trigger) {
            const supplier = SupplierPageRef?.suppliers.find((item) => String(item.id) === String(id));
            const phrase = `SUPPRIMER ${supplier?.name || 'FOURNISSEUR'}`;
            const confirmed = await Confirm.request({ title: 'Supprimer le fournisseur', phrase, description: 'Le fournisseur sera supprimé de la liste des partenaires.', details: ['Les commandes historiques restent conservées.', 'Vérifiez qu’aucune commande active ne dépend de ce fournisseur.'], actionLabel: 'Supprimer définitivement', trigger });
            if (!confirmed) return;
            try { await Api.supplierDel(id); this.state.panel?.close?.('deleted'); toast('Fournisseur supprimé', 'success'); await SupplierPageRef.load(); }
            catch (error) { toast(error.message || 'Suppression impossible', 'error'); }
        }
    };

    const Settings = {
        sections: [],
        active: '',
        originalMethods: {},
        install() {
            if (!SettingsPageRef || this.originalMethods.init) return;
            const Page = SettingsPageRef;
            this.originalMethods.init = Page.init.bind(Page);
            Page.init = async () => { await this.originalMethods.init(); await this.enhance(); };
            this.patchSecurity();
            document.addEventListener('magestock:devicechange', () => this.syncMode());
        },
        sectionDefinition(title) {
            const value = String(title || '').toLowerCase();
            if (value.includes('généraux')) return { key: 'general', title: 'Configuration générale', kicker: 'Identité & formats', icon: '⚙', description: 'Entreprise, SKU, pays, format régional, devise et logo.' };
            if (value.includes('ldap') || value.includes('active directory')) return { key: 'ldap', title: 'LDAP / Active Directory', kicker: 'Authentification entreprise', icon: '⌘', description: 'Serveurs, chiffrement, groupes, droits et diagnostics.' };
            if (value.includes('sauvegarde')) return { key: 'backup', title: 'Sauvegarde & restauration', kicker: 'Protection des données', icon: '⬇', description: 'Exporter une copie ou restaurer un fichier contrôlé.' };
            if (value.includes('archivage')) return { key: 'archive', title: 'Archivage', kicker: 'Conservation annuelle', icon: '▣', description: 'Créer, consulter et restaurer les archives annuelles.' };
            if (value.includes('langue')) return { key: 'language', title: 'Langue', kicker: 'Préférence utilisateur', icon: '文', description: 'Choisir la langue du compte courant.' };
            if (value.includes('push')) return { key: 'push', title: 'Notifications', kicker: 'Cet appareil', icon: '◉', description: 'Activer et tester les notifications push.' };
            if (value.includes('danger')) return { key: 'danger', title: 'Zone de danger', kicker: 'Actions irréversibles', icon: '!', description: 'Suppressions massives avec confirmation renforcée.', danger: true };
            return null;
        },
        async enhance() {
            const root = document.getElementById('pgSettings');
            if (!root) return;
            this.sections = Array.from(root.querySelectorAll('section.settings-card')).map((section) => {
                const title = section.querySelector('h3')?.textContent.trim() || '';
                const definition = this.sectionDefinition(title);
                if (!definition) return null;
                section.dataset.adminSettingsSection = definition.key;
                section.classList.add('settings-mobile-section');
                return Object.assign({ element: section }, definition);
            }).filter(Boolean);
            this.renderHub();
            this.bindBack();
            const restoreInput = document.getElementById('restoreFileInput');
            if (restoreInput) {
                restoreInput.onchange = async () => {
                    const file = restoreInput.files && restoreInput.files[0];
                    try { if (file) await this.secureBackupImport(file); }
                    finally { restoreInput.value = ''; }
                };
            }
            await this.renderArchiveCards();
            try { this.active = sessionStorage.getItem('magestock.settings.section') || ''; } catch (_) {}
            this.syncMode();
        },
        renderHub() {
            const hub = document.getElementById('settingsMobileHub');
            if (!hub) return;
            hub.innerHTML = `<div class="settings-mobile-hub__intro"><span>Administration</span><h2>Choisissez une rubrique</h2><p>Les réglages longs sont séparés pour éviter une page unique difficile à parcourir.</p></div><div class="settings-mobile-hub__grid">${this.sections.map((section) => `<button type="button" class="settings-mobile-hub__card${section.danger ? ' is-danger' : ''}" data-settings-open="${section.key}"><span class="settings-mobile-hub__icon" aria-hidden="true">${section.icon}</span><span><strong>${esc(section.title)}</strong><small>${esc(section.description)}</small></span><span aria-hidden="true">›</span></button>`).join('')}</div>`;
            hub.querySelectorAll('[data-settings-open]').forEach((button) => button.addEventListener('click', () => this.open(button.dataset.settingsOpen, button)));
        },
        bindBack() {
            document.getElementById('settingsMobileBack')?.addEventListener('click', () => this.closeSection());
        },
        syncMode() {
            const adaptive = isAdaptive();
            const hub = document.getElementById('settingsMobileHub');
            const head = document.getElementById('settingsMobileSectionHead');
            if (!hub || !head) return;
            if (!adaptive) {
                hub.hidden = true; head.hidden = true;
                this.sections.forEach((section) => { section.element.hidden = false; section.element.removeAttribute('inert'); });
                return;
            }
            if (this.active) this.open(this.active, null, false);
            else this.closeSection(false);
        },
        open(key, trigger, focus = true) {
            if (!isAdaptive()) return;
            const section = this.sections.find((item) => item.key === key);
            if (!section) return;
            this.active = key;
            const hub = document.getElementById('settingsMobileHub');
            const head = document.getElementById('settingsMobileSectionHead');
            hub.hidden = true; head.hidden = false;
            document.getElementById('settingsMobileSectionKicker').textContent = section.kicker;
            document.getElementById('settingsMobileSectionTitle').textContent = section.title;
            this.sections.forEach((item) => {
                const active = item.key === key;
                item.element.hidden = !active;
                item.element.toggleAttribute('inert', !active);
            });
            try { sessionStorage.setItem('magestock.settings.section', key); } catch (_) {}
            if (focus) {
                global.scrollTo({ top: 0, behavior: 'smooth' });
                global.setTimeout(() => document.getElementById('settingsMobileSectionTitle')?.focus?.(), 80);
            }
        },
        closeSection(focus = true) {
            if (!isAdaptive()) return;
            this.active = '';
            const hub = document.getElementById('settingsMobileHub');
            const head = document.getElementById('settingsMobileSectionHead');
            hub.hidden = false; head.hidden = true;
            this.sections.forEach((section) => { section.element.hidden = true; section.element.setAttribute('inert', ''); });
            try { sessionStorage.removeItem('magestock.settings.section'); } catch (_) {}
            if (focus) { global.scrollTo({ top: 0, behavior: 'smooth' }); global.setTimeout(() => hub.querySelector('button')?.focus(), 80); }
        },
        async renderArchiveCards() {
            const list = document.getElementById('archiveList');
            if (!list) return;
            let cards = document.getElementById('archiveMobileCards');
            if (!cards) {
                cards = document.createElement('div'); cards.id = 'archiveMobileCards'; cards.className = 'archive-mobile-cards ms-entity-list';
                list.parentNode.insertBefore(cards, list);
            }
            try {
                const archives = await Api.archiveList();
                cards.innerHTML = '';
                if (!archives.length) { cards.innerHTML = '<div class="admin-mobile-empty"><strong>Aucune archive</strong><span>Créez une archive annuelle pour sécuriser l’historique.</span></div>'; return; }
                global.MobileEntityCard?.renderList(cards, archives, (archive) => ({
                    id: archive.file,
                    title: archive.label || archive.file,
                    eyebrow: archive.createdAt && global.Locale ? global.Locale.formatDateTime(archive.createdAt) : 'Archive',
                    meta: archive.sizeHuman || '',
                    fields: [
                        { label: 'Année', value: archive.year || '—' },
                        { label: 'Contenu', value: Object.keys(archive.counts || {}).length ? Object.entries(archive.counts).map(([key, count]) => `${key}: ${count}`).join(' · ') : '—' }
                    ],
                    actions: [
                        { label: 'Consulter', className: 'btn btn-primary', onClick: () => SettingsPageRef.readArchive(archive.file) },
                        { label: 'Restaurer', className: 'btn btn-warning', onClick: ({ event }) => SettingsPageRef.restoreArchive(archive.file, archive.label, event.currentTarget) },
                        { label: 'Supprimer', className: 'btn btn-danger', onClick: ({ event }) => SettingsPageRef.deleteArchive(archive.file, archive.label, event.currentTarget) }
                    ]
                }));
            } catch (error) { cards.innerHTML = `<div class="admin-mobile-empty is-error"><strong>Archives indisponibles</strong><span>${esc(error.message || 'Erreur de chargement')}</span></div>`; }
        },
        patchSecurity() {
            const Page = SettingsPageRef;
            const originalRender = Page._renderArchiveList?.bind(Page);
            if (originalRender) Page._renderArchiveList = async (...args) => { const result = await originalRender(...args); await this.renderArchiveCards(); return result; };

            Page.restoreArchive = async (file, label, trigger) => {
                const confirmed = await Confirm.request({ title: 'Restaurer une archive', phrase: 'RESTAURER', description: `Les entités contenues dans « ${label || file} » remplaceront les données actuelles.`, details: ['Exportez une sauvegarde complète avant de continuer.', 'La page sera rechargée après restauration.'], actionLabel: 'Restaurer l’archive', actionClass: 'btn btn-warning', trigger });
                if (!confirmed) return;
                try { const result = await Api.archiveRestore(file, 'RESTAURER'); const total = Object.values(result.restored || {}).reduce((sum, count) => sum + count, 0); toast(`Archive restaurée — ${total} enregistrements`, 'success'); global.setTimeout(() => location.reload(), 1000); }
                catch (error) { toast(error.message || 'Restauration impossible', 'error'); }
            };
            Page.deleteArchive = async (file, label, trigger) => {
                const confirmed = await Confirm.request({ title: 'Supprimer une archive', phrase: 'SUPPRIMER', description: `L’archive « ${label || file} » sera supprimée définitivement.`, details: ['Cette suppression ne touche pas les données actives.', 'Le fichier d’archive ne pourra pas être récupéré.'], actionLabel: 'Supprimer l’archive', trigger });
                if (!confirmed) return;
                try { await Api.archiveDelete(file, 'SUPPRIMER'); toast('Archive supprimée', 'success'); await Page._renderArchiveList(); }
                catch (error) { toast(error.message || 'Suppression impossible', 'error'); }
            };
            Page.clearEntity = async (entity, label, trigger) => {
                const phrase = entity === 'products' ? 'SUPPRIMER PRODUITS' : 'SUPPRIMER MOUVEMENTS';
                const confirmed = await Confirm.request({ title: 'Suppression massive', phrase, description: `Vous allez supprimer ${label}.`, details: ['Créez une sauvegarde avant cette action.', 'Cette opération est irréversible.'], actionLabel: 'Supprimer les données', trigger });
                if (!confirmed) return;
                try {
                    if (entity === 'products') { const products = await Api.products(); for (const product of products) await Api.prodDel(product.id); }
                    else if (entity === 'movements') await Api.mvClear();
                    toast('Suppression terminée', 'success'); location.reload();
                } catch (error) { toast(error.message || 'Suppression impossible', 'error'); }
            };
            Page.clearAll = async (trigger) => {
                const confirmed = await Confirm.request({ title: 'Supprimer toutes les données', phrase: 'TOUT SUPPRIMER', description: 'Produits, stock, mouvements, magasins, alertes et inventaires seront supprimés.', details: ['Téléchargez une sauvegarde complète.', 'Fermez les autres sessions MageStock.', 'Cette opération est irréversible.'], actionLabel: 'Tout supprimer', trigger });
                if (!confirmed) return;
                try {
                    const products = await Api.products(); for (const product of products) await Api.prodDel(product.id);
                    await Api.mvClear();
                    const warehouses = await Api.warehouses(); for (const warehouse of warehouses) await Api.whDel(warehouse.id);
                    toast('Toutes les données ont été supprimées', 'success'); global.setTimeout(() => location.reload(), 1000);
                } catch (error) { toast(error.message || 'Suppression impossible', 'error'); }
            };
            Page.scrollToArchive = () => {
                if (isAdaptive()) { this.open('archive'); return; }
                document.getElementById('archiveSection')?.scrollIntoView({ behavior: 'smooth', block: 'start' });
            };
            Page.createArchive = async () => {
                const label = document.getElementById('archiveLabel')?.value.trim() || '';
                const year = document.getElementById('archiveYear')?.value || String(new Date().getFullYear() - 1);
                const entities = Array.from(document.querySelectorAll('.archive-entity-cb:checked')).map((input) => input.value);
                if (!entities.length) { toast('Sélectionnez au moins une famille de données', 'warning'); return; }
                const fullLabel = label || `Archive ${year}`;
                const confirmed = await Confirm.simple({ title: 'Créer l’archive', description: `${fullLabel} contiendra : ${entities.join(', ')}.`, actionLabel: 'Créer maintenant', trigger: document.getElementById('btnCreateArchive') });
                if (!confirmed) return;
                const button = document.getElementById('btnCreateArchive'); if (button) { button.disabled = true; button.textContent = 'Archivage…'; }
                try { const result = await Api.archiveCreate({ label: fullLabel, year, entities }); toast(`Archive créée — ${result.sizeHuman}`, 'success'); if (document.getElementById('archiveLabel')) document.getElementById('archiveLabel').value = ''; await Page._renderArchiveList(); }
                catch (error) { toast(error.message || 'Création impossible', 'error'); }
                finally { if (button) { button.disabled = false; button.textContent = 'Créer l’archive'; } }
            };
        },
        async secureBackupImport(file) {
            let backup;
            try { backup = JSON.parse(await file.text()); }
            catch (_) { toast('Le fichier sélectionné n’est pas un JSON valide.', 'error'); return; }
            const required = ['warehouses', 'products', 'stock', 'movements'];
            const invalid = required.filter((key) => !Array.isArray(backup?.[key]));
            if (invalid.length) { toast(`Sauvegarde incomplète : ${invalid.join(', ')}`, 'error'); return; }
            const counts = Object.entries(backup).filter(([, value]) => Array.isArray(value)).map(([key, value]) => `${key}: ${value.length}`);
            const confirmed = await Confirm.request({ title: 'Importer une sauvegarde', phrase: 'RESTAURER', description: `Fichier : ${file.name}`, details: [`Version source : ${backup?._meta?.version || 'inconnue'}`, ...counts.slice(0, 7), 'Les données actuelles seront remplacées.'], actionLabel: 'Importer et remplacer', actionClass: 'btn btn-warning', trigger: document.getElementById('btnRestore') });
            if (!confirmed) return;
            try { await Api.backupImport(backup, 'RESTAURER'); toast('Sauvegarde importée', 'success'); global.setTimeout(() => location.reload(), 800); }
            catch (error) { toast(error.message || 'Import impossible', 'error'); }
        }
    };

    const AdminMobile = {
        version: VERSION,
        confirm: Confirm,
        users: Users,
        suppliers: Suppliers,
        settings: Settings,
        install() {
            Users.install(); Suppliers.install(); Settings.install();
            document.documentElement.dataset.adminMobile = VERSION;
        }
    };

    global.MageStockAdminMobile = AdminMobile;
    global.AdminSecureConfirm = Confirm;
    AdminMobile.install();
})(window, document);
