<?php
/**
 * 异步导入处理脚本
 * 通过命令行执行，后台处理文件下载
 * 
 * 文件管理规则：
 * 1. 未确认的文件存储在 temp_imports/ 目录
 * 2. 只有导入成功后，文件才会移动到 uploads/ 目录
 * 3. 导入失败的文件会在 temp_imports/ 中保留24小时后自动清理
 */

error_reporting(E_ALL);
ini_set('display_errors', 1);

require_once __DIR__ . '/../MPHX/common.php';

if (!function_exists('import_debug_log')) {
    function import_debug_log($message) {
        // 调试日志已禁用
    }
}

set_time_limit(0);
ini_set('max_execution_time', 0);

// 使用系统临时目录存放导入过程中的临时文件，避免因站点目录权限或同步造成的问题
$temp_base_dir = rtrim(sys_get_temp_dir(), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'bt_program_imports' . DIRECTORY_SEPARATOR;
$temp_dir = $temp_base_dir;

// 程序正式文件仍然存放在站点 uploads 目录
$uploads_dir = ROOT . 'uploads/';
// 程序包统一存放在 uploads/programs 目录下，数据库中的 wj 字段保存相对路径 programs/xxx.zip
$programs_dir = $uploads_dir . 'programs/';

foreach ([$temp_dir, $uploads_dir, $programs_dir] as $dir) {
    if (!is_dir($dir)) {
        mkdir($dir, 0777, true);
    }
}

function fetchProgramData($source_api, $api_key, $program_id) {
    $url = rtrim($source_api, '/') . '/api/programs.php?key=' . urlencode($api_key);
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    
    $response = curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $curl_error = curl_error($ch);
    curl_close($ch);
    
    if ($curl_error) {
        import_debug_log('获取程序数据失败 [curl错误]: ' . $curl_error);
        return false;
    }
    
    if ($http_code != 200) {
        import_debug_log('获取程序数据失败 [HTTP错误]: ' . $http_code);
        return false;
    }
    
    $data = json_decode($response, true);
    if (!$data || !isset($data['data']['programs'])) {
        import_debug_log('获取程序数据失败 [解析错误]');
        return false;
    }
    
    foreach ($data['data']['programs'] as $program) {
        if ($program['id'] == $program_id) {
            return $program;
        }
    }
    
    import_debug_log('程序ID不存在: ' . $program_id);
    return false;
}

function downloadToTemp($url, $temp_dir, $original_filename, $max_retries = 3) {
    $file_extension = pathinfo($original_filename, PATHINFO_EXTENSION);
    if (empty($file_extension)) {
        $file_extension = 'bin';
    }
    
    $temp_filename = 'temp_' . uniqid() . '_' . time() . '.' . strtolower($file_extension);
    $temp_path = $temp_dir . $temp_filename;
    
    $retry_count = 0;
    
    while ($retry_count < $max_retries) {
        $fp = fopen($temp_path, 'w+');
        if (!$fp) {
            import_debug_log("无法创建临时文件: " . $temp_path);
            return false;
        }
        
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_FILE, $fp);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 300);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_HEADER, false);
        
        $success = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $curl_error = curl_error($ch);
        curl_close($ch);
        fclose($fp);
        
        import_debug_log("下载到临时目录 [第" . ($retry_count + 1) . "次] HTTP: " . $http_code);
        
        if ($success && $http_code == 200) {
            if (file_exists($temp_path) && filesize($temp_path) > 0) {
                import_debug_log("下载到临时目录成功: " . $temp_filename . " (" . filesize($temp_path) . " bytes)");
                return $temp_filename;
            }
        }
        
        if ($curl_error) {
            import_debug_log("下载错误: " . $curl_error);
        }
        
        $retry_count++;
        if ($retry_count < $max_retries) {
            sleep(1);
        }
    }
    
    @unlink($temp_path);
    import_debug_log("下载到临时目录失败: " . $original_filename);
    return false;
}

