'use strict';

class ScriptStyleLoader {
    constructor(config) {
        this.loadedScripts = new Set();
        this.loadedStyles = new Set();
        this.scriptPromises = new Map();
        this.stylePromises = new Map();
        this.config = Object.assign({ cdnPath: "https://cdn.ai12z.net/assets/bot", surveyCDNPath: "https://cdn.ai12z.net/pkg/surveyjs", customStyles: ["https://cdn.jsdelivr.net/npm/@highlightjs/cdn-assets@11.11.1/styles/default.min.css"], customScripts: [] }, config);
    }
    /**
     * Load a single script
     */
    loadScript(config) {
        const scriptConfig = typeof config === "string" ? { src: config } : config;
        const { src } = scriptConfig;
        // Return existing promise if script is already being loaded
        if (this.scriptPromises.has(src)) {
            return this.scriptPromises.get(src);
        }
        // Return resolved promise if script is already loaded
        if (this.loadedScripts.has(src) || this.isScriptLoaded(src)) {
            return Promise.resolve();
        }
        const promise = new Promise((resolve, reject) => {
            var _a, _b, _c;
            const script = document.createElement("script");
            script.src = src;
            script.async = (_a = scriptConfig.async) !== null && _a !== void 0 ? _a : false;
            script.defer = (_b = scriptConfig.defer) !== null && _b !== void 0 ? _b : false;
            script.type = (_c = scriptConfig.type) !== null && _c !== void 0 ? _c : "text/javascript";
            script.onload = () => {
                this.loadedScripts.add(src);
                this.scriptPromises.delete(src);
                if (scriptConfig.onLoad) {
                    scriptConfig.onLoad();
                }
                // console.log(`✅ Script loaded: ${src}`)
                resolve();
            };
            script.onerror = error => {
                this.scriptPromises.delete(src);
                const errorObj = new Error(`Failed to load script: ${src}`);
                if (scriptConfig.onError) {
                    scriptConfig.onError(errorObj);
                }
                console.error(`❌ Script failed to load: ${src}`, error);
                reject(errorObj);
            };
            // Append to shadow root if available, otherwise document head
            if (this.config.shadowRoot) {
                this.config.shadowRoot.appendChild(script);
            }
            else {
                document.head.appendChild(script);
            }
        });
        this.scriptPromises.set(src, promise);
        return promise;
    }
    /**
     * Load a single style
     */
    loadStyle(config, isTheme = false) {
        const styleConfig = typeof config === "string" ? { href: config } : config;
        const { href } = styleConfig;
        // Return existing promise if style is already being loaded
        if (this.stylePromises.has(href)) {
            return this.stylePromises.get(href);
        }
        // Return resolved promise if style is already loaded
        if (this.loadedStyles.has(href) || this.isStyleLoaded(href)) {
            return Promise.resolve();
        }
        const promise = new Promise((resolve, reject) => {
            var _a;
            const link = document.createElement("link");
            link.rel = "stylesheet";
            link.href = href;
            link.media = (_a = styleConfig.media) !== null && _a !== void 0 ? _a : "all";
            link.onload = () => {
                this.loadedStyles.add(href);
                this.stylePromises.delete(href);
                if (styleConfig.onLoad) {
                    styleConfig.onLoad();
                }
                // console.log(`✅ Style loaded: ${href}`)
                resolve();
            };
            link.onerror = error => {
                this.stylePromises.delete(href);
                const errorObj = new Error(`Failed to load style: ${href}`);
                if (styleConfig.onError) {
                    styleConfig.onError(errorObj);
                }
                console.error(`❌ Style failed to load: ${href}`, error);
                reject(errorObj);
            };
            // Append to shadow root if available, otherwise document head
            if (this.config.shadowRoot && !isTheme) {
                this.config.shadowRoot.appendChild(link);
            }
            else {
                document.head.appendChild(link);
            }
        });
        this.stylePromises.set(href, promise);
        return promise;
    }
    /**
     * Load multiple scripts sequentially
     */
    async loadScriptsSequentially(scripts) {
        // console.log(`🔄 Loading ${scripts.length} scripts sequentially...`)
        for (const script of scripts) {
            try {
                await this.loadScript(script);
            }
            catch (error) {
                console.error("Failed to load script in sequence:", error);
                throw error;
            }
        }
        // console.log("✅ All scripts loaded successfully")
    }
    /**
     * Load multiple scripts in parallel
     */
    async loadScriptsParallel(scripts) {
        // console.log(`🔄 Loading ${scripts.length} scripts in parallel...`)
        try {
            await Promise.all(scripts.map(script => this.loadScript(script)));
            // console.log("✅ All scripts loaded successfully")
        }
        catch (error) {
            console.error("Failed to load scripts in parallel:", error);
            throw error;
        }
    }
    /**
     * Load multiple styles in parallel
     */
    async loadStyles(styles, isTheme = false) {
        // console.log(`🔄 Loading ${styles.length} styles...`)
        try {
            await Promise.all(styles.map(style => this.loadStyle(style, isTheme)));
            //   console.log("✅ All styles loaded successfully")
        }
        catch (error) {
            console.error("Failed to load styles:", error);
            throw error;
        }
    }
    /**
     * Load all Survey.js dependencies
     */
    async loadSurveyDependencies() {
        const surveyScripts = [
            `${this.config.surveyCDNPath}/survey-core@2.3.4/survey.core.min.js`,
            `${this.config.surveyCDNPath}/survey-core@2.3.4/survey.i18n.min.js`,
            `${this.config.surveyCDNPath}/survey-core@2.3.4/themes/index.min.js`,
            `${this.config.surveyCDNPath}/survey-js-ui@2.3.4/survey-js-ui.min.js`,
        ];
        const surveyStyles = [`${this.config.surveyCDNPath}/survey-core@2.3.4/survey-core.min.css`];
        await this.loadStyles(surveyStyles);
        // console.log("🔄 Loading Survey.js dependencies...")
        await this.loadScriptsSequentially(surveyScripts);
        // console.log("✅ Survey.js dependencies loaded")
    }
    /**
     * Load all default styles and scripts for ai12z-bot
     */
    async loadBotAssets() {
        // console.log("🔄 Loading bot assets...")
        try {
            // Load styles and scripts in parallel
            await Promise.all([
                this.loadStyles(this.config.customStyles || []),
                // this.loadSurveyDependencies()
            ]);
            //   console.log("✅ All bot assets loaded successfully")
        }
        catch (error) {
            console.error("❌ Failed to load bot assets:", error);
            throw error;
        }
    }
    /**
     * Load custom theme and assets based on bot settings
     */
    async loadBotTheme(botSettings) {
        var _a, _b;
        const themesToLoad = [];
        const stylesToLoad = [];
        const scriptsToLoad = [];
        // Add theme CSS
        if (botSettings.theme) {
            if (botSettings.theme !== "custom") {
                themesToLoad.push(`${this.config.cdnPath}/v2/themes/theme-${botSettings.theme}.css`);
            }
            else if (botSettings.customTheme) {
                themesToLoad.push(botSettings.customTheme);
            }
        }
        else {
            themesToLoad.push(`${this.config.cdnPath}/v2/themes/theme-default.css`);
        }
        // Add welcome styles
        if ((_a = botSettings.welcome) === null || _a === void 0 ? void 0 : _a.styles) {
            stylesToLoad.push(botSettings.welcome.styles);
        }
        // Add custom CSS
        if (botSettings.customCSS) {
            stylesToLoad.push(botSettings.customCSS);
        }
        // Add welcome scripts
        if ((_b = botSettings.welcome) === null || _b === void 0 ? void 0 : _b.scripts) {
            scriptsToLoad.push({
                src: botSettings.welcome.scripts,
                type: "text/javascript",
            });
        }
        // Add custom JS
        if (botSettings.customJS) {
            scriptsToLoad.push({
                src: botSettings.customJS,
                type: "text/javascript",
            });
        }
        // Load all theme assets
        await Promise.all([
            themesToLoad.length > 0 ? this.loadStyles(themesToLoad, true) : Promise.resolve(),
            stylesToLoad.length > 0 ? this.loadStyles(stylesToLoad, false) : Promise.resolve(),
            scriptsToLoad.length > 0 ? this.loadScriptsParallel(scriptsToLoad) : Promise.resolve(),
        ]);
        // console.log("✅ Bot theme loaded successfully")
    }
    /**
     * Check if script is already loaded in DOM
     */
    isScriptLoaded(src) {
        var _a;
        return !!(document.querySelector(`script[src="${src}"]`) || ((_a = this.config.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector(`script[src="${src}"]`)));
    }
    /**
     * Check if style is already loaded in DOM
     */
    isStyleLoaded(href) {
        var _a;
        return !!(document.querySelector(`link[href="${href}"]`) || ((_a = this.config.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector(`link[href="${href}"]`)));
    }
    /**
     * Get loading status
     */
    getLoadingStatus() {
        return {
            loadedScripts: Array.from(this.loadedScripts),
            loadedStyles: Array.from(this.loadedStyles),
            pendingScripts: Array.from(this.scriptPromises.keys()),
            pendingStyles: Array.from(this.stylePromises.keys()),
        };
    }
    /**
     * Clear all cached promises and loaded assets
     */
    reset() {
        this.loadedScripts.clear();
        this.loadedStyles.clear();
        this.scriptPromises.clear();
        this.stylePromises.clear();
    }
}
// ✅ Factory function for easy usage
function createScriptStyleLoader(config) {
    return new ScriptStyleLoader(config);
}

exports.createScriptStyleLoader = createScriptStyleLoader;
