"""Loader module for components."""

from __future__ import annotations

import os
import platform
import shutil
import subprocess
import time
from concurrent.futures import ThreadPoolExecutor, as_completed
from dataclasses import dataclass, field
from functools import cached_property
from pathlib import Path
from typing import TYPE_CHECKING, Final

from pytola.core.logger import get_logger

from ..models.project import Project, detect_entry_files
from ..models.solution import Solution

if TYPE_CHECKING:
    from ..models.entryfile import EntryFile

logger = get_logger(__name__)

is_windows = platform.system() == "Windows"
is_linux = platform.system() == "Linux"
is_macos = platform.system() == "Darwin"
ext = ".exe" if is_windows else ""

# Default cache directory
_DEFAULT_BUILD_DIR = Path(".cbuild")
_DEFAULT_OUTPUT_DIR = Path("dist")
# Platform templates
_WINDOWS_GUI_TEMPLATE: str = r"""#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <time.h>
#define MAX_PATH_LEN 4096
#define MAX_ERROR_LEN 8192
// Debug flags array
static const char* DEBUG_FLAGS[] = {
    "-d",
    "--debug",
    "-v",
    "--verbose",
    NULL
};
// Check if Python runtime exists
static int check_python_runtime(const char* runtime_path) {
    return GetFileAttributesA(runtime_path) != INVALID_FILE_ATTRIBUTES;
}
// Filter command line arguments to remove debug flags
static void filter_debug_args(LPSTR input_args, char* output_args, int max_len) {
    output_args[0] = '\0';
    if (!input_args || strlen(input_args) == 0) {
        return;
    }
#if ${DEBUG_MODE}
    fprintf(stderr, "==================================================\n");
    fprintf(stderr, "DEBUG MODE - Argument Filtering\n");
    fprintf(stderr, "Raw input args: '%s'\n", input_args);
#endif
    // Tokenize and filter arguments
    char* input_copy = _strdup(input_args);
    char* token = strtok(input_copy, " \t");
    while (token != NULL) {
        int is_debug_flag = 0;
        // Check against known debug flags
        for (int i = 0; DEBUG_FLAGS[i] != NULL; i++) {
            if (_stricmp(token, DEBUG_FLAGS[i]) == 0) {
                is_debug_flag = 1;
                break;
            }
        }
        // Skip debug flags
        if (!is_debug_flag) {
            if (strlen(output_args) > 0) {
                strncat(output_args, " ", max_len - strlen(output_args) - 1);
            }
            strncat(output_args, token, max_len - strlen(output_args) - 1);
        }
#if ${DEBUG_MODE}
        else {
            fprintf(stderr, "Filtered out debug flag: '%s'\n", token);
        }
#endif
        token = strtok(NULL, " \t");
    }
    free(input_copy);
#if ${DEBUG_MODE}
    fprintf(stderr, "Filtered output args: '%s'\n", output_args);
    fprintf(stderr, "==================================================\n");
#endif
}
// Build Python command line
static void build_python_command(
    char* cmd,
    const char* exe_dir,
    const char* entry_file,
    int is_debug,
    LPSTR lpCmdLine
) {
#if ${DEBUG_MODE} == 1
    fprintf(stderr, "==================================================\n");
    fprintf(stderr, "DEBUG MODE - Command Construction\n");
    fprintf(stderr, "Executable directory: %s\n", exe_dir);
    fprintf(stderr, "Entry file: %s\n", entry_file);
    fprintf(stderr, "Debug mode: %s\n", is_debug ? "ON" : "OFF");
    fprintf(stderr, "Raw command line args: %s\n", lpCmdLine ? lpCmdLine : "(none)");
    fprintf(stderr, "==================================================\n");
#endif
    char python_runtime[MAX_PATH_LEN];
    char script_path[MAX_PATH_LEN];
    char filtered_args[MAX_PATH_LEN] = "";
    // Filter debug arguments
    if (lpCmdLine && strlen(lpCmdLine) > 0) {
        filter_debug_args(lpCmdLine, filtered_args, MAX_PATH_LEN);
    }
    // Build Python interpreter path
    // Debug mode: use python.exe to show console output
    // Production GUI mode: use pythonw.exe to hide console window
    if (is_debug) {
        snprintf(python_runtime, MAX_PATH_LEN, "%s\\runtime\\python.exe", exe_dir);
    } else {
        snprintf(python_runtime, MAX_PATH_LEN, "%s\\runtime\\pythonw.exe", exe_dir);
    }
    // Build startup script path
    snprintf(script_path, MAX_PATH_LEN, "%s\\%s", exe_dir, entry_file);
    // Build command line
    if (is_debug) {
        // Debug mode: don't redirect output, let output show in console
        snprintf(cmd, MAX_PATH_LEN * 2, "\"%s\" -u \"%s\"%s%s",
            python_runtime, script_path,
            strlen(filtered_args) > 0 ? " " : "",
            strlen(filtered_args) > 0 ? filtered_args : "");
    } else {
        // Production mode: redirect all output to pipe
        snprintf(cmd, MAX_PATH_LEN * 2, "\"%s\" -u \"%s\"%s%s 2>&1",
            python_runtime, script_path,
            strlen(filtered_args) > 0 ? " " : "",
            strlen(filtered_args) > 0 ? filtered_args : "");
    }
#if ${DEBUG_MODE} == 1
    fprintf(stderr, "==================================================\n");
    fprintf(stderr, "DEBUG MODE - Generated Command\n");
    fprintf(stderr, "Final command: %s\n", cmd);
    fprintf(stderr, "Command length: %zu characters\n", strlen(cmd));
    fprintf(stderr, "==================================================\n");
#endif
}
// Read process output with improved error handling
static void read_process_output(HANDLE hPipe, char* output, int max_len) {
    DWORD bytes_read;
    DWORD last_error;
    output[0] = '\0';
    while (
    ReadFile(hPipe, output + strlen(output), max_len - strlen(output) - 1, &bytes_read, NULL) && bytes_read > 0) {
        output[strlen(output) + bytes_read] = '\0';
        // Check for buffer overflow
        if (strlen(output) >= max_len - 1) {
            break;
        }
    }
    // Check if ReadFile failed
    last_error = GetLastError();
    if (last_error != ERROR_SUCCESS && last_error != ERROR_BROKEN_PIPE) {
        snprintf(output + strlen(output), max_len - strlen(output),
            "\n[PIPE ERROR] Failed to read process output (Error: %lu)", last_error);
    }
}
// Show message box (support UTF-8 encoding)
static void show_message_box(const char* title, const char* message) {
    // Convert UTF-8 to UTF-16 using MultiByteToWideChar
    int title_len = MultiByteToWideChar(CP_UTF8, 0, title, -1, NULL, 0);
    int msg_len = MultiByteToWideChar(CP_UTF8, 0, message, -1, NULL, 0);
    if (title_len > 0 && msg_len > 0) {
        wchar_t* wtitle = (wchar_t*)malloc(title_len * sizeof(wchar_t));
        wchar_t* wmsg = (wchar_t*)malloc(msg_len * sizeof(wchar_t));
        if (wtitle && wmsg) {
            MultiByteToWideChar(CP_UTF8, 0, title, -1, wtitle, title_len);
            MultiByteToWideChar(CP_UTF8, 0, message, -1, wmsg, msg_len);
            MessageBoxW(NULL, wmsg, wtitle, MB_ICONERROR | MB_OK);
        }
        if (wtitle) free(wtitle);
        if (wmsg) free(wmsg);
    } else {
        // Conversion failed, use ANSI version
        MessageBoxA(NULL, message, title, MB_ICONERROR | MB_OK);
    }
}
// Windows GUI entry point
int APIENTRY WinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow
) {
#if ${DEBUG_MODE} == 1
    // Print debug header with timestamp
    SYSTEMTIME st;
    GetLocalTime(&st);
    fprintf(stderr, "==================================================\n");
    fprintf(stderr, "DEBUG MODE - Application Startup\n");
    fprintf(stderr, "Timestamp: %04d-%02d-%02d %02d:%02d:%02d.%03d\n",
            st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
    fprintf(stderr, "Process ID: %lu\n", GetCurrentProcessId());
    fprintf(stderr, "Thread ID: %lu\n", GetCurrentThreadId());
    fprintf(stderr, "==================================================\n");
#endif
    char exe_dir[MAX_PATH_LEN];
    char cmd[MAX_PATH_LEN * 2];
    char error_output[MAX_ERROR_LEN] = "";
    char error_msg[MAX_ERROR_LEN];
    STARTUPINFOA si = {0};
    PROCESS_INFORMATION pi = {0};
    SECURITY_ATTRIBUTES sa = {0};
    HANDLE hReadPipe = NULL, hWritePipe = NULL;
    BOOL success;
    // Get executable directory
    GetModuleFileNameA(NULL, exe_dir, MAX_PATH_LEN);
    char* last_slash = strrchr(exe_dir, '\\');
    if (last_slash) {
        *last_slash = '\0';
    }
#if ${DEBUG_MODE} == 1
    fprintf(stderr, "==================================================\n");
    fprintf(stderr, "DEBUG MODE - Environment Info\n");
    fprintf(stderr, "Executable directory: %s\n", exe_dir);
    fprintf(stderr, "Command line arguments: %s\n", lpCmdLine ? lpCmdLine : "(none)");
    fprintf(stderr, "Current working directory: ");
    char current_dir[MAX_PATH_LEN];
    if (GetCurrentDirectoryA(MAX_PATH_LEN, current_dir)) {
        fprintf(stderr, "%s\n", current_dir);
    } else {
        fprintf(stderr, "(failed to get)\n");
    }
    fprintf(stderr, "==================================================\n");
#endif
    // Check Python runtime
    char runtime_path[MAX_PATH_LEN];
    snprintf(runtime_path, MAX_PATH_LEN, "%s\\runtime\\python%s.exe", exe_dir, ${DEBUG_MODE} ? "" : "w");
    if (!check_python_runtime(runtime_path)) {
#if ${DEBUG_MODE} == 1
        fprintf(stderr, "==================================================\n");
        fprintf(stderr, "DEBUG MODE - Python Runtime Check FAILED\n");
        fprintf(stderr, "Expected runtime path: %s\n", runtime_path);
        fprintf(stderr, "File attributes: %lu\n", GetFileAttributesA(runtime_path));
        fprintf(stderr, "Last error: %lu\n", GetLastError());
        fprintf(stderr, "\nDirectory listing of runtime folder:\n");
        WIN32_FIND_DATAA find_data;
        char search_path[MAX_PATH_LEN];
        snprintf(search_path, MAX_PATH_LEN, "%s\\runtime\\*.*", exe_dir);
        HANDLE h_find = FindFirstFileA(search_path, &find_data);
        if (h_find != INVALID_HANDLE_VALUE) {
            int file_count = 0;
            do {
                if (!(find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
                    fprintf(stderr, "  [%d] %s (size: %lu bytes)\n",
                           ++file_count, find_data.cFileName, find_data.nFileSizeLow);
                }
            } while (FindNextFileA(h_find, &find_data));
            FindClose(h_find);
            fprintf(stderr, "Total files found: %d\n", file_count);
        } else {
            fprintf(stderr, "Failed to list directory, error: %lu\n", GetLastError());
        }
        fprintf(stderr, "==================================================\n");
#endif
        show_message_box(
            "Application Error",
            "Python runtime not found.\n\n"
            "Please ensure the application is installed correctly and the runtime directory exists."
        );
        return 1;
    }
#if ${DEBUG_MODE} == 1
    else {
        fprintf(stderr, "==================================================\n");
        fprintf(stderr, "DEBUG MODE - Python Runtime Verified\n");
        fprintf(stderr, "Runtime path: %s\n", runtime_path);
        fprintf(stderr, "Verification: SUCCESS\n");
        fprintf(stderr, "==================================================\n");
    }
#endif
    // Build Python command
    build_python_command(cmd, exe_dir, "${ENTRY_FILE}", ${DEBUG_MODE}, lpCmdLine);
    // Setup startup info
    si.cb = sizeof(si);
    // Create pipe for capturing output (both debug and production modes)
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.bInheritHandle = TRUE;
    sa.lpSecurityDescriptor = NULL;
    if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0)) {
        show_message_box("Error", "Failed to create pipe for error output.");
        return 1;
    }
    si.dwFlags = STARTF_USESTDHANDLES;
    si.hStdError = hWritePipe;
    // In debug mode, keep stdout visible; in production, redirect all output
    si.hStdOutput = (${DEBUG_MODE} == 1) ? GetStdHandle(STD_OUTPUT_HANDLE) : hWritePipe;
    // Create Python process
    // Always inherit handles to capture error output
    DWORD createFlags = (${DEBUG_MODE} == 1) ? 0 : CREATE_NO_WINDOW;
#if ${DEBUG_MODE} == 1
    fprintf(stderr, "==================================================\n");
    fprintf(stderr, "DEBUG MODE - Process Creation\n");
    fprintf(stderr, "Creation flags: 0x%08X\n", createFlags);
    fprintf(stderr, "Working directory: %s\n", exe_dir);
    fprintf(stderr, "Inherit handles: TRUE\n");
    fprintf(stderr, "Startup info size: %lu\n", si.cb);
    fprintf(stderr, "==================================================\n");
#endif
    success = CreateProcessA(
        NULL, cmd, NULL, NULL, TRUE,
        createFlags,
        NULL, exe_dir, &si, &pi
    );
#if ${DEBUG_MODE} == 1
    if (success) {
        fprintf(stderr, "==================================================\n");
        fprintf(stderr, "DEBUG MODE - Process Created Successfully\n");
        fprintf(stderr, "Process ID: %lu\n", pi.dwProcessId);
        fprintf(stderr, "Thread ID: %lu\n", pi.dwThreadId);
        fprintf(stderr, "Process handle: %p\n", pi.hProcess);
        fprintf(stderr, "Thread handle: %p\n", pi.hThread);
        fprintf(stderr, "==================================================\n");
    } else {
        DWORD error = GetLastError();
        fprintf(stderr, "==================================================\n");
        fprintf(stderr, "DEBUG MODE - Process Creation FAILED\n");
        fprintf(stderr, "Error code: %lu\n", error);
        fprintf(stderr, "Error message: ");
        LPWSTR messageBuffer = NULL;
        FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                      NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                      (LPWSTR)&messageBuffer, 0, NULL);
        if (messageBuffer) {
            fwprintf(stderr, L"%s\n", messageBuffer);
            LocalFree(messageBuffer);
        } else {
            fprintf(stderr, "(failed to get error message)\n");
        }
        fprintf(stderr, "==================================================\n");
    }
#endif
    if (!success) {
        DWORD error = GetLastError();
        snprintf(error_msg, MAX_ERROR_LEN,
            "Failed to start Python process.\n\n"
            "Error code: %lu\n"
            "Command: %s",
            error, cmd);
        show_message_box("Application Error", error_msg);
            CloseHandle(hWritePipe);
            CloseHandle(hReadPipe);
        return 1;
    }
    // Read error output (always capture for better diagnostics)
        CloseHandle(hWritePipe);
        read_process_output(hReadPipe, error_output, MAX_ERROR_LEN);
        CloseHandle(hReadPipe);
    // Wait for process to end
    WaitForSingleObject(pi.hProcess, INFINITE);
    // Get exit code
    DWORD exit_code;
    GetExitCodeProcess(pi.hProcess, &exit_code);
#if ${DEBUG_MODE} == 1
    fprintf(stderr, "==================================================\n");
    fprintf(stderr, "DEBUG MODE - Process Exit\n");
    fprintf(stderr, "Exit code: %lu\n", exit_code);
    fprintf(stderr, "Exit code interpretation: ");
    if (exit_code == 0) {
        fprintf(stderr, "SUCCESS (normal termination)\n");
    } else if (exit_code == STILL_ACTIVE) {
        fprintf(stderr, "STILL ACTIVE (process still running)\n");
    } else {
        fprintf(stderr, "ERROR (abnormal termination)\n");
    }
    fprintf(stderr, "==================================================\n");
#endif
    // Cleanup
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    // Enhanced error reporting for abnormal termination
    // Only show error dialog for serious errors (exit code 1)
    // Allow argument errors (exit code 2) to pass through normally
    if (exit_code == 1) {
        char enhanced_error_msg[MAX_ERROR_LEN];
        // Always show error information when exit code is non-zero
        if (strlen(error_output) > 0) {
            // Preserve more error information (up to 6000 characters)
            size_t error_len = strlen(error_output);
            if (error_len > 6000) {
                error_output[6000] = '\0';
            }
            // Check if error message is too long for proper display
            size_t total_msg_len = strlen(error_output) + 500; // Approximate additional text length
            size_t error_output_len = strlen(error_output);
#if ${DEBUG_MODE} == 1
            fprintf(stderr, "==================================================\n");
            fprintf(stderr, "DEBUG MODE - Error Message Analysis\n");
            fprintf(stderr, "Error output length: %zu characters\n", error_output_len);
            fprintf(stderr, "Total message estimated length: %zu characters\n", total_msg_len);
            fprintf(stderr, "Message truncation threshold: 4000 characters\n");
            fprintf(stderr, "Truncation decision: %s\n", (total_msg_len > 4000) ? "TRUNCATE" : "KEEP FULL");
            fprintf(stderr, "==================================================\n");
#endif
            if (total_msg_len > 4000) {
                // For very long error messages, provide summary and suggest checking console
                // Limit the displayed error to prevent truncation issues
                char truncated_error[2001];
                strncpy(truncated_error, error_output, 2000);
                truncated_error[2000] = '\0';
#if ${DEBUG_MODE} == 1
                fprintf(stderr, "==================================================\n");
                fprintf(stderr, "DEBUG MODE - Error Truncation Applied\n");
                fprintf(stderr, "Original error length: %zu characters\n", error_output_len);
                fprintf(stderr, "Truncated error length: %zu characters\n", strlen(truncated_error));
                fprintf(stderr, "Characters preserved: %.1f%%\n",
                       (double)strlen(truncated_error) / error_output_len * 100);
                fprintf(stderr, "==================================================\n");
#endif
                snprintf(enhanced_error_msg, MAX_ERROR_LEN,
                    "应用程序运行失败!\n\n"
                    "退出代码: %lu\n\n"
                    "错误摘要:\n%s\n\n"  // Use truncated error
                    "[错误信息过长, 完整信息请查看控制台输出]\n\n"
                    "请检查:\n"
                    "• 是否缺少必要的依赖库\n"
                    "• Python 运行时是否完整\n"
                    "• 程序文件是否损坏\n\n"
                    "调试提示: 使用 -d 参数运行可查看完整错误信息",
                    exit_code, truncated_error);
            } else {
                // For shorter messages, show everything
                snprintf(enhanced_error_msg, MAX_ERROR_LEN,
                    "应用程序运行失败!\n\n"
                    "退出代码: %lu\n\n"
                    "错误详情:\n%s\n\n"
                    "请检查:\n"
                    "• 是否缺少必要的依赖库\n"
                    "• Python 运行时是否完整\n"
                    "• 程序文件是否损坏",
                    exit_code, error_output);
            }
        } else {
            // No error output captured, provide generic error message
            snprintf(enhanced_error_msg, MAX_ERROR_LEN,
                "应用程序异常终止!\n\n"
                "退出代码: %lu\n\n"
                "可能的原因:\n"
                "• 缺少必要的 Python 包\n"
                "• 依赖库版本不兼容\n"
                "• 程序初始化失败\n\n"
                "建议:\n"
                "• 检查程序安装完整性\n"
                "• 重新安装或更新依赖包\n"
                "• 联系技术支持获取帮助",
                exit_code);
        }
#if ${DEBUG_MODE} == 1
        // In debug mode, also output to console for easier debugging
        fprintf(stderr, "\n==================================================\n");
        fprintf(stderr, "DEBUG MODE - Application Error Details\n");
        fprintf(stderr, "==================================================\n");
        fprintf(stderr, "Exit Code: %lu\n", exit_code);
        fprintf(stderr, "Exit Code Hex: 0x%08X\n", exit_code);
        fprintf(stderr, "Time of error: ");
        SYSTEMTIME error_time;
        GetLocalTime(&error_time);
        fprintf(stderr, "%04d-%02d-%02d %02d:%02d:%02d.%03d\n",
                error_time.wYear, error_time.wMonth, error_time.wDay,
                error_time.wHour, error_time.wMinute, error_time.wSecond, error_time.wMilliseconds);
        if (strlen(error_output) > 0) {
            fprintf(stderr, "\nError Output (%zu characters):\n", strlen(error_output));
            fprintf(stderr, "--------------------------------------------------\n");
            fprintf(stderr, "%s\n", error_output);
            fprintf(stderr, "--------------------------------------------------\n");
            // Also save full error to temporary file for detailed analysis
            FILE* error_file = fopen("error_details.txt", "w");
            if (error_file) {
                fprintf(error_file, "Application Error Details\n");
                fprintf(error_file, "=========================\n");
                fprintf(error_file, "Exit Code: %lu (0x%08X)\n", exit_code, exit_code);
                fprintf(error_file, "Timestamp: %04d-%02d-%02d %02d:%02d:%02d.%03d\n\n",
                        error_time.wYear, error_time.wMonth, error_time.wDay,
                        error_time.wHour, error_time.wMinute, error_time.wSecond, error_time.wMilliseconds);
                fprintf(error_file, "Full Error Output:\n");
                fprintf(error_file, "===================\n");
                fprintf(error_file, "%s\n", error_output);
                fclose(error_file);
                fprintf(stderr, "\nFull error details saved to: error_details.txt\n");
                fprintf(stderr, "File size: %ld bytes\n", ftell(error_file));
            } else {
                fprintf(stderr, "\nWarning: Failed to create error_details.txt\n");
                fprintf(stderr, "Last error: %lu\n", GetLastError());
            }
        } else {
            fprintf(stderr, "\nNo error output captured from subprocess\n");
        }
        fprintf(stderr, "==================================================\n\n");
#endif
#if ${DEBUG_MODE} == 1
        // Debug output to verify final message
        size_t final_msg_len = strlen(enhanced_error_msg);
        fprintf(stderr, "==================================================\n");
        fprintf(stderr, "DEBUG MODE - Final Error Message\n");
        fprintf(stderr, "Message length: %zu characters\n", final_msg_len);
        fprintf(stderr, "Message box title: \"应用程序错误\"\n");
        fprintf(stderr, "\nMessage preview (first 500 chars):\n");
        fprintf(stderr, "--------------------------------------------------\n");
        char preview[501];
        size_t preview_len = (final_msg_len > 500) ? 500 : final_msg_len;
        strncpy(preview, enhanced_error_msg, preview_len);
        preview[preview_len] = '\0';
        fprintf(stderr, "%s\n", preview);
        if (final_msg_len > 500) {
            fprintf(stderr, "... (truncated, %zu more characters)\n", final_msg_len - 500);
        }
        fprintf(stderr, "--------------------------------------------------\n");
        fprintf(stderr, "==================================================\n");
#endif
        show_message_box("应用程序错误", enhanced_error_msg);
        return exit_code;
    }
    return exit_code;
}
"""
_WINDOWS_CONSOLE_TEMPLATE: str = r"""#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <locale.h>
#define MAX_PATH_LEN 4096
#define MAX_ERROR_LEN 8192
// Set console encoding to UTF-8
static void setup_encoding() {
    SetConsoleOutputCP(CP_UTF8);
    SetConsoleCP(CP_UTF8);
    setlocale(LC_ALL, ".UTF8");
}
// Check if Python runtime exists
static int check_python_runtime(const char* runtime_path) {
    return GetFileAttributesA(runtime_path) != INVALID_FILE_ATTRIBUTES;
}
// Filter command line arguments to remove debug flags
static void filter_debug_args(LPSTR input_args, char* output_args, int max_len) {
    output_args[0] = '\0';
    if (!input_args || strlen(input_args) == 0) {
        return;
    }
#if ${DEBUG_MODE}
    fprintf(stderr, "==================================================\n");
    fprintf(stderr, "DEBUG MODE - Argument Filtering\n");
    fprintf(stderr, "Raw input args: '%s'\n", input_args);
#endif
    // Tokenize and filter arguments
    char* input_copy = _strdup(input_args);
    char* token = strtok(input_copy, " \t");
    while (token != NULL) {
        int is_debug_flag = 0;
        // Check against known debug flags
        if (_stricmp(token, "-d") == 0 ||
            _stricmp(token, "--debug") == 0 ||
            _stricmp(token, "-v") == 0 ||
            _stricmp(token, "--verbose") == 0) {
            is_debug_flag = 1;
        }
        // Skip debug flags
        if (!is_debug_flag) {
            if (strlen(output_args) > 0) {
                strncat(output_args, " ", max_len - strlen(output_args) - 1);
            }
            strncat(output_args, token, max_len - strlen(output_args) - 1);
        }
#if ${DEBUG_MODE}
        else {
            fprintf(stderr, "Filtered out debug flag: '%s'\n", token);
        }
#endif
        token = strtok(NULL, " \t");
    }
    free(input_copy);
#if ${DEBUG_MODE}
    fprintf(stderr, "Filtered output args: '%s'\n", output_args);
    fprintf(stderr, "==================================================\n");
#endif
}
// Build Python command line
static void build_python_command(
    char* cmd,
    const char* exe_dir,
    const char* entry_file,
    int argc,
    char* argv[]
) {
    char python_runtime[MAX_PATH_LEN];
    char script_path[MAX_PATH_LEN];
    char* p = cmd;
    size_t remaining = MAX_PATH_LEN * 2;
    int len;
    // Build Python interpreter path
    snprintf(python_runtime, MAX_PATH_LEN, "%s\\runtime\\python.exe", exe_dir);
    // Build startup script path
    snprintf(script_path, MAX_PATH_LEN, "%s\\%s", exe_dir, entry_file);
    // Base command
    len = snprintf(p, remaining, "\"%s\" -u \"%s\"", python_runtime, script_path);
    p += len;
    remaining -= len;
    // Append arguments
    for (int i = 1; i < argc && remaining > 0; i++) {
        len = snprintf(p, remaining, " \"%s\"", argv[i]);
        if (len < 0 || (size_t)len >= remaining) break;
        p += len;
        remaining -= len;
    }
}
// Read process output with improved error handling
static void read_process_output(HANDLE hPipe, char* output, int max_len) {
    DWORD bytes_read;
    DWORD last_error;
    output[0] = '\0';
    while (ReadFile(hPipe, output + strlen(output),
          max_len - strlen(output) - 1, &bytes_read, NULL) && bytes_read > 0) {
        output[strlen(output) + bytes_read] = '\0';
        // Check for buffer overflow
        if (strlen(output) >= max_len - 1) {
            break;
        }
    }
    // Check if ReadFile failed
    last_error = GetLastError();
    if (last_error != ERROR_SUCCESS && last_error != ERROR_BROKEN_PIPE) {
        snprintf(output + strlen(output), max_len - strlen(output),
            "\n[PIPE ERROR] Failed to read process output (Error: %lu)", last_error);
    }
}
// Windows Console entry point
int main(int argc, char* argv[]) {
    char exe_dir[MAX_PATH_LEN];
    char cmd[MAX_PATH_LEN * 2];
    STARTUPINFOA si = {0};
    PROCESS_INFORMATION pi = {0};
    SECURITY_ATTRIBUTES sa = {0};
    HANDLE hReadPipe = NULL, hWritePipe = NULL;
    BOOL success;
    char* last_slash;
    // Setup
    setup_encoding();
    si.cb = sizeof(si);
    // Get executable directory
    GetModuleFileNameA(NULL, exe_dir, MAX_PATH_LEN);
    if ((last_slash = strrchr(exe_dir, '\\'))) *last_slash = '\0';
    // Check Python runtime
    if (!check_python_runtime(exe_dir)) {
        fprintf(stderr, "Error: Python runtime not found at %s\\runtime\\\n", exe_dir);
        fprintf(stderr, "Please ensure the application is installed correctly.\n");
        return 1;
    }
    // Build and execute Python command
    build_python_command(cmd, exe_dir, "${ENTRY_FILE}", argc, argv);
#if ${DEBUG_MODE} == 1
    // Debug output (only in actual debug mode, not in production diagnostics)
#ifdef _WIN32
    {
        int wcmd_len = MultiByteToWideChar(CP_UTF8, 0, cmd, -1, NULL, 0);
        if (wcmd_len > 0) {
            wchar_t* wcmd = (wchar_t*)malloc(wcmd_len * sizeof(wchar_t));
            MultiByteToWideChar(CP_UTF8, 0, cmd, -1, wcmd, wcmd_len);
            fwprintf(stderr, L"DEBUG: Command to execute: %ls\n", wcmd);
            free(wcmd);
        }
    }
#else
    fprintf(stderr, "DEBUG: Command to execute: %s\n", cmd);
#endif
#endif
    // Create Python process
    // Always inherit handles to capture error output
    success = CreateProcessA(
        NULL, cmd, NULL, NULL, TRUE,
        0, NULL, exe_dir, &si, &pi
    );
    if (!success) {
        DWORD error = GetLastError();
        fprintf(stderr, "Error: Failed to start Python process.\n");
        fprintf(stderr, "Error code: %lu\n", error);
        fprintf(stderr, "Command: %s\n", cmd);
        return 1;
    }
    // Enhanced error handling for console applications
    // Always capture error output for better diagnostics
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.bInheritHandle = TRUE;
    sa.lpSecurityDescriptor = NULL;
    if (CreatePipe(&hReadPipe, &hWritePipe, &sa, 0)) {
        si.dwFlags = STARTF_USESTDHANDLES;
        si.hStdError = hWritePipe;
        si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); // Keep stdout normal
        si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);   // Keep stdin normal
    }
    // Wait for process to end
    WaitForSingleObject(pi.hProcess, INFINITE);
    // Get exit code
    DWORD exit_code;
    GetExitCodeProcess(pi.hProcess, &exit_code);
#if ${DEBUG_MODE}
    fprintf(stderr, "==================================================\n");
    fprintf(stderr, "DEBUG MODE - Process Exit\n");
    fprintf(stderr, "Exit code: %lu\n", exit_code);
    fprintf(stderr, "Exit code interpretation: ");
    if (exit_code == 0) {
        fprintf(stderr, "SUCCESS (normal termination)\n");
    } else if (exit_code == STILL_ACTIVE) {
        fprintf(stderr, "STILL ACTIVE (process still running)\n");
    } else {
        fprintf(stderr, "ERROR (abnormal termination)\n");
    }
    fprintf(stderr, "==================================================\n");
#endif
    // Cleanup
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    // Enhanced error reporting for console mode
    // Only show error message for serious errors (exit code 1)
    // Allow argument errors (exit code 2) to pass through normally
    if (exit_code == 1) {
        char console_error_msg[MAX_ERROR_LEN] = "";
        // Try to read error output if pipe was created
        if (hReadPipe != NULL) {
            CloseHandle(hWritePipe);
            read_process_output(hReadPipe, console_error_msg, MAX_ERROR_LEN);
            CloseHandle(hReadPipe);
        }
        fprintf(stderr, "\n==================================================\n");
        fprintf(stderr, "应用程序运行失败!\n");
        fprintf(stderr, "退出代码: %lu\n", exit_code);
        if (strlen(console_error_msg) > 0) {
            fprintf(stderr, "\n详细错误信息:\n%s\n", console_error_msg);
        } else {
            fprintf(stderr, "\n可能的原因:\n");
            fprintf(stderr, "• 缺少必要的 Python 包 (如 numpy, pandas 等)\n");
            fprintf(stderr, "• 依赖库版本不兼容\n");
            fprintf(stderr, "• 程序文件损坏或不完整\n");
        }
        fprintf(stderr, "\n解决建议:\n");
        fprintf(stderr, "1. 检查程序安装目录的完整性\n");
        fprintf(stderr, "2. 重新运行打包程序确保所有依赖都被正确包含\n");
        fprintf(stderr, "3. 查看详细的错误日志获取更多信息\n");
        fprintf(stderr, "==================================================\n\n");
        return exit_code;
    }
    return exit_code;
}
"""
_UNIX_GUI_TEMPLATE: str = r"""#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#define MAX_PATH_LEN 4096
#define MAX_ERROR_LEN 8192
// Build Python command line
static void build_python_command(
    char* cmd,
    const char* exe_dir,
    const char* entry_file,
    int argc,
    char* argv[]
) {
    char script_path[MAX_PATH_LEN];
    char* p = cmd;
    size_t remaining = MAX_PATH_LEN * 3;
    int len;
    // Build startup script path
    snprintf(script_path, MAX_PATH_LEN, "%s/%s", exe_dir, entry_file);
    // Build log file path (record error information)
    char log_file[MAX_PATH_LEN];
    snprintf(log_file, MAX_PATH_LEN, "%s/.error_log", exe_dir);
    // Build command line - use system python3 instead of bundled runtime
    // GUI mode uses nohup and background execution, error output to log
    len = snprintf(p, remaining,
        "cd \"%s\" && nohup python3 -u \"%s\"",
        exe_dir, script_path);
    p += len;
    remaining -= len;
    // Append command line arguments
    for (int i = 1; i < argc && remaining > 0; i++) {
        len = snprintf(p, remaining, " \"%s\"", argv[i]);
        if (len < 0 || (size_t)len >= remaining) break;
        p += len;
        remaining -= len;
    }
    // Append log redirection
    if (remaining > 0) {
        snprintf(p, remaining, " >\"%s\" 2>&1 &", log_file);
    }
}
// Unix GUI entry point
int main(int argc, char* argv[]) {
    char exe_dir[MAX_PATH_LEN];
    char cmd[MAX_PATH_LEN * 3];
    char log_file[MAX_PATH_LEN];
    pid_t pid;
    int status;
    char* last_slash;
    // Get executable directory
    if (realpath("/proc/self/exe", exe_dir) == NULL &&
        realpath(argv[0], exe_dir) == NULL) {
        fprintf(stderr, "Error: Cannot determine executable directory\n");
        return 1;
    }
    // Remove executable name, keep only directory
    if ((last_slash = strrchr(exe_dir, '/'))) *last_slash = '\0';
    // Build and execute Python command
    build_python_command(cmd, exe_dir, "${ENTRY_FILE}", argc, argv);
    snprintf(log_file, MAX_PATH_LEN, "%s/.error_log", exe_dir);
    // Execute Python process in background
    pid = fork();
    if (pid == 0) {
        // Child process: execute Python command and exit immediately
        int ret = system(cmd);
        _exit(WEXITSTATUS(ret));
    } else if (pid < 0) {
        fprintf(stderr, "Error: Failed to fork process\n");
        return 1;
    }
    // Wait for a short time to check if process failed to start
    sleep(1);
    if (waitpid(pid, &status, WNOHANG) == pid) {
        // Process has already exited, read error log
        FILE* fp = fopen(log_file, "r");
        if (fp) {
            char error_msg[MAX_ERROR_LEN];
            if (fgets(error_msg, sizeof(error_msg), fp)) {
                fprintf(stderr, "Application failed to start:\n%s\n", error_msg);
            }
            fclose(fp);
        } else {
            fprintf(stderr, "Application failed to start (exit code: %d)\n", WEXITSTATUS(status));
        }
#if ${DEBUG_MODE} == 1
        // In debug mode, also show additional diagnostic information
        fprintf(stderr, "\n==================================================\n");
        fprintf(stderr, "DEBUG MODE - Process Exit Details\n");
        fprintf(stderr, "Exit status: %d\n", WEXITSTATUS(status));
        fprintf(stderr, "Raw status value: %d (0x%08X)\n", status, status);
        fprintf(stderr, "Process exited normally: %s\n", WIFEXITED(status) ? "YES" : "NO");
        fprintf(stderr, "Process terminated by signal: %s\n", WIFSIGNALED(status) ? "YES" : "NO");
        if (WIFSIGNALED(status)) {
            fprintf(stderr, "Termination signal: %d\n", WTERMSIG(status));
        }
        fprintf(stderr, "Process stopped: %s\n", WIFSTOPPED(status) ? "YES" : "NO");
        fprintf(stderr, "Log file location: %s\n", log_file);
        fprintf(stderr, "==================================================\n");
#endif
        return WEXITSTATUS(status);
    }
    // Parent process exits immediately
    return 0;
}
"""
_UNIX_CONSOLE_TEMPLATE: str = r"""#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#define MAX_PATH_LEN 4096
// Filter debug arguments for Unix systems
static void filter_debug_args(int argc, char* argv[], char* output_args, int max_len) {
    output_args[0] = '\0';
#if ${DEBUG_MODE} == 1
    fprintf(stderr, "==================================================\n");
    fprintf(stderr, "DEBUG MODE - Argument Filtering\n");
    fprintf(stderr, "Input arguments: ");
    for (int i = 1; i < argc; i++) {
        fprintf(stderr, "'%s' ", argv[i]);
    }
    fprintf(stderr, "\n");
#endif
    // Filter out debug flags
    for (int i = 1; i < argc; i++) {
        int is_debug_flag = 0;
        // Check against known debug flags
        if (strcasecmp(argv[i], "-d") == 0 ||
            strcasecmp(argv[i], "--debug") == 0 ||
            strcasecmp(argv[i], "-v") == 0 ||
            strcasecmp(argv[i], "--verbose") == 0) {
            is_debug_flag = 1;
        }
        // Skip debug flags
        if (!is_debug_flag) {
            if (strlen(output_args) > 0) {
                strncat(output_args, " ", max_len - strlen(output_args) - 1);
            }
            strncat(output_args, argv[i], max_len - strlen(output_args) - 1);
        }
#if ${DEBUG_MODE} == 1
        else {
            fprintf(stderr, "Filtered out debug flag: '%s'\n", argv[i]);
        }
#endif
    }
#if ${DEBUG_MODE} == 1
    fprintf(stderr, "Filtered output args: '%s'\n", output_args);
    fprintf(stderr, "==================================================\n");
#endif
}
// Build Python command line
static void build_python_command(
    char* cmd,
    const char* exe_dir,
    const char* entry_file,
    int argc,
    char* argv[]
) {
    char script_path[MAX_PATH_LEN];
    char filtered_args[MAX_PATH_LEN * 2] = "";
    char* p = cmd;
    size_t remaining = MAX_PATH_LEN * 2;
    int len;
    // Filter debug arguments
    if (argc > 1) {
        filter_debug_args(argc, argv, filtered_args, MAX_PATH_LEN * 2);
    }
    // Build startup script path
    snprintf(script_path, MAX_PATH_LEN, "%s/%s", exe_dir, entry_file);
    // Build command line - use system python3 instead of bundled runtime
    // add -u parameter for real-time output capture
    len = snprintf(p, remaining,
        "cd \"%s\" && python3 -u \"%s\"",
        exe_dir, script_path);
    p += len;
    remaining -= len;
    // Append filtered command line arguments
    if (strlen(filtered_args) > 0) {
        len = snprintf(p, remaining, " %s", filtered_args);
        if (len > 0 && (size_t)len < remaining) {
            p += len;
            remaining -= len;
        }
    }
}
// Unix Console entry point
int main(int argc, char* argv[]) {
    char exe_dir[MAX_PATH_LEN];
    char cmd[MAX_PATH_LEN * 3];
    pid_t pid;
    int status;
    char* last_slash;
    // Get executable directory
    if (realpath("/proc/self/exe", exe_dir) == NULL) {
        fprintf(stderr, "Error: Cannot determine executable directory\n");
        return 1;
    }
    // Remove executable name, keep only directory
    if ((last_slash = strrchr(exe_dir, '/'))) *last_slash = '\0';
    // Build and execute Python command
    build_python_command(cmd, exe_dir, "${ENTRY_FILE}", argc, argv);
    // Fork and execute Python process
    pid = fork();
    if (pid == 0) {
        // Child process: execute Python command
        execl("/bin/sh", "sh", "-c", cmd, NULL);
        fprintf(stderr, "Error: Failed to execute Python process\n");
        _exit(127); // If execl fails
    } else if (pid < 0) {
        fprintf(stderr, "Error: Failed to fork process\n");
        return 1;
    }
    // Parent process: wait for child process to end
    waitpid(pid, &status, 0);
    int exit_code = WEXITSTATUS(status);
    if (exit_code != 0) {
        fprintf(stderr, "\nApplication exited abnormally, error code: %d\n", exit_code);
        fprintf(stderr, "Please check the error information above for details.\n");
#if ${DEBUG_MODE} == 1
        // In debug mode, provide additional diagnostic information
        fprintf(stderr, "\n==================================================\n");
        fprintf(stderr, "DEBUG MODE - Exit Code Analysis\n");
        fprintf(stderr, "Process exit status: %d (0x%08X)\n", status, status);
        fprintf(stderr, "Exited normally (WIFEXITED): %s\n", WIFEXITED(status) ? "YES" : "NO");
        fprintf(stderr, "Terminated by signal (WIFSIGNALED): %s\n", WIFSIGNALED(status) ? "YES" : "NO");
        fprintf(stderr, "Stopped by signal (WIFSTOPPED): %s\n", WIFSTOPPED(status) ? "YES" : "NO");
        if (WIFEXITED(status)) {
            fprintf(stderr, "Exit code value: %d\n", WEXITSTATUS(status));
        }
        if (WIFSIGNALED(status)) {
            fprintf(stderr, "Termination signal number: %d\n", WTERMSIG(status));
            fprintf(stderr, "Signal description: ");
            switch (WTERMSIG(status)) {
                case SIGSEGV: fprintf(stderr, "Segmentation fault"); break;
                case SIGABRT: fprintf(stderr, "Aborted"); break;
                case SIGTERM: fprintf(stderr, "Terminated"); break;
                case SIGINT: fprintf(stderr, "Interrupted"); break;
                case SIGKILL: fprintf(stderr, "Killed"); break;
                default: fprintf(stderr, "Signal %d", WTERMSIG(status)); break;
            }
            fprintf(stderr, "\n");
        }
        if (WIFSTOPPED(status)) {
            fprintf(stderr, "Stop signal number: %d\n", WSTOPSIG(status));
        }
        fprintf(stderr, "==================================================\n");
#endif
    }
    return exit_code;
}
"""
_MACOS_GUI_TEMPLATE: str = r"""#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <CoreFoundation/CoreFoundation.h>
#include <ApplicationServices/ApplicationServices.h>
#define MAX_PATH_LEN 4096
#define MAX_ERROR_LEN 8192
// Check if Python interpreter exists
static int check_python_runtime(const char* runtime_path) {
    struct stat st;
    return stat(runtime_path, &st) == 0 && (st.st_mode & S_IXUSR);
}
// Filter debug arguments for macOS
static void filter_debug_args(int argc, char* argv[], char* output_args, int max_len) {
    output_args[0] = '\0';
#if ${DEBUG_MODE} == 1
    fprintf(stderr, "==================================================\n");
    fprintf(stderr, "DEBUG MODE - Argument Filtering\n");
    fprintf(stderr, "Input arguments: ");
    for (int i = 1; i < argc; i++) {
        fprintf(stderr, "'%s' ", argv[i]);
    }
    fprintf(stderr, "\n");
#endif
    // Filter out debug flags
    for (int i = 1; i < argc; i++) {
        int is_debug_flag = 0;
        // Check against known debug flags
        if (strcasecmp(argv[i], "-d") == 0 ||
            strcasecmp(argv[i], "--debug") == 0 ||
            strcasecmp(argv[i], "-v") == 0 ||
            strcasecmp(argv[i], "--verbose") == 0) {
            is_debug_flag = 1;
        }
        // Skip debug flags
        if (!is_debug_flag) {
            if (strlen(output_args) > 0) {
                strncat(output_args, " ", max_len - strlen(output_args) - 1);
            }
            strncat(output_args, argv[i], max_len - strlen(output_args) - 1);
        }
#if ${DEBUG_MODE} == 1
        else {
            fprintf(stderr, "Filtered out debug flag: '%s'\n", argv[i]);
        }
#endif
    }
#if ${DEBUG_MODE} == 1
    fprintf(stderr, "Filtered output args: '%s'\n", output_args);
    fprintf(stderr, "==================================================\n");
#endif
}
// Get executable directory (macOS specific)
static void get_exe_dir_macos(char* exe_dir, size_t size) {
    CFBundleRef bundle = CFBundleGetMainBundle();
    if (bundle) {
        CFURLRef url = CFBundleCopyBundleURL(bundle);
        if (url) {
            CFStringRef path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
            if (path) {
                CFStringGetCString(path, exe_dir, size, kCFStringEncodingUTF8);
                CFRelease(path);
            }
            CFRelease(url);
        }
    } else {
        // If not in bundle, get current working directory
        if (getcwd(exe_dir, size) == NULL) {
            exe_dir[0] = '\0';
        }
    }
    // Remove Contents/MacOS suffix of bundle
    char* macos_path = strstr(exe_dir, ".app/Contents/MacOS");
    if (macos_path) {
        *macos_path = '\0';
    }
}
// Display macOS error dialog
static void show_error_dialog(const char* message) {
    CFStringRef cf_message = CFStringCreateWithCString(
        NULL, message, kCFStringEncodingUTF8
    );
    CFOptionFlags response;
    CFUserNotificationDisplayAlert(
        0,
        kCFUserNotificationStopAlertLevel,
        NULL, NULL, NULL,
        CFSTR("Application Error"),
        cf_message,
        CFSTR("OK"), NULL, NULL, &response
    );
    CFRelease(cf_message);
}
// Build Python command line
static void build_python_command(
    char* cmd,
    const char* exe_dir,
    const char* entry_file,
    int argc,
    char* argv[]
) {
    char python_runtime[MAX_PATH_LEN];
    char script_path[MAX_PATH_LEN];
    char log_file[MAX_PATH_LEN];
    char filtered_args[MAX_PATH_LEN * 2] = "";
    char* p = cmd;
    size_t remaining = MAX_PATH_LEN * 2;
    int len;
    // Filter debug arguments
    if (argc > 1) {
        filter_debug_args(argc, argv, filtered_args, MAX_PATH_LEN * 2);
    }
    // macOS Python path
    snprintf(python_runtime, MAX_PATH_LEN, "%s/runtime/bin/python3", exe_dir);
    snprintf(script_path, MAX_PATH_LEN, "%s/%s", exe_dir, entry_file);
    // Build log file path
    snprintf(log_file, MAX_PATH_LEN, "%s/.error_log", exe_dir);
    // Build command line (GUI mode uses nohup and background execution, error output to log)
    len = snprintf(p, remaining,
        "cd \"%s\" && nohup \"%s\" -u \"%s\"",
        exe_dir, python_runtime, script_path);
    p += len;
    remaining -= len;
    // Append filtered command line arguments
    if (strlen(filtered_args) > 0) {
        len = snprintf(p, remaining, " %s", filtered_args);
        if (len > 0 && (size_t)len < remaining) {
            p += len;
            remaining -= len;
        }
    }
    // Append log redirection
    if (remaining > 0) {
        snprintf(p, remaining, " >\"%s\" 2>&1 &", log_file);
    }
}
// macOS GUI entry point
int main(int argc, char* argv[]) {
    char exe_dir[MAX_PATH_LEN];
    char cmd[MAX_PATH_LEN * 3];
    char log_file[MAX_PATH_LEN];
    char python_runtime[MAX_PATH_LEN];
    pid_t pid;
    int status;
    // Get executable directory
    get_exe_dir_macos(exe_dir, MAX_PATH_LEN);
    // Check Python runtime
    snprintf(python_runtime, MAX_PATH_LEN, "%s/runtime/bin/python3", exe_dir);
    if (!check_python_runtime(python_runtime)) {
        char error_msg[MAX_PATH_LEN];
        snprintf(error_msg, MAX_PATH_LEN,
            "Python runtime not found.\n\n"
            "Please ensure the application is installed correctly and the runtime directory is at:\n%s/runtime/bin/",
            exe_dir);
        show_error_dialog(error_msg);
        return 1;
    }
    // Build and execute Python command
    build_python_command(cmd, exe_dir, "${ENTRY_FILE}", argc, argv);
    snprintf(log_file, MAX_PATH_LEN, "%s/.error_log", exe_dir);
    // Execute Python process in background
    pid = fork();
    if (pid == 0) {
        // Child process
        int ret = system(cmd);
        _exit(WEXITSTATUS(ret));
    } else if (pid < 0) {
        char error_msg[MAX_PATH_LEN];
        snprintf(error_msg, MAX_PATH_LEN, "Failed to create process.\nError: %s", strerror(errno));
        show_error_dialog(error_msg);
        return 1;
    }
    // Wait for a short time to check if process failed to start
    sleep(1);
    if (waitpid(pid, &status, WNOHANG) == pid) {
        // Process has already exited, read error log
        FILE* fp = fopen(log_file, "r");
        if (fp) {
            char error_msg[MAX_ERROR_LEN];
            if (fgets(error_msg, sizeof(error_msg), fp)) {
                // Remove newline
                char* newline = strchr(error_msg, '\n');
                if (newline) *newline = '\0';
                char full_error[MAX_PATH_LEN + MAX_ERROR_LEN];
                snprintf(full_error, sizeof(full_error),
                    "Application failed to start.\n\nError:\n%s", error_msg);
                show_error_dialog(full_error);
            }
            fclose(fp);
        } else {
            char error_msg[MAX_PATH_LEN];
            snprintf(error_msg, MAX_PATH_LEN,
                "Application failed to start.\n\nExit code: %d",
                WEXITSTATUS(status));
            show_error_dialog(error_msg);
        }
#if ${DEBUG_MODE} == 1
        // In debug mode, also output to stderr for debugging
        fprintf(stderr, "\n==================================================\n");
        fprintf(stderr, "DEBUG MODE - macOS Application Error Details\n");
        fprintf(stderr, "Exit Code: %d\n", WEXITSTATUS(status));
        fprintf(stderr, "Raw Process Status: %d (0x%08X)\n", status, status);
        fprintf(stderr, "Process exited normally: %s\n", WIFEXITED(status) ? "YES" : "NO");
        fprintf(stderr, "Process terminated by signal: %s\n", WIFSIGNALED(status) ? "YES" : "NO");
        fprintf(stderr, "Process stopped: %s\n", WIFSTOPPED(status) ? "YES" : "NO");
        if (WIFSIGNALED(status)) {
            fprintf(stderr, "Termination signal: %d\n", WTERMSIG(status));
        }
        fprintf(stderr, "Log file location: %s\n", log_file);
        fprintf(stderr, "Current working directory: ");
        char cwd[PATH_MAX];
        if (getcwd(cwd, sizeof(cwd))) {
            fprintf(stderr, "%s\n", cwd);
        } else {
            fprintf(stderr, "(failed to get)\n");
        }
        fprintf(stderr, "==================================================\n");
#endif
        return WEXITSTATUS(status);
    }
    return 0;
}
"""
_MACOS_CONSOLE_TEMPLATE: str = r"""#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <errno.h>
#include <CoreFoundation/CoreFoundation.h>
#define MAX_PATH_LEN 4096
// Check if Python interpreter exists
static int check_python_runtime(const char* runtime_path) {
    struct stat st;
    return stat(runtime_path, &st) == 0 && (st.st_mode & S_IXUSR);
}
// Get executable directory (macOS specific)
static void get_exe_dir_macos(char* exe_dir, size_t size) {
    CFBundleRef bundle = CFBundleGetMainBundle();
    if (bundle) {
        CFURLRef url = CFBundleCopyBundleURL(bundle);
        if (url) {
            CFStringRef path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
            if (path) {
                CFStringGetCString(path, exe_dir, size, kCFStringEncodingUTF8);
                CFRelease(path);
            }
            CFRelease(url);
        }
    } else {
        // Get current working directory if not in bundle
        if (getcwd(exe_dir, size) == NULL) {
            exe_dir[0] = '\0';
        }
    }
}
// Build Python command line
static void build_python_command(
    char* cmd,
    const char* exe_dir,
    const char* entry_file,
    int argc,
    char* argv[]
) {
    char python_runtime[MAX_PATH_LEN];
    char script_path[MAX_PATH_LEN];
    char* p = cmd;
    size_t remaining = MAX_PATH_LEN;
    int len;
    snprintf(python_runtime, MAX_PATH_LEN, "%s/runtime/bin/python3", exe_dir);
    snprintf(script_path, MAX_PATH_LEN, "%s/%s", exe_dir, entry_file);
    // Build command line (add -u parameter for real-time output capture)
    len = snprintf(p, remaining,
        "cd \"%s\" && \"%s\" -u \"%s\"",
        exe_dir, python_runtime, script_path);
    p += len;
    remaining -= len;
    // Append command line arguments
    for (int i = 1; i < argc && remaining > 0; i++) {
        len = snprintf(p, remaining, " \"%s\"", argv[i]);
        if (len < 0 || (size_t)len >= remaining) break;
        p += len;
        remaining -= len;
    }
}
// macOS Console entry point
int main(int argc, char* argv[]) {
    char exe_dir[MAX_PATH_LEN];
    char cmd[MAX_PATH_LEN * 3];
    char python_runtime[MAX_PATH_LEN];
    pid_t pid;
    int status;
    // Get executable directory
    get_exe_dir_macos(exe_dir, MAX_PATH_LEN);
    // Check Python runtime
    snprintf(python_runtime, MAX_PATH_LEN, "%s/runtime/bin/python3", exe_dir);
    if (!check_python_runtime(python_runtime)) {
        fprintf(stderr, "Error: Python runtime not found at %s/runtime/bin/\n", exe_dir);
        fprintf(stderr, "Please ensure the application is installed correctly.\n");
        return 1;
    }
    // Build and execute Python command
    build_python_command(cmd, exe_dir, "${ENTRY_FILE}", argc, argv);
    // Fork and execute Python process
    pid = fork();
    if (pid == 0) {
        execl("/bin/sh", "sh", "-c", cmd, NULL);
        fprintf(stderr, "Error: Failed to execute Python process\n");
        _exit(127);
    } else if (pid < 0) {
        fprintf(stderr, "Error: Failed to create process: %s\n", strerror(errno));
        return 1;
    }
    waitpid(pid, &status, 0);
    int exit_code = WEXITSTATUS(status);
    if (exit_code != 0) {
        fprintf(stderr, "\nApplication exited abnormally, error code: %d\n", exit_code);
        fprintf(stderr, "Please check the error information above for details.\n");
#if ${DEBUG_MODE} == 1
        // In debug mode, provide additional diagnostic information
        fprintf(stderr, "\nDEBUG: Exit code details:\n");
        fprintf(stderr, "  - Process exit status: %d\n", status);
        fprintf(stderr, "  - WIFEXITED: %s\n", WIFEXITED(status) ? "true" : "false");
        fprintf(stderr, "  - WIFSIGNALED: %s\n", WIFSIGNALED(status) ? "true" : "false");
        if (WIFSIGNALED(status)) {
            fprintf(stderr, "  - Signal number: %d\n", WTERMSIG(status));
        }
#endif
    }
    return exit_code;
}
"""
ENTRY_FILE_TEMPLATE = r"""
import os
import sys
from pathlib import Path
# Setup environment
cwd = Path.cwd()
site_dirs = [cwd / "site-packages", cwd / "lib"]
dirs = [cwd, cwd / "src", cwd / "runtime", *site_dirs]
for dir in dirs:
    sys.path.append(str(dir))
# Fix zipimporter compatibility for packages imported from zip archives
# Some packages (e.g., markdown) require exec_module on zipimporter
import zipimport
if not hasattr(zipimport.zipimporter, 'exec_module'):
    def _create_module(self, spec):
        return None
    def _exec_module(self, module):
        code = self.get_code(module.__name__)
        exec(code, module.__dict__)
    zipimport.zipimporter.create_module = _create_module
    zipimport.zipimporter.exec_module = _exec_module
# Qt configuration (optional)
$QT_CONFIG
# Main entry point
from src.$PROJECT_NAME.$ENTRY_NAME import main
main()
"""