function moveTempToUploads($temp_dir, $temp_filename, $target_dir, $prefix = '') {
    $temp_path = $temp_dir . $temp_filename;
    
    if (!file_exists($temp_path)) {
        import_debug_log("临时文件不存在: " . $temp_path);
        return false;
    }
    
    $file_extension = pathinfo($temp_filename, PATHINFO_EXTENSION);
    $new_filename = $prefix . uniqid() . '_' . time() . '.' . strtolower($file_extension);
    $target_path = $target_dir . $new_filename;
    
    if (!is_dir($target_dir)) {
        mkdir($target_dir, 0777, true);
    }
    
    if (rename($temp_path, $target_path)) {
        import_debug_log("文件移动到正式目录: " . $new_filename);
        return $new_filename;
    } else {
        import_debug_log("移动文件失败: " . $temp_path . " -> " . $target_path);
        return false;
    }
}

function cleanupTempFiles($temp_dir, $max_age_hours = 24) {
    if (!is_dir($temp_dir)) {
        return;
    }
    
    $files = glob($temp_dir . 'temp_*');
    $now = time();
    $max_age = $max_age_hours * 3600;
    
    foreach ($files as $file) {
        if (is_file($file)) {
            $file_age = $now - filemtime($file);
            if ($file_age > $max_age) {
                @unlink($file);
                import_debug_log("清理过期临时文件: " . basename($file) . " (年龄: " . round($file_age/3600, 1) . "小时)");
            }
        }
    }
}

$import_id = isset($argv[1]) ? $argv[1] : (isset($_GET['import_id']) ? $_GET['import_id'] : '');
if (empty($import_id)) {
    import_debug_log('缺少导入ID');
    exit("缺少导入ID\n");
}

$task = $DB->get_row("SELECT * FROM `import_tasks` WHERE `id`='" . daddslashes($import_id) . "'");
if (!$task) {
    import_debug_log('导入任务不存在: ' . $import_id);
    exit("导入任务不存在\n");
}

import_debug_log('开始处理导入任务: ' . $import_id);

cleanupTempFiles($temp_dir);

$DB->query("UPDATE `import_tasks` SET `status`='processing', `updated_at`=NOW() WHERE `id`='" . daddslashes($import_id) . "'");

$programs_data = $task['programs_data'];
// 移除多余空白字符（换行符、制表符等），避免 JSON 解析错误
$programs_data = preg_replace('/\s+/', ' ', $programs_data);
$programs_data = trim($programs_data);
$programs = json_decode($programs_data, true);

if (!is_array($programs)) {
    $error_msg = '程序数据解析失败: ' . json_last_error_msg();
    import_debug_log($error_msg);
    $DB->query("UPDATE `import_tasks` SET `status`='failed', `result`='" . daddslashes($error_msg) . "', `updated_at`=NOW() WHERE `id`='" . daddslashes($import_id) . "'");
    exit($error_msg . "\n");
}

$source_api = $task['source_api'];
$api_key = $task['api_key'];

if (strpos($source_api, '/api/programs.php') !== false) {
    $source_api = substr($source_api, 0, strpos($source_api, '/api/programs.php'));
}
if (strpos($source_api, '?') !== false) {
    $source_api = substr($source_api, 0, strpos($source_api, '?'));
}
$source_api = rtrim($source_api, '/');

import_debug_log('处理后的 source_api: ' . $source_api);

$total = count($programs);
$imported = 0;
$failed_files = array();

import_debug_log('开始导入 ' . $total . ' 个程序');

