/**
 * Projet                    : MageStock
 * Logiciel                  : MageStock
 * Fichier                   : assets/js/pages/warehouse-manager.js
 * Rôle                      : Gestion interactive unique des magasins et catégories
 * Auteur                    : Régis KREMER
 * Version du fichier        : 2.6.116
 * Version générale          : 2.6.116
 * Lot                       : MAGESTOCK WAREHOUSE UI CONSOLIDATION1
 * Base requise              : MageStock 2.6.115
 * Création                  : 2026-02-21
 * Dernière modification     : 2026-07-25
 * Dépendances               : api.js, app.js, i18n.js, views/warehouse-manager.php
 * Données touchées          : magasins et catégories via les API protégées
 * Permissions               : warehouses.manage pour les écritures
 * Sécurité                  : échappement HTML, aucun gestionnaire inline, CSRF via Api
 * Compatibilité             : navigateurs modernes, smartphone, tablette et ordinateur
 *
 * Résumé :
 * - remplace l'ancien module warehouses.js et centralise toutes les actions ;
 * - affiche les informations réellement persistées par l'API ;
 * - explique les dépendances qui bloquent une suppression non destructive.
 *
 * Historique :
 * - 2.6.116 — consolidation, internationalisation et suppression contrôlée.
 * - 2.6.101 — cartes compactes non étirées.
 * - 2.6.86 — formulaires et confirmations accessibles.
 */