@dataclass(frozen=True)
class CompilerConfig:
    """Compiler configuration dataclass.

    Attributes.
    ----------
        name: Compiler name
        args: Tuple of compiler arguments
    """

    name: str
    args: tuple[str, ...]

    def to_list(self) -> list[str]:
        """Convert arguments to list.

        Returns.
        -------
            List of compiler arguments
        """
        return list(self.args)


# Compiler configurations
_COMPILER_CONFIGS: Final = [
    CompilerConfig(name="gcc", args=("-std=c99", "-Wall", "-O2")),
    CompilerConfig(name="clang", args=("-std=c99", "-Wall", "-O2")),
    CompilerConfig(name="cl", args=("/std:c99", "/O2")),
]


def find_compiler() -> str | None:
    """Find available C compiler."""
    for compiler in ("gcc", "clang", "cl"):
        if shutil.which(compiler):
            return compiler
    logger.error("No compiler found")
    return None


def get_compiler_args(compiler: str) -> list[str]:
    """Get compiler arguments for specified compiler.

    Args:
        compiler: Compiler name or path.

    Returns.
    -------
        List of compiler arguments
    """
    compiler_name = Path(compiler).stem if "\\" in compiler or "/" in compiler else compiler
    for config in _COMPILER_CONFIGS:
        if config.name == compiler_name:
            return config.to_list()
    return []