foreach ($programs as $index => $program) {
    $original_id = $program['id'];
    $progress = round((($index + 1) / $total) * 100);
    
    $DB->query("UPDATE `import_tasks` SET 
        `progress`={$progress}, 
        `current_program`='" . daddslashes($program['name']) . "',
        `updated_at`=NOW() 
        WHERE `id`='" . daddslashes($import_id) . "'");
    
    import_debug_log('处理程序: ' . $program['name'] . ' (ID: ' . $original_id . ')');
    
    $fresh_program = fetchProgramData($source_api, $api_key, $original_id);
    if (!$fresh_program) {
        import_debug_log('无法获取最新数据，使用缓存数据');
        $fresh_program = $program;
    } else {
        import_debug_log('获取到最新数据，wj: ' . ($fresh_program['wj'] ?? '空'));
    }
    
    $temp_files = array();
    $import_success = true;
    
    $temp_tb = '';
    if (!empty($fresh_program['tb'])) {
        $token = isset($fresh_program['tb_token']) ? $fresh_program['tb_token'] : '';
        $download_url = rtrim($source_api, '/') . '/api/download.php?key=' . urlencode($api_key) . '&token=' . urlencode($token) . '&type=tb&file=' . urlencode($fresh_program['tb']);
        import_debug_log('下载图标URL: ' . $download_url);
        $temp_tb = downloadToTemp($download_url, $temp_dir, $fresh_program['tb']);
        if ($temp_tb) {
            $temp_files['tb'] = $temp_tb;
        } else {
            // 图标下载失败不再视为致命错误，只记录失败信息，程序仍然可以导入
            $failed_files[] = '图标: ' . $fresh_program['tb'];
        }
    }
    
    $temp_wj = '';
    if (!empty($fresh_program['wj'])) {
        $token = isset($fresh_program['wj_token']) ? $fresh_program['wj_token'] : '';
        $download_url = rtrim($source_api, '/') . '/api/download.php?key=' . urlencode($api_key) . '&token=' . urlencode($token) . '&type=wj&file=' . urlencode($fresh_program['wj']);
        import_debug_log('下载程序包URL: ' . $download_url);
        $temp_wj = downloadToTemp($download_url, $temp_dir, $fresh_program['wj']);
        if ($temp_wj) {
            $temp_files['wj'] = $temp_wj;
        } else {
            $failed_files[] = '程序包: ' . $fresh_program['wj'];
            $import_success = false;
        }
    }
    
    $temp_images = array();
    if (!empty($fresh_program['images'])) {
        $images = is_array($fresh_program['images']) ? $fresh_program['images'] : json_decode($fresh_program['images'], true);
        if (is_array($images)) {
            foreach ($images as $img) {
                $token = isset($fresh_program['image_tokens'][$img]) ? $fresh_program['image_tokens'][$img] : '';
                $download_url = rtrim($source_api, '/') . '/api/download.php?key=' . urlencode($api_key) . '&token=' . urlencode($token) . '&type=image&file=' . urlencode($img);
                $temp_img = downloadToTemp($download_url, $temp_dir, $img);
                if ($temp_img) {
                    $temp_images[$img] = $temp_img;
                } else {
                    $failed_files[] = '图片: ' . $img;
                }
            }
        }
    }
    
    if (!$import_success) {
        import_debug_log('程序导入失败，关键文件下载失败: ' . $fresh_program['name']);
        foreach ($temp_files as $temp_file) {
            @unlink($temp_dir . $temp_file);
        }
        foreach ($temp_images as $temp_img) {
            @unlink($temp_dir . $temp_img);
        }
        continue;
    }
    
    $field_mapping = array(
        'name' => 'name',
        'js' => 'js',
        'pz' => 'pz',
        'jg' => 'jg',
        'ybd' => 'ybd',
        'pzsj' => 'pzsj',
        'wcts' => 'wcts',
        'type' => 'type',
        'version' => 'version',
        'php_version' => 'php_version',
        'webkj' => 'webkj',
        'sqlkj' => 'sqlkj',
        'alerts' => 'alerts',
        'form_fields' => 'form_fields',
        'install_ops' => 'install_ops',
        'cover' => 'cover',
        'php_ext' => 'php_ext'
    );
    
    $values = array();
    foreach ($field_mapping as $api_field => $db_field) {
        if (isset($fresh_program[$api_field])) {
            $value = $fresh_program[$api_field];
            if (is_array($value)) {
                $value = json_encode($value, JSON_UNESCAPED_UNICODE);
            }
            $values[$db_field] = daddslashes($value);
        }
    }
    
    $required_defaults = array(
        'js' => '',
        'pz' => '',
        'ybd' => '',
        'pzsj' => '',
        'wcts' => '',
        'alerts' => '',
        'form_fields' => '',
        'install_ops' => '',
        'php_ext' => '',
        // 确保这些字段在严格模式下也有默认值，后续会通过 UPDATE 写入真实文件名
        'tb' => '',
        'wj' => '',
        'images' => json_encode(array(), JSON_UNESCAPED_UNICODE)
    );
    
    foreach ($required_defaults as $field => $default) {
        if (!isset($values[$field]) || $values[$field] === '') {
            $values[$field] = $default;
        }
    }
    // 价格字段单独处理：如果接口没有提供，则默认为 0；如果为 '0' 或 0，则保留
    if (!isset($values['jg']) || $values['jg'] === '') {
        $values['jg'] = '0';
    } else {
        // 确保价格不为负数
        $price_value = floatval($values['jg']);
        if ($price_value < 0) {
            import_debug_log('检测到负数价格：' . $values['jg'] . '，已修正为 0');
            $values['jg'] = '0';
        }
    }
    
    $fields = array_keys($values);
    $field_str = '`' . implode('`, `', $fields) . '`';
    $value_str = "'" . implode("', '", $values) . "'";
    
    $insert_sql = "INSERT INTO `bs` ({$field_str}) VALUES ({$value_str})";
    
    if ($DB->query($insert_sql)) {
        $new_program_id = $DB->insert_id();
        import_debug_log('数据库插入成功，新ID: ' . $new_program_id);
        
        $new_tb = '';
        $new_wj = '';
        $new_images = array();
        
        if (!empty($temp_files['tb'])) {
            $new_tb = moveTempToUploads($temp_dir, $temp_files['tb'], $uploads_dir, 'tb_');
        }
        
        if (!empty($temp_files['wj'])) {
            $new_wj = moveTempToUploads($temp_dir, $temp_files['wj'], $programs_dir, 'pkg_');
        }
        
        foreach ($temp_images as $original_name => $temp_img) {
            $new_img = moveTempToUploads($temp_dir, $temp_img, $uploads_dir, 'img_');
            if ($new_img) {
                $new_images[] = $new_img;
            }
        }
        
        // 程序包存放在 uploads/programs 目录下，数据库中保存相对路径，方便统一管理
        $wj_path = $new_wj ? 'programs/' . $new_wj : '';
        
        $update_sql = "UPDATE `bs` SET 
            `tb` = '" . daddslashes($new_tb) . "',
            `wj` = '" . daddslashes($wj_path) . "',
            `images` = '" . daddslashes(json_encode($new_images, JSON_UNESCAPED_UNICODE)) . "'
            WHERE `id` = " . intval($new_program_id);
        
        $DB->query($update_sql);
        import_debug_log('文件路径更新完成: tb=' . $new_tb . ', wj=' . $new_wj);
        
        $imported++;
        import_debug_log('程序导入成功: ' . $fresh_program['name']);
    } else {
        import_debug_log('数据库插入失败: ' . $fresh_program['name'] . ' - ' . $DB->error());
        foreach ($temp_files as $temp_file) {
            @unlink($temp_dir . $temp_file);
        }
        foreach ($temp_images as $temp_img) {
            @unlink($temp_dir . $temp_img);
        }
    }
}

$result_data = array(
    'imported' => $imported,
    'total' => $total,
    'failed_files' => $failed_files
);

$DB->query("UPDATE `import_tasks` SET 
    `status`='completed', 
    `progress`=100, 
    `result`='" . daddslashes(json_encode($result_data, JSON_UNESCAPED_UNICODE)) . "',
    `updated_at`=NOW() 
    WHERE `id`='" . daddslashes($import_id) . "'");

cleanupTempFiles($temp_dir);

import_debug_log('导入完成: 成功 ' . $imported . '/' . $total);
echo "导入完成\n";
?>
