
(function () {
    var scriptFile = new File($.fileName);
    var scriptDir = scriptFile.parent.fsName.replace(/\\/g, "/");
    $.global.PRLB_SCRIPT_DIR = scriptDir;

    function labT(key, fallback) {
        if (typeof i18n !== "undefined" && i18n && typeof i18n.t === "function") {
            var translated = i18n.t(key);
            if (translated && translated !== key) {
                return translated;
            }
        }
        return fallback || key;
    }

    function labF(key, params, fallback) {
        var message = labT(key, fallback || key);
        if (!params) return message;
        for (var name in params) {
            if (params.hasOwnProperty(name)) {
                var token = "{" + name + "}";
                var value = String(params[name]);
                while (message.indexOf(token) !== -1) {
                    message = message.replace(token, value);
                }
            }
        }
        return message;
    }

    function loadLabI18n() {
        try {
            function tryLoad(relBin, relJsx) {
                var bin = new File(scriptDir + "/" + relBin);
                var jsx = new File(scriptDir + "/" + relJsx);
                if (bin.exists) {
                    $.evalFile(bin);
                    return true;
                }
                if (jsx.exists) {
                    $.evalFile(jsx);
                    return true;
                }
                return false;
            }

            tryLoad("lib/i18n/en_us.jsxbin", "lib/i18n/en_us.jsx");
            tryLoad("lib/i18n/es_hn.jsxbin", "lib/i18n/es_hn.jsx");
            tryLoad("lib/07_i18n.jsxbin", "lib/07_i18n.jsx");
            tryLoad("lib/02_settings.jsxbin", "lib/02_settings.jsx");

            if (typeof i18n !== "undefined" && i18n && typeof i18n.init === "function") {
                var uiLanguage = "en_us";
                try {
                    var prefsFile = null;
                    if (typeof settingsManager !== "undefined" && settingsManager && settingsManager.getUserPreferencesPath) {
                        prefsFile = settingsManager.getUserPreferencesPath();
                    }
                    if (prefsFile && prefsFile.exists && prefsFile.open("r")) {
                        var prefsContent = prefsFile.read();
                        prefsFile.close();
                        var langMatch = prefsContent.match(/"uiLanguage"\s*:\s*"([^"]+)"/);
                        if (langMatch && langMatch[1]) {
                            uiLanguage = String(langMatch[1]);
                        }
                    }
                } catch (langErr) { }
                i18n.init(uiLanguage);
            }
        } catch (i18nErr) { }
    }

    loadLabI18n();

    function logToFile(message) {
        try {
            function getGmt6Date() {
                var now = new Date();
                var offsetMs = -6 * 60 * 60 * 1000;
                return new Date(now.getTime() + offsetMs);
            }
            function formatGmt6Timestamp(d) {
                function pad(n) { return (n < 10) ? ("0" + n) : String(n); }
                return d.getUTCFullYear() + "-" + pad(d.getUTCMonth() + 1) + "-" + pad(d.getUTCDate()) +
                    " " + pad(d.getUTCHours()) + ":" + pad(d.getUTCMinutes()) + ":" + pad(d.getUTCSeconds()) + " GMT-06";
            }
            function sanitizeLogMessage(msg) {
                if (msg === null || msg === undefined) return "";
                try {
                    var out = String(msg);
                    if (!out || out === "null" || out === "undefined") return "";
                    var winPathRe = new RegExp("[A-Za-z]:[\\\\/][^\\r\\n]*", "g");
                    out = out.replace(winPathRe, "<PATH>");
                    var macUsersRe = new RegExp("\\\\/Users\\\\/[^\\r\\n]*", "g");
                    var macVolumesRe = new RegExp("\\\\/Volumes\\\\/[^\\r\\n]*", "g");
                    out = out.replace(macUsersRe, "<PATH>");
                    out = out.replace(macVolumesRe, "<PATH>");
                    return out;
                } catch (e) {
                    return "[Log sanitization error]";
                }
            }
            var now = getGmt6Date();
            var year = now.getUTCFullYear();
            var month = ("0" + (now.getUTCMonth() + 1)).slice(-2);
            var day = ("0" + now.getUTCDate()).slice(-2);
            var dateFolderName = year + "-" + month + "-" + day;

            var dateFolder = null;
            if (typeof settingsManager !== "undefined" &&
                settingsManager &&
                typeof settingsManager.getProofLabLogsDir === "function") {
                dateFolder = settingsManager.getProofLabLogsDir();
            }

            if (!dateFolder) {
                return;
            }

            var logFileName = dateFolderName + "_laboratory.txt";

            var logFile = new File(dateFolder.fsName + "/" + logFileName);
            logFile.encoding = "UTF-8";

            if (logFile.open("a")) {
                var timestamp = formatGmt6Timestamp(now);
                logFile.writeln("\n\n================================================================================");
                logFile.writeln("LABORATORY EXECUTION LOG");
                logFile.writeln("Time: " + timestamp);
                logFile.writeln("================================================================================");
                logFile.writeln("");
                if (message !== null && message !== undefined) {
                    try {
                        var sanitized = sanitizeLogMessage(message);
                        if (sanitized !== null && sanitized !== undefined) {
                            logFile.write(sanitized);
                        }
                    } catch (e) {
                        logFile.write("[Log sanitization failed: " + String(e) + "]");
                    }
                }
                logFile.writeln("");
                logFile.writeln("================================================================================");
                logFile.close();
            }
        } catch (e) {
            $.writeln("[LABORATORY][ERROR] Failed to write log: " + e.toString());
        }
    }

    try {
        if (!app.documents.length) {
            alert(labT("ui.laboratory.error.open_document_first", "Please open a document before running Laboratory."));
            return;
        }
        var doc = app.activeDocument;
        if (!doc) {
            alert(labT("ui.laboratory.error.no_active_document", "No active document."));
            return;
        }

        if (!doc.artboards || doc.artboards.length === 0) {
            alert(labT("ui.laboratory.error.no_artboards", "The document has no artboards.\n\nPlease add at least one artboard to the document before running Laboratory."));
            return;
        }

        var logMessages = [];
        logMessages.push("[START] Laboratory execution started");
        logMessages.push("[DOC] Document: " + doc.name);

        var isProduction = true;

        var loggerBin = new File(scriptDir + "/lib/00_logger.jsxbin");
        var loggerJsx = new File(scriptDir + "/lib/00_logger.jsx");
        if (loggerBin.exists) {
            $.evalFile(loggerBin);
        } else if (loggerJsx.exists) {
            $.evalFile(loggerJsx);
            isProduction = false;
        } else {
            alert(labF("ui.laboratory.error.logger_module_not_found", { binPath: loggerBin.fsName, jsxPath: loggerJsx.fsName }, "Error: Logger module not found.\n\n" +
                "Tried:\n" +
                "  - {binPath}\n" +
                "  - {jsxPath}\n\n" +
                "No JSXBIN files found. Please contact your administrator."));
            return;
        }

        var versionBin = new File(scriptDir + "/lib/06_versioning.jsxbin");
        var versionJsx = new File(scriptDir + "/lib/06_versioning.jsx");
        if (versionBin.exists) {
            $.evalFile(versionBin);
        } else if (versionJsx.exists) {
            $.evalFile(versionJsx);
            isProduction = false;
        }

        var jsonBin = new File(scriptDir + "/lib/01_json_polyfill.jsxbin");
        var jsonJsx = new File(scriptDir + "/lib/01_json_polyfill.jsx");
        if (jsonBin.exists) {
            $.evalFile(jsonBin);
        } else if (jsonJsx.exists) {
            $.evalFile(jsonJsx);
            isProduction = false;
        } else {
            alert(labF("ui.laboratory.error.json_module_not_found", { binPath: jsonBin.fsName, jsxPath: jsonJsx.fsName }, "Error: JSON polyfill module not found.\n\n" +
                "Tried:\n" +
                "  - {binPath}\n" +
                "  - {jsxPath}\n\n" +
                "No JSXBIN files found. Please contact your administrator."));
            return;
        }

        var securityBinPre = new File(scriptDir + "/lib/05_security.jsxbin");
        var securityJsxPre = new File(scriptDir + "/lib/05_security.jsx");
        if (securityBinPre.exists) {
            $.evalFile(securityBinPre);
        } else if (securityJsxPre.exists) {
            $.evalFile(securityJsxPre);
            isProduction = false;
        } else {
            alert(labF("ui.laboratory.error.security_module_not_found", { binPath: securityBinPre.fsName, jsxPath: securityJsxPre.fsName }, "Error: Security module not found.\n\n" +
                "Tried:\n" +
                "  - {binPath}\n" +
                "  - {jsxPath}\n\n" +
                "No JSXBIN files found. Please contact your administrator."));
            return;
        }

        $.global.PRLB_PRODUCTION = isProduction;

        loadLabI18n();

        if (typeof security === "undefined" || !security.check) {
            alert(labT("ui.laboratory.security.module_unavailable_access_denied", "Security module not available. Access denied."));
            return;
        }

        var securityResult = security.check();
        if (!securityResult.ok) {
            security.showActivationError(securityResult.machineID);
            if (isProduction) {
                logMessages.push("[ERROR] Access denied - Machine ID: <REDACTED>");
            } else {
                logMessages.push("[ERROR] Access denied - Machine ID: " + securityResult.machineID);
            }
            logToFile(logMessages.join("\n"));
            return;
        }
        if (isProduction) {
            logMessages.push("[SECURITY] License check passed - Machine ID: <REDACTED>");
        } else {
            logMessages.push("[SECURITY] License check passed - Machine ID: " + securityResult.machineID);
        }

        var licenseRole = "UNKNOWN";
        if (typeof security !== "undefined" && security.getRoleFromLicense) {
            licenseRole = security.getRoleFromLicense();
        }

        var devModeActive = false;
        if (typeof security !== "undefined" && security.checkDevelopmentMode) {
            devModeActive = security.checkDevelopmentMode();
            if (devModeActive) {
                logMessages.push("[MODE] Development mode active (bypasses role check)");
            }
        }

        var activeABIndex = doc.artboards.getActiveArtboardIndex();
        if (activeABIndex < 0 || activeABIndex >= doc.artboards.length) {
            alert(labT("ui.laboratory.error.no_active_artboard", "No active artboard found.\n\nPlease select an artboard before running Laboratory."));
            return;
        }
        var activeAB = doc.artboards[activeABIndex];
        logMessages.push("[ARTBOARD] Active artboard: " + activeAB.name + " (index: " + activeABIndex + ")");

        var selection = doc.selection;
        var selectionCount = selection ? selection.length : 0;
        logMessages.push("[SELECTION] Selected items: " + selectionCount);

        logMessages.push("");
        logMessages.push("[PHASE 1] Checking artboard structure...");

        var needsFix = false;
        var fixIssues = [];

        var requiredGlobalLayer = "$_Global_AB" + activeABIndex;
        var requiredPerArtLayer = "$_PerArt_AB" + activeABIndex;
        var requiredTextFramesLayer = "$_Text_Frames";

        var hasGlobalLayer = false;
        var hasPerArtLayer = false;
        var hasTextFramesLayer = false;

        for (var i = 0; i < doc.layers.length; i++) {
            var layerName = doc.layers[i].name;
            if (layerName === requiredGlobalLayer) hasGlobalLayer = true;
            if (layerName === requiredPerArtLayer) hasPerArtLayer = true;
            if (layerName === requiredTextFramesLayer) hasTextFramesLayer = true;
        }

        if (!hasGlobalLayer) {
            needsFix = true;
            fixIssues.push("Missing layer: " + requiredGlobalLayer);
        }
        if (!hasPerArtLayer) {
            needsFix = true;
            fixIssues.push("Missing layer: " + requiredPerArtLayer);
        }
        if (!hasTextFramesLayer) {
            needsFix = true;
            fixIssues.push("Missing layer: " + requiredTextFramesLayer);
        }

        var allowFixStructure = true;
        if (needsFix) {
            logMessages.push("[FIX] Issues found:");
            for (var i = 0; i < fixIssues.length; i++) {
                logMessages.push("  - " + fixIssues[i]);
            }
            if (allowFixStructure) {
                logMessages.push("[FIX] Executing FixStructure to repair...");

                var fixStructureBin = new File(scriptDir + "/FixStructure.jsxbin");
                var fixStructureJsx = new File(scriptDir + "/FixStructure.jsx");

                if (fixStructureBin.exists) {
                    $.evalFile(fixStructureBin);
                    logMessages.push("[FIX] FixStructure.jsxbin executed successfully");
                } else if (fixStructureJsx.exists) {
                    $.evalFile(fixStructureJsx);
                    logMessages.push("[FIX] FixStructure.jsx executed successfully");
                } else {
                    logMessages.push("[ERROR] FixStructure script not found");
                    logToFile(logMessages.join("\n"));
                    alert(labT("ui.laboratory.error.fixstructure_not_found", "Laboratory Error:\n\nFixStructure script not found."));
                    return;
                }
            }
        } else {
            logMessages.push("[OK] Structure is valid, no fixes needed");
        }

        logMessages.push("");
        logMessages.push("[PHASE 2] Setting mode based on license role...");

        var uiMode = "USER"; // Default to USER for safety
        if (devModeActive) {
            uiMode = "ADMIN"; // Dev mode gets full access
        } else if (licenseRole === "ADMIN") {
            uiMode = "ADMIN";
        } else {
            uiMode = "USER"; // USER or unknown -> USER mode
        }

        $.global.PRLB_MODE = uiMode;
        logMessages.push("[MODE] UI Mode: " + $.global.PRLB_MODE + " (License Role: " + licenseRole + (devModeActive ? ", Dev Mode Active" : "") + ")");

        logMessages.push("");
        logMessages.push("[PHASE 3] Executing ProofLab...");

        $.global.PRLB_LABORATORY_MODE = true;
        $.global.PRLB_APPLY_SUCCESS = false; // Reset flag before execution

        var proofLabBin = new File(scriptDir + "/ProofLab.jsxbin");
        var proofLabJsx = new File(scriptDir + "/ProofLab.jsx");

        if (proofLabBin.exists) {
            $.evalFile(proofLabBin);
        } else if (proofLabJsx.exists) {
            $.evalFile(proofLabJsx);
            $.global.PRLB_PRODUCTION = false; // Using .jsx = dev mode
        } else {
            logMessages.push("[ERROR] ProofLab script not found");
            logToFile(logMessages.join("\n"));
            alert(labF("ui.laboratory.error.prooflab_not_found", { binPath: proofLabBin.fsName, jsxPath: proofLabJsx.fsName }, "Error: ProofLab script not found.\n\n" +
                "Tried:\n" +
                "  - {binPath}\n" +
                "  - {jsxPath}\n\n" +
                "No JSXBIN files found. Please contact your administrator."));
            return;
        }

        var applySuccess = $.global.PRLB_APPLY_SUCCESS === true;
        delete $.global.PRLB_APPLY_SUCCESS; // Clean up flag

        if (!applySuccess) {
            logMessages.push("[CANCELLED] ProofLab was closed without applying (user cancelled or error)");
            logMessages.push("[END] Laboratory execution stopped - no swatch panel opened");
            logToFile(logMessages.join("\n"));
            return; // Don't open swatch panel
        }

        var lastTemplate = $.global.PRLB_LAST_TEMPLATE;
        if (lastTemplate) {
            logMessages.push("[TEMPLATE] " + lastTemplate);
            delete $.global.PRLB_LAST_TEMPLATE;
        }
        var lastApplyMode = $.global.PRLB_LAST_APPLY_MODE;
        if (lastApplyMode) {
            logMessages.push("[APPLY_MODE] " + lastApplyMode);
            delete $.global.PRLB_LAST_APPLY_MODE;
        }
        logMessages.push("[SUCCESS] ProofLab applied successfully");

        logMessages.push("");
        logMessages.push("[PHASE 3] Opening Swatch Settings panel...");

        var swatchLauncher = new File(scriptDir + "/SwatchesSettingsLauncher.jsx");
        if (swatchLauncher.exists) {
            $.evalFile(swatchLauncher);
            logMessages.push("[SUCCESS] Swatch panel opened successfully");
        } else {
            logMessages.push("[WARN] SwatchesSettingsLauncher.jsx not found");
        }

        logMessages.push("");
        logMessages.push("[END] Laboratory execution completed");

        logToFile(logMessages.join("\n"));

    } catch (e) {
        var errorLog = "[ERROR] Laboratory execution failed: " + e.toString();
        if (e.line) errorLog += "\n[ERROR] Line: " + e.line;
        if (e.stack) errorLog += "\n[ERROR] Stack: " + e.stack;

        logToFile(errorLog);
        alert(labF("ui.laboratory.error.generic", { error: e.toString() }, "Laboratory Error:\n\n{error}"));
    }
})();