def select_c_template(loader_type: str, debug: bool) -> str:
    """Select the appropriate C code template based on platform and type.

    In debug mode, always use console template to ensure output is visible.
    Uses optimized template with enhanced error diagnostics for better troubleshooting.
    """
    # Import optimized version for better error handling
    try:
        from .loader_optimized import get_optimized_template

        return get_optimized_template(loader_type, debug)
    except ImportError:
        # Fallback to original implementation
        if debug:
            loader_type = "console"
        if is_windows:
            return _WINDOWS_GUI_TEMPLATE if loader_type == "gui" else _WINDOWS_CONSOLE_TEMPLATE
        if is_macos:
            return _MACOS_GUI_TEMPLATE if loader_type == "gui" else _MACOS_CONSOLE_TEMPLATE
        return _UNIX_GUI_TEMPLATE if loader_type == "gui" else _UNIX_CONSOLE_TEMPLATE


def prepare_entry_file(project: Project, entry_stem: str) -> str:
    """Generate entry file code by replacing placeholders in template.

    Args:
        project: Project object containing metadata
        entry_stem: Entry file name without extension (e.g., "myapp" for "myapp.py" or "myapp.ent").

    Returns.
    -------
        Generated entry file code
    """
    # 智能Qt配置生成: 如果项目有Qt依赖或者被识别为GUI项目, 则生成Qt配置
    should_generate_qt_config = project.has_qt or project.is_gui
    # 直接使用Project提供的正确Qt库名称
    qt_libname = project.qt_libname or ""
    qt_config = (
        """# Qt configuration
qt_dir = cwd / "site-packages" / "$QT_NAME"
plugin_path = str(qt_dir / "plugins" / "platforms")
os.environ["QT_QPA_PLATFORM_PLUGIN_PATH"] = plugin_path
""".replace("$QT_NAME", qt_libname)
        if should_generate_qt_config
        else ""
    )
    return (
        ENTRY_FILE_TEMPLATE.replace("$PROJECT_NAME", project.name.replace("-", "_"))
        .replace("$ENTRY_NAME", entry_stem)
        .replace("$QT_CONFIG", qt_config)
    )


