/**
 * SectionBase.js
 * کلاس پایه سبک برای زیربخش‌های داخلی — بدون header / user-context
 * فقط template را مستقیم داخل container می‌نویسد.
 */

import acl from "../../core/AclService.js";

export default class SectionBase {

    constructor({ eventBus, store, tab, api } = {}) {
        this.eventBus = eventBus ?? null;
        this.store    = store    ?? null;
        this.tab      = tab      ?? null;
        this.api      = api      ?? null;

        this.container = null;
        this.refs      = {};
        this.boundEvents = [];
        this.busEvents   = [];
        this.isDestroyed = false;
    }

    /* ---- Lifecycle ---- */

    async render(container) {
        if (!container) return this;
        this.container = container;

        if (typeof this.beforeRender === "function") {
            await this.beforeRender();
        }

        const html = await this.template();
        container.innerHTML = html ?? "";
        this._bindRefs();

        if (typeof this.afterRender === "function") {
            await this.afterRender();
        }

        // اعمال ACL خودکار روی DOM
        try { this.applyAclToDom(); } catch (e) { /* ignore */ }

        return this;
    }

    /* ── ACL helpers ─────────────────────────────────────── */
    can(key, scopeType = null, scopeId = null)   { return acl.can(key, scopeType, scopeId); }
    cannot(key, scopeType = null, scopeId = null){ return !acl.can(key, scopeType, scopeId); }

    applyAclToDom(root = null) {
        const scope = root || this.container;
        if (!scope) return;
        scope.querySelectorAll('[data-perm]').forEach(el => {
            const key = el.dataset.perm;
            if (!key || acl.can(key)) return;
            const mode = el.dataset.permMode || 'hide';
            if (mode === 'disable') {
                el.setAttribute('disabled', 'disabled');
                el.style.opacity = '0.5';
                el.style.cursor  = 'not-allowed';
                el.title = '🚫 دسترسی ندارید';
            } else {
                el.style.display = 'none';
            }
        });
    }

    async template() { return ""; }

    /* ---- Refs ---- */

    _bindRefs() {
        this.refs = {};
        if (!this.container) return;
        this.container.querySelectorAll("[data-ref]").forEach(el => {
            if (el.dataset.ref) this.refs[el.dataset.ref] = el;
        });
    }

    ref(name) { return this.refs[name] ?? null; }

    /* ---- DOM events ---- */

    on(element, event, handler) {
        if (!element || !event || !handler) return;
        element.addEventListener(event, handler);
        this.boundEvents.push({ element, event, handler });
    }

    /* ---- EventBus ---- */

    listen(event, handler) {
        if (!this.eventBus) return;
        const off = this.eventBus.on(event, handler);
        if (off) this.busEvents.push(off);
    }

    /* ---- Destroy ---- */

    destroy() {
        if (this.isDestroyed) return;
        this.boundEvents.forEach(({ element, event, handler }) => {
            try { element.removeEventListener(event, handler); } catch {}
        });
        this.busEvents.forEach(off => { try { if (typeof off === "function") off(); } catch {} });
        this.boundEvents = [];
        this.busEvents   = [];
        this.refs        = {};
        this.container   = null;
        this.isDestroyed = true;
    }

    /* ---- Helpers ---- */

    escape(str) {
        if (str == null) return "";
        return String(str)
            .replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
            .replace(/"/g, "&quot;")
            .replace(/'/g, "&#039;");
    }
}
