export default class TabManager {
    constructor({
        eventBus,
        store,
        api = null,      // ✅ اضافه شود
        cache = null,    // ✅ اگر استفاده می‌کنی
        auth = null,     // ✅ اگر استفاده می‌کنی
        tabbarSelector = '#acc-tabbar',
        contentSelector = '#acc-tab-content',
        tabConfigRegistry,
        viewResolver
    }) {
        if (!tabConfigRegistry) throw new Error('TabManager: tabConfigRegistry is required');
        if (!viewResolver) throw new Error('TabManager: viewResolver is required');

        this.eventBus = eventBus;
        this.store = store;

        this.api = api;      // ✅ اینجا دیگر خطا ندارد
        this.cache = cache;
        this.auth = auth;

        this.tabConfigRegistry = tabConfigRegistry;
        this.viewResolver = viewResolver;

        this.tabs = new Map();
        this.activeTabId = null;

        this.tabsContainer = document.querySelector(tabbarSelector);
        this.contentContainer = document.querySelector(contentSelector);

        this.boundEvents = [];
        this.boundBusEvents = [];

        // ERP-grade view cache
        this.viewCache = new Map();

        // Persistence
        this.enablePersistence = true;
        this.storageKey = 'acc_tabs_state';

        this.restoredTabs = null;
        this._restoreTabsFromStorage();

        if (!this.tabsContainer || !this.contentContainer) {
            console.warn('TabManager: tab containers not found.');
        }

        this._registerGlobalEvents();

        if (this.restoredTabs) {
            this._hydrateRestoredTabs();
        }
    }


    /* =========================
       Global Events
    ========================== */

    _registerGlobalEvents() {
        const closeHandler = (id) => this.closeTab(id);
        const refreshHandler = () => {
            if (this.activeTabId) this.refreshTab(this.activeTabId);
        };

        const userSelectedHandler = ({ tabId, user, userId }) => {
            if (!tabId) return;

            const tab = this.tabs.get(tabId);
            if (!tab) return;

            const finalId = userId || user?.id || null;
            tab.userContext = user
                ? { id: finalId, username: user.username, fullname: user.fullname }
                : { id: finalId };

            this._saveTabsToStorage();
            this.refreshTab(tabId);
        };

        this.eventBus.on('tabs:closeById', closeHandler);
        this.eventBus.on('tabs:refreshActive', refreshHandler);
        this.eventBus.on('modal:userSelected', userSelectedHandler);

        this.boundBusEvents.push(
            ['tabs:closeById', closeHandler],
            ['tabs:refreshActive', refreshHandler],
            ['modal:userSelected', userSelectedHandler]
        );
    }

    /* =========================
       Open Tab API
    ========================== */

    openTab(ViewClassOrKey, options = {}) {
        let ViewClass = null;
        let tabConfig = {};

        // ✅ Case 1: openTab('users')
        if (typeof ViewClassOrKey === 'string') {
            const key = ViewClassOrKey;
            tabConfig = this.tabConfigRegistry.get(key) || {};

            // ── بررسی مجوز قبل از باز کردن تب ──
            try {
                // import lazy تا چرخه نداشته باشد
                const acl = window.acl;
                if (acl && acl._loaded) {
                    const reqPerm = tabConfig.requiredPermission ||
                                    acl.menus?.find(m => m.route === key)?.required_permission;
                    if (reqPerm && !acl.can(reqPerm)) {
                        this._showDeniedToast(`دسترسی به «${tabConfig.title || key}» مجاز نیست`);
                        return;
                    }
                }
            } catch (e) { /* ignore */ }

            ViewClass = this.viewResolver.resolve(key, tabConfig);

            if (!ViewClass) {
                console.error(`TabManager: View not found for key "${key}"`);
                return;
            }
        }

        // ✅ Case 2: openTab(ViewClass)
        if (typeof ViewClassOrKey === 'function') {
            ViewClass = ViewClassOrKey;
        }

        if (!ViewClass) {
            console.warn('TabManager.openTab: invalid ViewClass');
            return;
        }

        const title =
            options.title ||
            tabConfig.title ||
            ViewClass.title ||
            ViewClass.viewTitle ||
            ViewClass.name ||
            'تب جدید';

        const tabKey =
            options.key ||
            tabConfig.key ||
            ViewClass.tabKey ||
            ViewClass.name;

        const existing = [...this.tabs.values()].find(t => t.key === tabKey);
        if (existing) {
            this.activateTab(existing.id);
            return existing;
        }

        const tabId = this._generateTabId();

        const tab = {
            id: tabId,
            key: tabKey,
            title,
            ViewClass,
            view: null,
            params: options.params || tabConfig.params || {},
            userContext: options.userContext || null,
            api: options.api || this.api || null,
            fixed: options.fixed ?? tabConfig.fixed ?? false,

            // ✅ Persistence control
            persist: options.persist ?? tabConfig.persist ?? true,

            // ✅ optional future-safe config holder
            config: tabConfig
        };

        this.tabs.set(tabId, tab);

        this._renderTabHeader(tab);
        this.activateTab(tabId);

        if (!options.silent) this._saveTabsToStorage();

        return tab;
    }