def prepare_c_source(template: str, entry_file: str, is_debug: bool) -> str:
    """Generate C source code by replacing placeholders in template.

    Args:
        template: C code template with placeholders
        entry_file: Entry file name
        is_debug: Whether to enable debug mode.

    Returns.
    -------
        Generated C source code with placeholders replaced
    """
    # Replace placeholders
    c_code = template.replace("${ENTRY_FILE}", entry_file)
    # Enhanced debug mode control with three levels:
    # 0: Release mode - minimal critical error diagnostics only
    # 1: Debug mode - full verbose output
    # 2: Production with diagnostics - key startup/error info (new)
    if is_debug:
        debug_mode_value = "1"  # Full debug mode
    else:
        # For release builds, enable minimal critical diagnostics
        # This helps troubleshoot silent failures without full debug overhead
        debug_mode_value = "2"  # Production with critical diagnostics
    # Apply the basic replacement first
    c_code = c_code.replace("${DEBUG_MODE}", debug_mode_value)
    # For production with diagnostics mode (level 2), we need to enhance
    # the conditional compilation to show critical startup information
    if debug_mode_value == "2":
        # Replace debug mode headers to show "PRODUCTION DIAGNOSTICS" instead of "DEBUG MODE"
        c_code = c_code.replace("DEBUG MODE - ", "PRODUCTION DIAGNOSTICS - ")
        # Enable critical startup diagnostics by modifying conditionals
        # This allows key startup information to be shown even in production
        c_code = c_code.replace("#if ${DEBUG_MODE}", "#if ${DEBUG_MODE} || ${DEBUG_MODE} == 2")
    return c_code


