// src/core/registries.js

/** 
 * لایه اول: مدیریت تنظیمات و متادیتای تب‌ها
 */
export class TabConfigRegistry {
    constructor() {
        this.configs = new Map();
    }

    // ثبت یک کانفیگ تب جدید
    register(config) {
        if (!config.key) throw new Error("TabConfig must have a 'key'");
        this.configs.set(config.key, config);
    }

    // دریافت یک کانفیگ تب با کلید مشخص
    get(key) {
        return this.configs.get(key);
    }

    // دریافت تمام کانفیگ‌ها
    getAll() {
        return Array.from(this.configs.values());
    }

    // دریافت تب‌های ثابت (fixed) مرتب شده بر اساس sortOrder
    getDefaults() {
        return this.getAll()
            .filter(config => config.fixed)
            .sort((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0));
    }
}

/** 
 * لایه دوم: رجیستری کلاس‌های View
 */
export class ViewRegistry {
    constructor() {
        // نگهداری کلاس ویوها بر اساس کلید تب
        this.byTabKey = new Map();

        // نگهداری کلاس ویوها بر اساس ترکیب module:view
        this.byModuleView = new Map();
    }

    // رجیستر کلاس ویو بر اساس کلید تب
    registerByTabKey(tabKey, ViewClass) {
        this.byTabKey.set(tabKey, ViewClass);
    }

    // رجیستر کلاس ویو بر اساس ترکیب module:view
    registerByModuleView(module, view, ViewClass) {
        this.byModuleView.set(`${module}:${view}`, ViewClass);
    }

    // دریافت کلاس ویو بر اساس کلید تب
    getByTabKey(tabKey) {
        return this.byTabKey.get(tabKey);
    }

    // دریافت کلاس ویو بر اساس ترکیب module:view
    getByModuleView(module, view) {
        return this.byModuleView.get(`${module}:${view}`);
    }

    /**
     * افزودن متد register برای سازگاری (ایجاد پلی به registerByTabKey)
     */
    register(tabKey, ViewClass) {
        // معادل registerByTabKey
        this.registerByTabKey(tabKey, ViewClass);
    }
}

/**
 * کلاس کمکی برای پیدا کردن View مربوطه بر اساس کلید تب و کانفیگ مربوط
 * 
 * - قابلیت resolve sync (کلاس view را برگشت می‌دهد)
 * - در صورت نیاز می‌توان متد resolve را async کرد تا lazy loading پشتیبانی شود.
 */
export class ViewResolver {
    constructor(viewRegistry) {
        this.registry = viewRegistry;
        this._cache = new Map();  // کش برای بهبود عملکرد و جلوگیری از resolveهای مکرر
    }

    /**
     * Resolve view class synchronously or asynchronously if lazy loader function
     * 
     * @param {string} tabKey کلید تب
     * @param {object} config کانفیگ تب (اختیاری) برای resolve بر اساس module:view
     * @returns {Promise<Class|Function>} کلاس ویو
     */
    async resolve(tabKey, config) {
        if (!tabKey) {
            throw new Error("ViewResolver: tabKey is required");
        }

        // کش را چک می‌کنیم
        if (this._cache.has(tabKey)) {
            return this._cache.get(tabKey);
        }

        let ViewClassOrLoader = this.registry.getByTabKey(tabKey);

        if (!ViewClassOrLoader && config && config.module && config.view) {
            ViewClassOrLoader = this.registry.getByModuleView(config.module, config.view);
        }

        if (!ViewClassOrLoader) {
            throw new Error(`ViewResolver: view not registered for key "${tabKey}"`);
        }

        let ViewClass;

        // اگر loader تابع است (فرض lazy loader async)
        if (typeof ViewClassOrLoader === "function" && !ViewClassOrLoader.prototype) {
            const mod = await ViewClassOrLoader();
            ViewClass = mod.default || mod;
        } else {
            ViewClass = ViewClassOrLoader;
        }

        this._cache.set(tabKey, ViewClass);

        return ViewClass;
    }
}

// ساخت و اکسپورت نمونه‌های Singleton برای استفاده در کل برنامه
export const tabConfigRegistry = new TabConfigRegistry();
export const viewRegistry = new ViewRegistry();
export const viewResolver = new ViewResolver(viewRegistry);