    _generateTabId() {
        return 'tab_' + Math.random().toString(36).slice(2, 11);
    }

    /* =========================
       Tab Management
    ========================== */

    async activateTab(tabId) {
        if (!this.tabs.has(tabId)) return;

        this.activeTabId = tabId;
        const tab = this.tabs.get(tabId);

        this._updateTabHeaders();

        // 👇 همه‌ی contentهای تب را hide کن، بعد فقط تب فعال را render/show کن
        if (this.contentContainer) {
            [...this.contentContainer.children].forEach(child => {
                // فقط divهایی که برای تب‌ها ساخته‌ایم
                if (child.dataset && child.dataset.tabContentId) {
                    child.style.display = 'none';
                }
            });
        }

        await this._renderView(tab);
        this._saveTabsToStorage();
    }

    closeTab(tabId) {
        const tab = this.tabs.get(tabId);
        if (!tab || tab.fixed) return;

        // ۱. destroy کردن view (اگر متد destroy داشته باشد)
        tab.view?.destroy?.();

        // ۲. حذف از cache
        this.viewCache.delete(tabId);

        // ۳. حذف header تب
        this.tabsContainer
            ?.querySelector(`[data-tab-id="${tabId}"]`)
            ?.remove();

        // ۴. حذف خود tab از Map
        this.tabs.delete(tabId);

        // ۵. حذف container محتوای این تب (اگر وجود دارد)
        const tabContentEl = this.contentContainer
            ?.querySelector(`[data-tab-content-id="${tabId}"]`);
        tabContentEl?.remove();

        // ۶. اگر تب بسته‌شده، تب فعال بوده است → تب دیگری را فعال کن
        if (this.activeTabId === tabId) {
            const remaining = [...this.tabs.values()];
            this.activeTabId = remaining.length ? remaining.at(-1).id : null;

            if (this.activeTabId) {
                // تب آخر باقیمانده را فعال کن
                this.activateTab(this.activeTabId);
            } else if (this.contentContainer) {
                // دیگر هیچ تبی نداریم → کل content خالی شود
                this.contentContainer.innerHTML = '';
            }
        }

        // ۷. آپدیت ظاهر headerها و ذخیره در storage
        this._updateTabHeaders();
        this._saveTabsToStorage();
    }


    /* =========================
       Headers
    ========================== */

    _renderTabHeader(tab) {
        const el = document.createElement('div');
        el.className = 'acc-tab';
        el.dataset.tabId = tab.id;

        // تب = فقط عنوان (بدون دکمه) — close/refresh در هدر ویو هستند
        el.innerHTML = `<span class="tab-title">${tab.title}</span>`;

        if (tab.fixed) {
            this.tabsContainer.prepend(el);
        } else {
            this.tabsContainer.appendChild(el);
        }

        el.addEventListener('click', () => this.activateTab(tab.id));

        this._updateTabHeaders();
    }

    _updateTabHeaders() {
        [...this.tabsContainer.children].forEach(el => {
            el.classList.toggle('active', el.dataset.tabId === this.activeTabId);
        });
    }

    /* =========================
       View Rendering
    ========================== */