const WarehouseManagerPage = {
    warehouses: [],
    products: [],

    tr(key, fallback, params = null) {
        if (typeof window.t === 'function') return window.t(key, params || {}, fallback);
        return String(fallback || key).replace(/\{([a-zA-Z0-9_.-]+)\}/g, (match, name) => (
            params && Object.prototype.hasOwnProperty.call(params, name) ? String(params[name]) : match
        ));
    },

    esc(value) {
        return String(value == null ? '' : value).replace(/[&<>"']/g, (char) => ({
            '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#039;'
        }[char]));
    },

    asArray(value) {
        if (Array.isArray(value)) return value;
        if (value == null || value === '') return [];
        try {
            const parsed = JSON.parse(value);
            return Array.isArray(parsed) ? parsed : [];
        } catch (_) {
            return [];
        }
    },

    async init() {
        const root = document.getElementById('pgWarehouseManager');
        if (!root || root.dataset.managerReady === '1') return;
        root.dataset.managerReady = '1';
        await Promise.resolve(window._i18nReady).catch(() => {});
        document.getElementById('btnNewWarehouse')?.addEventListener('click', () => this.openWarehouseModal());
        root.querySelector('.warehouse-manager-grid')?.addEventListener('click', (event) => this.handleGridAction(event));
        await this.load();
    },

    handleGridAction(event) {
        const button = event.target.closest('[data-wm-action]');
        if (!button) return;
        const warehouseId = button.dataset.warehouseId || '';
        const action = button.dataset.wmAction || '';
        if (action === 'edit') this.openWarehouseModal(warehouseId);
        if (action === 'add-category') this.openCategoryModal(warehouseId);
        if (action === 'remove-category') this.removeCategory(warehouseId, button.dataset.category || '');
    },

    async load() {
        try {
            const [warehouses, products] = await Promise.all([Api.warehouses(), Api.products()]);
            this.warehouses = Array.isArray(warehouses) ? warehouses : [];
            this.products = Array.isArray(products) ? products : [];
            this.render();
        } catch (error) {
            console.error('[WarehouseManagerPage]', error);
            toast(error?.message || this.tr('warehouse.manager.load_error', 'Erreur de chargement des magasins.'), 'error');
        }
    },

    render() {
        const grid = document.querySelector('#pgWarehouseManager .warehouse-manager-grid');
        if (!grid) return;
        if (!this.warehouses.length) {
            grid.innerHTML = `<div class="crud-mobile-empty"><strong>${this.esc(this.tr('warehouse.manager.empty_title', 'Aucun magasin'))}</strong><span>${this.esc(this.tr('warehouse.manager.empty_text', 'Créez le premier magasin pour organiser les stocks.'))}</span></div>`;
            return;
        }
        grid.innerHTML = this.warehouses.map((warehouse) => this.renderWarehouseCard(warehouse)).join('');
        if (typeof window.renderIcons === 'function') window.renderIcons();
    },

    renderWarehouseCard(warehouse) {
        const categories = this.asArray(warehouse.categories);
        const productsInWarehouse = this.products.filter((product) => {
            const allowed = this.asArray(product.allowedWarehouses).map(String);
            return allowed.includes(String(warehouse.id)) || String(product.defaultWarehouse || '') === String(warehouse.id);
        });
        const name = this.esc(warehouse.name || `#${warehouse.id}`);
        const address = warehouse.address || this.tr('warehouse.manager.not_provided', 'Non renseigné');
        const contact = warehouse.contact || this.tr('warehouse.manager.not_provided', 'Non renseigné');
        const capacity = warehouse.capacity == null || warehouse.capacity === ''
            ? this.tr('warehouse.manager.not_provided', 'Non renseignée')
            : (window.Locale ? window.Locale.formatNumber(warehouse.capacity) : String(warehouse.capacity));
        const editLabel = this.tr('warehouse.manager.edit', 'Modifier le magasin');
        const addLabel = this.tr('warehouse.manager.add_category', 'Ajouter');
        const removeLabel = this.tr('warehouse.manager.remove_category', 'Retirer {category}', { category: '' });
        return `
            <article class="warehouse-card" data-warehouse-id="${this.esc(warehouse.id)}">
                <div class="warehouse-header">
                    <div class="warehouse-name">${name}</div>
                    <button type="button" class="btn btn-sm btn-secondary" data-wm-action="edit" data-warehouse-id="${this.esc(warehouse.id)}" title="${this.esc(editLabel)}" aria-label="${this.esc(editLabel)}">${Icons.edit}</button>
                </div>
                <div class="warehouse-details">
                    <div class="warehouse-detail"><span class="warehouse-detail-label">${this.esc(this.tr('warehouse.manager.address', 'Adresse'))}</span><span class="warehouse-detail-value">${this.esc(address)}</span></div>
                    <div class="warehouse-detail"><span class="warehouse-detail-label">${this.esc(this.tr('warehouse.manager.contact', 'Contact'))}</span><span class="warehouse-detail-value">${this.esc(contact)}</span></div>
                    <div class="warehouse-detail"><span class="warehouse-detail-label">${this.esc(this.tr('warehouse.manager.capacity', 'Capacité maximale'))}</span><span class="warehouse-detail-value">${this.esc(capacity)}</span></div>
                </div>
                <div class="warehouse-stats" aria-label="${this.esc(this.tr('warehouse.manager.indicators', 'Indicateurs du magasin'))}">
                    <div class="warehouse-stat"><div class="warehouse-stat-value">${productsInWarehouse.length}</div><div class="warehouse-stat-label">${this.esc(this.tr('warehouse.manager.products', 'Produits'))}</div></div>
                    <div class="warehouse-stat"><div class="warehouse-stat-value">${categories.length}</div><div class="warehouse-stat-label">${this.esc(this.tr('warehouse.manager.categories', 'Catégories'))}</div></div>
                </div>
                <div class="warehouse-categories">
                    <div class="warehouse-categories-header">
                        <div class="warehouse-categories-title">${this.esc(this.tr('warehouse.manager.categories', 'Catégories'))}</div>
                        <button type="button" class="btn btn-sm btn-primary" data-wm-action="add-category" data-warehouse-id="${this.esc(warehouse.id)}"><span data-icon="plus"></span> ${this.esc(addLabel)}</button>
                    </div>
                    <div class="category-list" id="categoryList${this.esc(warehouse.id)}">
                        ${categories.length ? categories.map((category) => `
                            <span class="category-tag">
                                ${this.esc(category)}
                                <button type="button" class="category-tag-remove" data-wm-action="remove-category" data-warehouse-id="${this.esc(warehouse.id)}" data-category="${this.esc(category)}" title="${this.esc(removeLabel.trim() + ' ' + category)}" aria-label="${this.esc(removeLabel.trim() + ' ' + category)}">×</button>
                            </span>`).join('') : `<span class="category-empty">${this.esc(this.tr('warehouse.manager.no_categories', 'Aucune catégorie'))}</span>`}
                    </div>
                </div>
            </article>`;
    },

    confirmAction(title, message, confirmLabel = null) {
        return new Promise((resolve) => {
            let settled = false;
            const finish = (value) => {
                if (settled) return;
                settled = true;
                Modal.close();
                resolve(value);
            };
            Modal.show(title, `<p class="crud-confirm-message">${this.esc(message)}</p>`, [
                { label: this.tr('warehouse.manager.cancel', 'Annuler'), cls: 'btn-secondary', onclick: () => finish(false) },
                { label: confirmLabel || this.tr('warehouse.manager.confirm', 'Confirmer'), cls: 'btn-danger', onclick: () => finish(true) }
            ], 'warning');
            Modal.onClose?.(() => { if (!settled) resolve(false); });
        });
    },

    openCategoryModal(warehouseId) {
        const warehouse = this.warehouses.find((item) => String(item.id) === String(warehouseId));
        if (!warehouse) return;
        const categories = this.asArray(warehouse.categories);
        const countText = categories.length
            ? this.tr('warehouse.manager.existing_categories', '{count} catégorie(s) existe(nt) déjà dans ce magasin.', { count: categories.length })
            : this.tr('warehouse.manager.no_categories_defined', 'Aucune catégorie n’est encore définie.');
        Modal.show(
            this.tr('warehouse.manager.add_category_title', 'Ajouter une catégorie — {warehouse}', { warehouse: warehouse.name }),
            `<label class="lbl" for="wmCategoryName">${this.esc(this.tr('warehouse.manager.category_name', 'Nom de la catégorie'))} *</label>
             <input type="text" class="inp" id="wmCategoryName" maxlength="120" autocomplete="off" placeholder="${this.esc(this.tr('warehouse.manager.category_placeholder', 'Ex. Signalisation verticale'))}">
             <p class="text-muted" style="margin-top:8px">${this.esc(countText)}</p>`,
            [
                { label: this.tr('warehouse.manager.cancel', 'Annuler'), cls: 'btn-secondary', onclick: () => Modal.close() },
                { label: this.tr('warehouse.manager.add', 'Ajouter'), cls: 'btn-primary', onclick: () => this.saveCategory(warehouseId) }
            ],
            'info'
        );
        window.setTimeout(() => document.getElementById('wmCategoryName')?.focus(), 0);
    },

    async saveCategory(warehouseId) {
        const input = document.getElementById('wmCategoryName');
        const category = input?.value?.trim() || '';
        if (!category) {
            input?.focus();
            toast(this.tr('warehouse.manager.category_required', 'Nom de catégorie obligatoire.'), 'error');
            return;
        }
        const warehouse = this.warehouses.find((item) => String(item.id) === String(warehouseId));
        if (this.asArray(warehouse?.categories).some((item) => String(item).toLowerCase() === category.toLowerCase())) {
            input?.focus();
            toast(this.tr('warehouse.manager.category_exists', 'Cette catégorie existe déjà dans ce magasin.'), 'warning');
            return;
        }
        try {
            await Api.warehouseCategoryAdd({ warehouseId, category });
            toast(this.tr('warehouse.manager.category_added', 'Catégorie ajoutée.'), 'success');
            Modal.close();
            await this.load();
        } catch (error) {
            toast(error?.message || this.tr('warehouse.manager.category_add_error', 'Erreur lors de l’ajout.'), 'error');
        }
    },

    async removeCategory(warehouseId, category) {
        const warehouse = this.warehouses.find((item) => String(item.id) === String(warehouseId));
        if (!warehouse || !category) return;
        const accepted = await this.confirmAction(
            this.tr('warehouse.manager.remove_category_title', 'Retirer la catégorie'),
            this.tr('warehouse.manager.remove_category_question', 'Retirer « {category} » du magasin « {warehouse} » ? Les produits conserveront leur libellé actuel.', { category, warehouse: warehouse.name }),
            this.tr('warehouse.manager.remove', 'Retirer')
        );
        if (!accepted) return;
        try {
            await Api.warehouseCategoryDel({ warehouseId, category });
            toast(this.tr('warehouse.manager.category_removed', 'Catégorie retirée.'), 'success');
            await this.load();
        } catch (error) {
            toast(error?.message || this.tr('warehouse.manager.category_remove_error', 'Erreur lors du retrait.'), 'error');
        }
    },

    openWarehouseModal(id) {
        const warehouse = id ? this.warehouses.find((item) => String(item.id) === String(id)) : null;
        const isEdit = !!warehouse;
        Modal.show(
            isEdit ? this.tr('warehouse.manager.edit_title', 'Modifier le magasin') : this.tr('warehouse.manager.new_title', 'Nouveau magasin'),
            `<label class="lbl" for="whName">${this.esc(this.tr('warehouse.manager.name', 'Nom'))} *</label>
             <input type="text" class="inp" id="whName" maxlength="120" value="${this.esc(warehouse?.name || '')}" placeholder="${this.esc(this.tr('warehouse.manager.name_placeholder', 'Ex. Atelier principal'))}">
             <label class="lbl" for="whAddress">${this.esc(this.tr('warehouse.manager.address', 'Adresse'))}</label>
             <input type="text" class="inp" id="whAddress" maxlength="240" value="${this.esc(warehouse?.address || '')}" placeholder="${this.esc(this.tr('warehouse.manager.address_placeholder', 'Adresse complète'))}">
             <label class="lbl" for="whCapacity">${this.esc(this.tr('warehouse.manager.capacity', 'Capacité maximale'))}</label>
             <input type="number" class="inp" id="whCapacity" min="0" step="1" value="${this.esc(warehouse?.capacity ?? '')}" inputmode="numeric" placeholder="${this.esc(this.tr('warehouse.manager.optional', 'Optionnel'))}">
             <label class="lbl" for="whContact">${this.esc(this.tr('warehouse.manager.contact', 'Contact'))}</label>
             <input type="text" class="inp" id="whContact" maxlength="160" value="${this.esc(warehouse?.contact || '')}" placeholder="${this.esc(this.tr('warehouse.manager.contact_placeholder', 'Responsable du magasin'))}">
             <label class="lbl" for="whNotes">${this.esc(this.tr('warehouse.manager.notes', 'Notes'))}</label>
             <textarea class="inp" id="whNotes" maxlength="1000" rows="3">${this.esc(warehouse?.notes || '')}</textarea>`,
            [
                { label: this.tr('warehouse.manager.cancel', 'Annuler'), cls: 'btn-secondary', onclick: () => Modal.close() },
                { label: isEdit ? this.tr('warehouse.manager.save', 'Enregistrer') : this.tr('warehouse.manager.create', 'Créer'), cls: 'btn-primary', onclick: () => this.saveWarehouse(warehouse?.id || null) },
                ...(isEdit ? [{ label: this.tr('warehouse.manager.delete', 'Supprimer'), cls: 'btn-danger', onclick: () => this.deleteWarehouse(warehouse.id) }] : [])
            ],
            isEdit ? 'info' : 'success'
        );
        window.setTimeout(() => document.getElementById('whName')?.focus(), 0);
    },

    async saveWarehouse(id) {
        const nameInput = document.getElementById('whName');
        const name = nameInput?.value?.trim() || '';
        if (!name) {
            nameInput?.focus();
            toast(this.tr('warehouse.manager.name_required', 'Nom obligatoire.'), 'error');
            return;
        }
        const capacityValue = document.getElementById('whCapacity')?.value ?? '';
        const payload = {
            name,
            address: document.getElementById('whAddress')?.value?.trim() || '',
            capacity: capacityValue === '' ? null : Number(capacityValue),
            contact: document.getElementById('whContact')?.value?.trim() || '',
            notes: document.getElementById('whNotes')?.value?.trim() || ''
        };
        if (id) payload.id = id;
        try {
            if (id) await Api.warehouseEdit(payload);
            else await Api.warehouseAdd(payload);
            toast(id ? this.tr('warehouse.manager.updated', 'Magasin mis à jour.') : this.tr('warehouse.manager.created', 'Magasin créé.'), 'success');
            Modal.close();
            await this.load();
        } catch (error) {
            toast(error?.message || this.tr('warehouse.manager.save_error', 'Erreur lors de l’enregistrement.'), 'error');
        }
    },

    dependencyLabel(key) {
        const labels = {
            products: ['warehouse.manager.dep_products', 'Produits'],
            stock: ['warehouse.manager.dep_stock', 'Lignes de stock'],
            movements: ['warehouse.manager.dep_movements', 'Mouvements'],
            inventories: ['warehouse.manager.dep_inventories', 'Inventaires'],
            orders: ['warehouse.manager.dep_orders', 'Commandes'],
            locations: ['warehouse.manager.dep_locations', 'Emplacements'],
            plans: ['warehouse.manager.dep_plans', 'Plans'],
            alerts: ['warehouse.manager.dep_alerts', 'Alertes'],
            reservations: ['warehouse.manager.dep_reservations', 'Réservations'],
            users: ['warehouse.manager.dep_users', 'Utilisateurs'],
            ldapMappings: ['warehouse.manager.dep_ldap', 'Mappings LDAP']
        };
        const [translationKey, fallback] = labels[key] || [key, key];
        return this.tr(translationKey, fallback);
    },

    showDeleteBlocked(warehouse, dependencies) {
        const items = Object.entries(dependencies || {})
            .filter(([, count]) => Number(count) > 0)
            .map(([key, count]) => `<li><span>${this.esc(this.dependencyLabel(key))}</span><strong>${this.esc(count)}</strong></li>`)
            .join('');
        Modal.show(
            this.tr('warehouse.manager.delete_blocked_title', 'Suppression impossible'),
            `<p>${this.esc(this.tr('warehouse.manager.delete_blocked_text', 'Le magasin « {warehouse} » est encore utilisé. Réaffectez les éléments ci-dessous avant de le supprimer.', { warehouse: warehouse.name }))}</p><ul class="warehouse-delete-dependencies">${items}</ul>`,
            [{ label: this.tr('warehouse.manager.close', 'Fermer'), cls: 'btn-primary', onclick: () => Modal.close() }],
            'warning'
        );
    },

    async deleteWarehouse(id) {
        const warehouse = this.warehouses.find((item) => String(item.id) === String(id));
        if (!warehouse) return;
        const productsCount = this.products.filter((product) => {
            const allowed = this.asArray(product.allowedWarehouses).map(String);
            return allowed.includes(String(id)) || String(product.defaultWarehouse || '') === String(id);
        }).length;
        const productNotice = productsCount
            ? ' ' + this.tr('warehouse.manager.delete_products_notice', '{count} produit(s) sont actuellement rattachés à ce magasin.', { count: productsCount })
            : '';
        const accepted = await this.confirmAction(
            this.tr('warehouse.manager.delete_title', 'Supprimer le magasin'),
            this.tr('warehouse.manager.delete_question', 'Supprimer définitivement « {warehouse} » ?', { warehouse: warehouse.name }) + productNotice,
            this.tr('warehouse.manager.delete', 'Supprimer')
        );
        if (!accepted) return;
        try {
            await Api.warehouseDel(id);
            toast(this.tr('warehouse.manager.deleted', 'Magasin supprimé.'), 'success');
            await this.load();
        } catch (error) {
            if (error?.status === 409 && error?.payload?.dependencies) {
                this.showDeleteBlocked(warehouse, error.payload.dependencies);
                return;
            }
            toast(error?.message || this.tr('warehouse.manager.delete_error', 'Erreur lors de la suppression.'), 'error');
        }
    }
};

if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', () => {
        if (window.SM_PAGE === 'warehouse-manager') WarehouseManagerPage.init();
    }, { once: true });
} else if (window.SM_PAGE === 'warehouse-manager') {
    WarehouseManagerPage.init();
}