def compile_c_source(
    c_source_path: str | Path,
    output_filepath: Path,
    compiler: str | None = None,
) -> bool:
    """Compile C source code to executable file."""
    # Find compiler if not specified
    if compiler is None:
        compiler = find_compiler()
        if compiler is None:
            logger.error("Error: No suitable C compiler found (gcc/clang/cl required)")
            return False
    logger.debug("==================================================")
    logger.debug("DEBUG MODE - Compiler Selection")
    logger.debug(f"Selected compiler: {compiler}")
    logger.debug(
        f"Compiler path: {shutil.which(compiler) or 'NOT FOUND'}",
    )
    logger.debug("==================================================")
    # Get compiler arguments
    compiler_args = get_compiler_args(compiler)
    # Prepare paths using pathlib
    c_source_path = Path(c_source_path)
    output_filepath.parent.mkdir(parents=True, exist_ok=True)
    output_filepath = output_filepath.with_suffix(ext)
    # Build compile command
    compiler_name = Path(compiler).name if "\\" in compiler or "/" in compiler else compiler
    if compiler_name.lower() == "cl" or compiler_name.lower() == "cl.exe":
        # MSVC compiler
        cmd = [
            compiler,
            *compiler_args,
            str(c_source_path),
            f"/Fe:{output_filepath}",
            "/link",
            "/SUBSYSTEM:WINDOWS" if "gui" in str(c_source_path).lower() else "/SUBSYSTEM:CONSOLE",
        ]
    else:
        # GCC/Clang compiler
        subsystem_flag = []
        # For Windows GUI, add -mwindows flag with gcc/clang
        if is_windows and "gui" in str(c_source_path).lower():
            subsystem_flag = ["-mwindows"]
        cmd = [
            compiler,
            *compiler_args,
            *subsystem_flag,
            "-o",
            str(output_filepath),
            str(c_source_path),
        ]
    logger.debug("==================================================")
    logger.debug("DEBUG MODE - Compilation Start")
    logger.debug(f"Source file: {c_source_path}")
    logger.debug(f"Output file: {output_filepath}")
    logger.debug(f"Compiler command: {' '.join(cmd)}")
    logger.debug(f"Command length: {len(' '.join(cmd))} characters")
    logger.debug("==================================================")
    try:
        result = subprocess.run(cmd, capture_output=True, text=True, check=False)
        if result.returncode != 0:
            logger.debug("==================================================")
            logger.debug("DEBUG MODE - Compilation FAILED")
            logger.debug(f"Return code: {result.returncode}")
            logger.debug(f"Error occurred at: {time.strftime('%Y-%m-%d %H:%M:%S')}")
            if result.stdout:
                logger.debug(f"Compiler STDOUT:\n{result.stdout}")
            if result.stderr:
                logger.debug(f"Compiler STDERR:\n{result.stderr}")
            logger.debug("==================================================")
            return False
        logger.info(f"Successfully compiled to: {output_filepath}")
        logger.debug("==================================================")
        logger.debug("DEBUG MODE - Compilation SUCCESS")
        logger.debug(
            f"Output file size: {output_filepath.stat().st_size if output_filepath.exists() else 0} bytes",
        )
        logger.debug(f"Compilation completed at: {time.strftime('%Y-%m-%d %H:%M:%S')}")
        logger.debug("==================================================")
        return True
    except FileNotFoundError:
        logger.exception(f"Error: Compiler '{compiler}' not found")
        return False
    except Exception as e:
        logger.exception(f"Error during compilation: {e}")
        return False