    async _renderView(tab) {
        if (!this.contentContainer) return;

        // یک helper کوچک برای گرفتن/ساختن container این تب
        const getOrCreateTabContainer = () => {
            // سعی کن container قبلی این تب را پیدا کنی
            let el = this.contentContainer.querySelector(
                `[data-tab-content-id="${tab.id}"]`
            );

            if (!el) {
                el = document.createElement('div');
                el.dataset.tabContentId = tab.id;
                el.style.width = '100%';
                el.style.height = '100%';
                this.contentContainer.appendChild(el);
            }

            return el;
        };

        // ✅ اگر از cache هست
        if (this.viewCache.has(tab.id)) {
            const view = this.viewCache.get(tab.id);
            tab.view = view;

            const tabContainer = getOrCreateTabContainer();
            tabContainer.style.display = ''; // show

            // اگر view متد resume داشته باشد، اجازه بده خودش تصمیم بگیرد چه کند
            if (typeof view.resume === 'function') {
                return view.resume(tabContainer);
            }

            // اگر resume ندارد، ولی قبلاً container خودش را می‌شناسد، فقط ensure کن که در DOM است
            if (view.container && view.container !== tabContainer) {
                // در صورت نیاز می‌توانی اینجا content را منتقل کنی،
                // اما معمولاً render اولیه روی tabContainer انجام می‌شود
            }

            return;
        }

        // ✅ اگر ViewClass هنوز resolve نشده
        if (!tab.ViewClass) {
            tab.ViewClass = this.viewResolver.resolve(tab.key, tab.config);
        }

        // ✅ اگر Promise بود → await کن
        if (tab.ViewClass instanceof Promise) {
            tab.ViewClass = await tab.ViewClass;
        }

        // ✅ اگر ES module default export داشت
        if (tab.ViewClass?.default) {
            tab.ViewClass = tab.ViewClass.default;
        }

        if (typeof tab.ViewClass !== 'function') {
            throw new Error(`tab.ViewClass is not a constructor for tab.key=${tab.key}`);
        }

        // ✅ برای این تب یک container اختصاصی بساز/بگیر
        const tabContainer = getOrCreateTabContainer();
        tabContainer.style.display = ''; // show

        // ✅ view را با container مخصوص خودش بساز
        const view = new tab.ViewClass({
            eventBus: this.eventBus,
            store: this.store,
            tab,
            api: tab.api,
            container: tabContainer
        });

        tab.view = view;

        // render روی همـان container
        await view.render(tabContainer);

        // در cache نگه‌دار
        this.viewCache.set(tab.id, view);
    }


    async refreshTab(tabId) {
        const tab = this.tabs.get(tabId);
        if (!tab) return;

        // 1) destroy view قبلی
        try { tab.view?.destroy?.(); } catch (e) { console.warn('destroy failed', e); }

        // 2) از cache حذف کن تا render مجدد ساخته شود
        this.viewCache.delete(tabId);
        tab.view = null;

        // 3) HTML container قدیمی را پاک کن تا چیز قدیمی ته نشین نماند
        const el = this.contentContainer?.querySelector(
            `[data-tab-content-id="${tab.id}"]`
        );
        if (el) el.innerHTML = '';

        // 4) feedback بصری — چرخش آیکن
        const headerEl  = this.tabsContainer?.querySelector(`[data-tab-id="${tab.id}"]`);
        const refreshBtn = headerEl?.querySelector('.tab-refresh');
        if (refreshBtn) {
            refreshBtn.style.transition = 'transform .3s';
            refreshBtn.style.transform  = 'rotate(360deg)';
            setTimeout(() => { refreshBtn.style.transform = ''; }, 350);
        }

        // 5) render مجدد
        await this._renderView(tab);

        // 6) اگر همین تب active بود، نمایش بده
        if (this.activeTabId === tab.id && el) {
            el.style.display = '';
        }
    }

    /* =========================
       Persistence
    ========================== */

    _saveTabsToStorage() {
        if (!this.enablePersistence) return;

        localStorage.setItem(this.storageKey, JSON.stringify({
            active: this.activeTabId,
            tabs: [...this.tabs.values()]
                .filter(t => t.persist !== false)
                .map(t => ({
                    key: t.key,
                    title: t.title,
                    params: t.params,
                    userContext: t.userContext,
                    fixed: t.fixed,
                    persist: t.persist
                }))
        }));
    }

    _restoreTabsFromStorage() {
        try {
            const raw = localStorage.getItem(this.storageKey);
            if (raw) this.restoredTabs = JSON.parse(raw);
        } catch {
            console.warn('Tab restore failed');
        }
    }

    _showDeniedToast(msg) {
        const t = document.createElement('div');
        t.style.cssText = 'position:fixed;top:80px;left:24px;background:#ef4444;color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;font-weight:600;z-index:99999;box-shadow:0 4px 20px rgba(0,0,0,.2);';
        t.textContent = '🚫 ' + msg;
        document.body.appendChild(t);
        setTimeout(() => t.remove(), 3500);
    }

    _hydrateRestoredTabs() {
        const { tabs = [], active } = this.restoredTabs || {};

        tabs
            .filter(t => t.persist !== false)
            .forEach(t => {
                this.openTab(t.key, { ...t, silent: true });
            });

        if (active && this.tabs.has(active)) {
            this.activateTab(active);
        }
    }

    /* =========================
       Destroy
    ========================== */

    destroy() {
        this.boundBusEvents.forEach(([evt, fn]) => this.eventBus.off?.(evt, fn));
        this.tabs.forEach(tab => tab.view?.destroy?.());

        this.tabs.clear();
        this.viewCache.clear();
        this.activeTabId = null;

        [...this.tabsContainer.querySelectorAll('[data-tab-id]')].forEach(el => el.remove());
        this.contentContainer.innerHTML = '';
    }

    getActiveTab() {
        return this.activeTabId ? this.tabs.get(this.activeTabId) : null;
    }
}