@dataclass
class PyLoaderBuilder:
    """Helper class to build individual loaders."""

    parent: PyLoaderGenerator
    project: Project
    entry_file: EntryFile
    is_debug: bool = False

    @cached_property
    def build_dir(self) -> Path:
        """Build directory path."""
        return self.parent.root_dir / _DEFAULT_BUILD_DIR

    @cached_property
    def output_dir(self) -> Path:
        """Output directory path."""
        return self.parent.root_dir / _DEFAULT_OUTPUT_DIR

    @cached_property
    def output_exe(self) -> Path:
        """Output executable path.

        Uses project name as the executable name instead of the entry file name.
        This ensures alarmclock project generates alarmclock.exe instead of gui.exe.
        """
        return self.output_dir / f"{self.project.normalized_name}{ext}"

    @cached_property
    def loader_type(self) -> str:
        """Determine loader type based on entry file.

        Entry file is GUI if:
        - The entry file itself is detected as GUI (contains 'gui' in name or imports GUI libs)
        - Otherwise, fall back to project-level loader_type.
        """
        return "gui" if self.entry_file.is_gui else self.project.loader_type

    @cached_property
    def c_source_path(self) -> Path:
        """C source file path.

        Uses project name for consistency with output_exe naming.
        """
        debug_str = "_debug" if self.is_debug else ""
        loader_type = "console" if self.is_debug else self.loader_type
        return self.output_exe.with_name(f"{self.project.normalized_name}{debug_str}_{loader_type}.c")

    @cached_property
    def entry_filepath(self) -> Path:
        """Entry file path.

        Uses project name for consistency with output_exe naming.
        """
        return self.output_exe.with_suffix(".ent")

    def generate(self) -> bool:
        """Generate loader for a single entry file."""
        t0 = time.perf_counter()
        # Prepare directories
        self.build_dir.mkdir(parents=True, exist_ok=True)
        self.output_dir.mkdir(parents=True, exist_ok=True)
        # Ensure src/__init__.py exists for Python package recognition
        src_dir = self.output_dir / "src"
        src_dir.mkdir(parents=True, exist_ok=True)
        src_init = src_dir / "__init__.py"
        if not src_init.exists():
            src_init.write_text("# src package\n", encoding="utf-8")
            logger.debug(f"Created {src_init}")
        # Generate entry file
        entry_file_code = prepare_entry_file(
            project=self.project,
            entry_stem=self.entry_file.entry_name,
        )
        self.entry_filepath.write_text(entry_file_code, encoding="utf-8")
        logger.debug("==================================================")
        logger.debug("DEBUG MODE - Entry File Generation")
        logger.debug(f"Entry file path: {self.entry_filepath}")
        logger.debug(
            f"Entry file size: {self.entry_filepath.stat().st_size if self.entry_filepath.exists() else 0} bytes",
        )
        logger.debug("Entry file content preview (first 200 chars):")
        if self.entry_filepath.exists():
            content = self.entry_filepath.read_text(encoding="utf-8")[:200]
            logger.debug(f"{content}{'...' if len(content) == 200 else ''}")
        logger.debug("==================================================")
        # Generate and compile C source
        c_template = select_c_template(self.loader_type, self.is_debug)
        c_code = prepare_c_source(c_template, self.entry_filepath.name, self.is_debug)
        self.c_source_path.write_text(c_code, encoding="utf-8")
        logger.debug("==================================================")
        logger.debug("DEBUG MODE - C Source Generation")
        logger.debug(f"C source path: {self.c_source_path}")
        logger.debug(
            f"C source size: {self.c_source_path.stat().st_size if self.c_source_path.exists() else 0} bytes",
        )
        logger.debug(f"Loader type: {self.loader_type}")
        logger.debug(f"Debug mode: {self.is_debug}")
        logger.debug(f"Entry file name: {self.entry_filepath.name}")
        logger.debug("==================================================")
        compiler = find_compiler()
        if not compiler:
            logger.error("==================================================")
            logger.error("DEBUG MODE - Compiler Detection FAILED")
            logger.error("No suitable compiler found in PATH")
            logger.error("Searched for: gcc, clang, cl")
            logger.error(f"Current PATH: {os.environ.get('PATH', 'NOT SET')}")
            logger.error("==================================================")
            return False
        success = compile_c_source(self.c_source_path, self.output_exe, compiler)
        if success:
            logger.info(f"Loader executable generated successfully: {self.output_exe}")
            logger.debug("==================================================")
            logger.debug("DEBUG MODE - Build Summary")
            logger.debug(f"Entry file: {self.entry_file}")
            logger.debug(f"Loader type: {self.loader_type}")
            logger.debug(f"Has Qt: {self.project.has_qt}")
            logger.debug(f"Qt library name: {self.project.qt_libname or 'None'}")
            logger.debug(f"Debug mode: {self.is_debug}")
            logger.debug(f"Build directory: {self.build_dir}")
            logger.debug(f"Output directory: {self.output_dir}")
            logger.debug(f"Output executable: {self.output_exe}")
            logger.debug(f"Compilation time: {time.perf_counter() - t0:.4f} seconds")
            logger.debug(f"Build completed at: {time.strftime('%Y-%m-%d %H:%M:%S')}")
            logger.debug("==================================================")
        else:
            logger.error(f"Failed to compile loader for {self.entry_file.entry_name}")
        return success


@dataclass
class PyLoaderGenerator:
    """Main class for generating Python loader executables."""

    root_dir: Path
    build_dir: Path = field(default_factory=lambda: _DEFAULT_BUILD_DIR)
    output_dir: Path = field(default_factory=lambda: _DEFAULT_OUTPUT_DIR)
    compiler: str | None = None

    @cached_property
    def solution(self) -> Solution:
        """Get the solution from the target directory."""
        return Solution.from_directory(self.root_dir)

    def _is_console_app_project(self, project: Project) -> bool:
        """Determine if project is a console application that should have entry files.

        Args:
            project: Project object to analyze.

        Returns.
        -------
            True if this is a console application project, False if it's likely a library
        """
        # Check for console entry points
        if project.scripts or project.entry_points.get("console_scripts"):
            return True
        # Check for CLI-related keywords
        cli_keywords = {"cli", "command", "tool", "utility", "script"}
        if set(project.keywords) & cli_keywords:
            return True
        # Check for argument parsing libraries in dependencies
        arg_parsing_deps = {"argparse", "click", "typer", "fire", "docopt"}
        if arg_parsing_deps & project.dep_names:
            return True
        # If none of the above indicators are present, it's likely a library
        return False

    def generate_for_project(
        self,
        project: Project,
        project_dir: Path,
        debug: bool = False,
    ) -> bool:
        """Generate loader executables and entry files for a single project.

        Args:
            project: Project information dataclass
            project_dir: Directory containing the project (pyproject.toml location)
            debug: Whether to generate debug version.
        """
        # Detect all entry files in project directory
        entry_files = detect_entry_files(project_dir, project.name)
        if not entry_files:
            # For library projects (no entry files), skip loader generation
            if project.loader_type == "console" and not self._is_console_app_project(
                project,
            ):
                logger.info(
                    f"Library project detected in {project_dir}, skipping loader generation",
                )
                return True
            logger.error(f"No entry files found in {project_dir}")
            return False
        # Generate loaders for all entry files
        for entry_file in entry_files:
            logger.debug(f"Generating loader for: {entry_file.project_name}")
            builder = PyLoaderBuilder(
                parent=self,
                project=project,
                entry_file=entry_file,
                is_debug=debug,
            )
            if not builder.generate():
                return False
        return True

    def run(self, debug: bool = False) -> None:
        """Generate loader executables for all projects concurrently."""
        projects = self.solution.projects
        if not projects:
            logger.error("Failed to load project information")
            return
        success_count = 0
        failed_projects: list[str] = []
        if len(projects) == 1:
            logger.debug("Only one project found, using current directory")
            project_dir = self.root_dir
            if self.generate_for_project(
                project=next(iter(projects.values())),
                project_dir=project_dir,
                debug=debug,
            ):
                success_count += 1
            else:
                failed_projects.append(next(iter(projects)))
        else:
            # Prepare project tasks
            project_tasks = []
            for project_name, project in projects.items():
                # Use the actual directory from toml_path instead of project name
                project_dir = project.toml_path.parent
                if not project_dir.is_dir():
                    logger.error(
                        f"Project directory not found: {project_dir}, skipping...",
                    )
                    failed_projects.append(project_name)
                    continue
                project_tasks.append((project_name, project, project_dir))
            # Execute compilation tasks concurrently
            logger.info(f"Compiling {len(project_tasks)} projects concurrently...")
            with ThreadPoolExecutor(max_workers=None) as executor:
                future_to_project = {
                    executor.submit(
                        self.generate_for_project,
                        project,
                        project_dir,
                        debug,
                    ): project_name
                    for project_name, project, project_dir in project_tasks
                }
                for future in as_completed(future_to_project):
                    project_name = future_to_project[future]
                    try:
                        if future.result():
                            success_count += 1
                        else:
                            failed_projects.append(project_name)
                    except Exception as e:
                        logger.exception(
                            f"Project {project_name} compilation failed: {e}",
                        )
                        failed_projects.append(project_name)
        logger.info(f"Pack {success_count}/{len(projects)} projects successfully")
        if failed_projects:
            logger.error(f"Failed: {failed_projects}")
