<?php
require_once 'MPHX/common.php';

header('Content-Type: application/json; charset=UTF-8');

$my = isset($_GET['my']) ? $_GET['my'] : '';
$gn = isset($_GET['gn']) ? $_GET['gn'] : '';

if ($my != $conf['api']) {
    exit(json_encode(array('code' => -1, 'msg' => 'API密钥错误')));
}

/**
 * 使用shell_exec调用curl获取宝塔API数据
 * 用于解决PHP curl库连接宝塔API失败的问题
 * 支持HTTP和HTTPS自动切换（优先使用数据库配置的协议）
 */
function bt_api_request($bt_panel, $bt_key, $endpoint, $post_data = array()) {
    $now_time = time();
    $request_token = md5($now_time . '' . md5($bt_key));
    
    $post_data['request_token'] = $request_token;
    $post_data['request_time'] = $now_time;
    $post_str = http_build_query($post_data);
    
    // 构建URL（API调用不需要安全入口）
    $url = rtrim($bt_panel, '/') . $endpoint;
    
    // 使用curl命令行工具，添加-k参数忽略SSL证书验证
    $cmd = "curl -sk -X POST '{$url}' -d '{$post_str}' 2>&1";
    $output = shell_exec($cmd);
    
    // 尝试解析JSON
    $data = json_decode($output, true);
    if ($data !== null) {
        return $data;
    }
    
    // 如果不是JSON，返回原始输出
    return array('status' => false, 'raw_output' => $output);
}

/**
 * 获取宝塔面板URL（根据数据库配置自动选择HTTP/HTTPS）
 * @param array $bt 宝塔配置数组
 * @return string 面板URL
 */
function get_bt_panel_url($bt) {
    // 优先使用数据库中配置的协议（aqfw字段）
    if (isset($bt['aqfw']) && $bt['aqfw'] == 'true') {
        $protocol = 'https';
    } else {
        $protocol = 'http';
    }
    
    return $protocol . '://' . $bt['ip'] . ':' . $bt['dk'];
}

switch ($gn) {
    case 'web':
        $result = run_monitor_task('web', '空间监控', 'monitor_web_space');
        break;
    case 'sql':
        $result = run_monitor_task('sql', '数据库监控', 'monitor_sql_space');
        break;
    case 'fh':
        $result = run_monitor_task('fh', '流量监控', 'monitor_flow');
        break;
    case 'fhq':
        $result = run_monitor_task('fhq', '流量清零', 'clear_flow');
        break;
    case 'ywjkdel':
        $result = monitor_domain_delete();
        break;
    case 'cleanup':
        $result = run_monitor_task('cleanup', '临时文件清理', 'cleanup_temp_files');
        break;
    case 'stop_expire':
        $result = run_expire_task('stop_expire', '到期自动停止', 'run_auto_stop_expire');
        break;
    case 'delete_expire':
        $result = run_expire_task('delete_expire', '到期自动删除', 'run_auto_delete_expire');
        break;
    case 'all':
        $result = run_all_monitor_tasks();
        break;
    default:
        $result = array('code' => -1, 'msg' => '功能代码错误');
}

echo json_encode($result);

/**
 * 运行监控任务并记录日志
 */
function run_monitor_task($task_type, $task_name, $callback) {
    global $DB;
    
    $start_time = microtime(true);
    $start_datetime = date('Y-m-d H:i:s');
    
    try {
        // 执行实际任务
        $result = call_user_func($callback);
        
        $execution_time = round(microtime(true) - $start_time, 3);
        $status = ($result['code'] == 1) ? 'success' : 'failed';
        $output = json_encode($result, JSON_UNESCAPED_UNICODE);
        
        // 记录执行日志
        $DB->query("INSERT INTO `cron_monitor_logs` (`task_name`, `task_type`, `status`, `output`, `execution_time`, `created_at`) VALUES ('{$task_name}', '{$task_type}', '{$status}', '" . daddslashes($output) . "', {$execution_time}, '{$start_datetime}')");
        
        // 更新统计信息
        $DB->query("INSERT INTO `cron_monitor_stats` (`task_type`, `task_name`, `total_count`, `success_count`, `fail_count`, `last_run_time`, `last_run_status`) VALUES ('{$task_type}', '{$task_name}', 1, " . ($status == 'success' ? 1 : 0) . ", " . ($status == 'failed' ? 1 : 0) . ", '{$start_datetime}', '{$status}') ON DUPLICATE KEY UPDATE total_count = total_count + 1, success_count = success_count + " . ($status == 'success' ? 1 : 0) . ", fail_count = fail_count + " . ($status == 'failed' ? 1 : 0) . ", last_run_time = '{$start_datetime}', last_run_status = '{$status}'");
        
        return $result;
        
    } catch (Exception $e) {
        $execution_time = round(microtime(true) - $start_time, 3);
        $status = 'failed';
        $output = $e->getMessage();
        
        // 记录错误日志
        $DB->query("INSERT INTO `cron_monitor_logs` (`task_name`, `task_type`, `status`, `output`, `execution_time`, `created_at`) VALUES ('{$task_name}', '{$task_type}', '{$status}', '" . daddslashes($output) . "', {$execution_time}, '{$start_datetime}')");
        
        // 更新统计信息
        $DB->query("INSERT INTO `cron_monitor_stats` (`task_type`, `task_name`, `total_count`, `success_count`, `fail_count`, `last_run_time`, `last_run_status`) VALUES ('{$task_type}', '{$task_name}', 1, 0, 1, '{$start_datetime}', '{$status}') ON DUPLICATE KEY UPDATE total_count = total_count + 1, fail_count = fail_count + 1, last_run_time = '{$start_datetime}', last_run_status = '{$status}'");
        
        return array('code' => -1, 'msg' => '执行失败: ' . $e->getMessage());
    }
}

function monitor_web_space() {
    global $DB;
    $zjs = $DB->query("SELECT * FROM `zj` WHERE `zt`='正常'");
    $count = 0;
    while ($zj = $DB->fetch($zjs)) {
        $bt = $DB->get_row("SELECT * FROM `bt` WHERE `id`='{$zj['btid']}'");
        if (!$bt) continue;
        
        $bt_api = new bt_api();
        $protocol = isset($bt['aqfw']) && $bt['aqfw'] == 'true' ? 'https' : 'http';
        $bt_api->BT_PANEL = $protocol . '://' . $bt['ip'] . ':' . $bt['dk'];
        $bt_api->BT_KEY = $bt['key'];
        
        $path = $bt['czzt'] == 'Linux' ? '/www/wwwroot/' . $zj['user'] : 'D:/wwwroot/' . $zj['user'];
        // 使用 GetDirSize 获取目录大小
        $dir_size_str = $bt_api->GetDirSize($path);
        
        if ($dir_size_str) {
            // 解析字符串格式的大小
            $size = parse_size_string($dir_size_str);
            // wypj以MB存储，转换为字节
            $limit = floatval($zj['wypj']) * 1024 * 1024;
            
            if ($size > $limit) {
                $result = $bt_api->ztweb($zj['webid'], $zj['user']);
                $DB->query("UPDATE `zj` SET `zt`='已暂停' WHERE `id`='{$zj['id']}'");
                logjl($zj['user'], '系统监控', '网页空间超限，主机已暂停', true);
                $count++;
            }
        }
    }
    return array('code' => 1, 'msg' => '监控完成，暂停了' . $count . '个主机');
}

function monitor_sql_space() {
    global $DB;
    $zjs = $DB->query("SELECT * FROM `zj` WHERE `zt`='正常'");
    $count = 0;
    while ($zj = $DB->fetch($zjs)) {
        $bt = $DB->get_row("SELECT * FROM `bt` WHERE `id`='{$zj['btid']}'");
        if (!$bt) continue;
        
        $bt_api = new bt_api();
        $protocol = isset($bt['aqfw']) && $bt['aqfw'] == 'true' ? 'https' : 'http';
        $bt_api->BT_PANEL = $protocol . '://' . $bt['ip'] . ':' . $bt['dk'];
        $bt_api->BT_KEY = $bt['key'];
        
        $sql_info = $bt_api->sqlkjhq($zj['sqldb']);
        
        if ($sql_info && isset($sql_info['data_size'])) {
            // 修正：将字符串格式的大小转换为字节数
            $size = parse_size_string($sql_info['data_size']);
            // sypj以MB存储，转换为字节
            $limit = floatval($zj['sypj']) * 1024 * 1024;
            
            if ($size > $limit) {
                $result = $bt_api->ztweb($zj['webid'], $zj['user']);
                $DB->query("UPDATE `zj` SET `zt`='已暂停' WHERE `id`='{$zj['id']}'");
                logjl($zj['user'], '系统监控', '数据库空间超限，主机已暂停', true);
                $count++;
            }
        }
    }
    return array('code' => 1, 'msg' => '监控完成，暂停了' . $count . '个主机');
}

/**
 * 解析大小字符串（如 "11.10KB"）为字节数
 */
function parse_size_string($size_str) {
    if (is_numeric($size_str)) {
        return intval($size_str);
    }
    
    if (preg_match('/([\d.]+)\s*([KMGT]?[Bb])/i', $size_str, $matches)) {
        $value = floatval($matches[1]);
        $unit = strtoupper($matches[2]);
        switch ($unit) {
            case 'B': return $value;
            case 'KB': return $value * 1024;
            case 'MB': return $value * 1024 * 1024;
            case 'GB': return $value * 1024 * 1024 * 1024;
            case 'TB': return $value * 1024 * 1024 * 1024 * 1024;
        }
    }
    
    return 0;
}

function monitor_flow() {
    global $DB;
    $zjs = $DB->query("SELECT * FROM `zj` WHERE `zt`='正常'");
    $count = 0;
    $today = date('Y-m-d');

    while ($zj = $DB->fetch($zjs)) {
        $bt = $DB->get_row("SELECT * FROM `bt` WHERE `id`='{$zj['btid']}'");
        if (!$bt) continue;

        // 使用数据库配置的协议（HTTP/HTTPS）
        $bt_panel = get_bt_panel_url($bt);
        $bt_key = $bt['key'];

        // 使用shell_exec方式获取网站列表，找到正确的网站名称
        $sites_data = bt_api_request($bt_panel, $bt_key, '/data?action=getData&table=sites', array('limit' => 100, 'p' => 1));
        $site_name = '';

        if (isset($sites_data['data']) && is_array($sites_data['data'])) {
            foreach ($sites_data['data'] as $site) {
                // 查找路径包含用户名的网站
                if (isset($site['path']) && strpos($site['path'], $zj['user']) !== false) {
                    $site_name = $site['name'];
                    break;
                }
            }
        }

        // 如果没找到，使用默认域名
        if (empty($site_name)) {
            $site_name = $zj['user'] . '.a116.vip';
        }

        // 使用shell_exec方式获取日志
        $log_data = bt_api_request($bt_panel, $bt_key, '/site?action=GetSiteLogs', array('siteName' => $site_name));

        $flow = 0;
        $traffic_in = 0;
        $traffic_out = 0;
        $request_count = 0;

        if (isset($log_data['status']) && $log_data['status'] && !empty($log_data['msg'])) {
            $msg = $log_data['msg'];

            // 全角引号和斜杠转换（宝塔日志使用全角引号）
            $msg_fixed = str_replace('＂', '"', $msg);
            $msg_fixed = str_replace('／', '/', $msg_fixed);

            // 解析日志行
            $lines = explode("\n", $msg_fixed);

            foreach ($lines as $line) {
                if (empty(trim($line))) continue;

                // 解析日志格式: IP - - [时间] "METHOD URL" 状态码 流量
                // 匹配: "GET / HTTP/1.1" 200 917
                if (preg_match('/"(\w+)\s+[^\s]+\s+HTTP[^"]*"\s+(\d+)\s+(\d+)/', $line, $matches)) {
                    $bytes = intval($matches[3]);
                    if ($bytes > 0) {
                        $request_count++;
                        $traffic_out += $bytes; // 出站流量
                    }
                }
            }

            $flow = $traffic_in + $traffic_out;
        }

        // 将流量数据写入数据库
        if ($flow > 0 || $request_count > 0) {
            // 检查今天是否已有记录
            $existing = $DB->get_row("SELECT * FROM `traffic_stats` WHERE `user_id`='{$zj['id']}' AND `stat_date`='{$today}'");

            if ($existing) {
                // 累加流量数据
                $new_traffic_in = $existing['traffic_in'] + $traffic_in;
                $new_traffic_out = $existing['traffic_out'] + $traffic_out;
                $new_traffic_total = $existing['traffic_total'] + $flow;
                $new_request_count = $existing['request_count'] + $request_count;
                
                $DB->query("UPDATE `traffic_stats` SET
                    `traffic_in`='{$new_traffic_in}',
                    `traffic_out`='{$new_traffic_out}',
                    `traffic_total`='{$new_traffic_total}',
                    `request_count`='{$new_request_count}',
                    `update_time`=NOW()
                    WHERE `id`='{$existing['id']}'");
            } else {
                // 插入新记录
                $DB->query("INSERT INTO `traffic_stats`
                    (`user_id`, `bt_id`, `stat_date`, `traffic_in`, `traffic_out`, `traffic_total`, `request_count`, `create_time`, `update_time`)
                    VALUES ('{$zj['id']}', '{$zj['btid']}', '{$today}', '{$traffic_in}', '{$traffic_out}', '{$flow}', '{$request_count}', NOW(), NOW())");
            }
        }

        // 检查流量是否超限（使用累计流量）
        $today_stats = $DB->get_row("SELECT * FROM `traffic_stats` WHERE `user_id`='{$zj['id']}' AND `stat_date`='{$today}'");
        $total_flow = $today_stats ? $today_stats['traffic_total'] : $flow;
        $limit = $zj['llxz'] * 1024 * 1024 * 1024;
        if ($total_flow > $limit && $limit > 0) {
            // 暂停网站
            bt_api_request($bt_panel, $bt_key, '/site?action=SiteStop', array('id' => $zj['webid'], 'name' => $site_name));
            $DB->query("UPDATE `zj` SET `zt`='已暂停' WHERE `id`='{$zj['id']}'");
            logjl($zj['user'], '系统监控', '流量超限，主机已暂停', true);
            $count++;
        }
    }
    return array('code' => 1, 'msg' => '监控完成，暂停了' . $count . '个主机');
}

function clear_flow() {
    global $DB;
    $result = $DB->query("UPDATE `zj` SET `llxz`='0'");
    return array('code' => 1, 'msg' => '流量清零完成');
}

function monitor_domain_delete() {
    global $conf, $DB;
    
    if ($conf['ymjkkg'] != 'true') {
        return array('code' => 1, 'msg' => '域名监控未开启');
    }
    
    $threshold = intval($conf['ymjktsyz']);
    $zjs = $DB->query("SELECT * FROM `zj` WHERE `zt`='正常'");
    $count = 0;
    
    while ($zj = $DB->fetch($zjs)) {
        $bt = $DB->get_row("SELECT * FROM `bt` WHERE `id`='{$zj['btid']}'");
        if (!$bt) continue;
        
        $bt_api = new bt_api();
        $bt_api->BT_PANEL = 'http://' . $bt['ip'] . ':' . $bt['dk'];
        $bt_api->BT_KEY = $bt['key'];
        
        $ym_list = $bt_api->Getymlist($zj['webid']);
        
        if ($ym_list && isset($ym_list['domains']) && count($ym_list['domains']) == 0) {
            $days = (time() - strtotime($zj['dqsj'])) / 86400;
            
            if ($days > $threshold) {
                $bt_api->delsite($zj['webid'], $zj['user']);
                $DB->query("DELETE FROM `zj` WHERE `id`='{$zj['id']}'");
                
                if ($conf['mtyxfskg'] == 'true' && !empty($zj['email'])) {
                    sendEmail($zj['email'], '主机删除通知', '您的主机 ' . $zj['user'] . ' 因未绑定域名且超过' . $threshold . '天已被删除');
                }
                
                logjl($zj['user'], '系统监控', '未绑定域名超过' . $threshold . '天，主机已删除', true);
                $count++;
            }
        }
    }
    
    return array('code' => 1, 'msg' => '监控完成，删除了' . $count . '个主机');
}

function cleanup_temp_files() {
    global $DB;
    
    $cleanup_stats = array(
        'temp_zip_files' => 0,
        'temp_dirs' => 0,
        'user_zip_files' => 0,
        'unused_upload_files' => 0,
        'total_size' => 0
    );
    
    // ==================== 1. 清理系统临时目录中的过期压缩包 ====================
    $temp_dir = sys_get_temp_dir();
    $cleanup_time = time() - 86400; // 24小时前
    
    $zip_files = glob($temp_dir . '/*.zip');
    foreach ($zip_files as $zip_file) {
        $file_time = filemtime($zip_file);
        
        if ($file_time < $cleanup_time) {
            $file_size = filesize($zip_file);
            if (unlink($zip_file)) {
                $cleanup_stats['temp_zip_files']++;
                $cleanup_stats['total_size'] += $file_size;
            }
        }
    }
    
    // ==================== 2. 清理程序导出/导入临时文件夹 ====================
    $temp_patterns = array(
        $temp_dir . '/program_export_*',
        $temp_dir . '/program_import_*'
    );
    
    foreach ($temp_patterns as $pattern) {
        $dirs = glob($pattern, GLOB_ONLYDIR);
        foreach ($dirs as $dir) {
            $dir_time = filemtime($dir);
            
            if ($dir_time < $cleanup_time) {
                $dir_size = getDirSize($dir);
                if (removeDir($dir)) {
                    $cleanup_stats['temp_dirs']++;
                    $cleanup_stats['total_size'] += $dir_size;
                }
            }
        }
    }
    
    // ==================== 3. 清理用户目录中的过期压缩包 ====================
    $cleanup_time_user = time() - (7 * 86400); // 7天前
    
    $users = $DB->query("SELECT id, user, webid, btid FROM `zj` WHERE `zt`='正常'");
    
    while ($user = $DB->fetch($users)) {
        $username = $user['user'];
        
        $bt = $DB->get_row("SELECT * FROM `bt` WHERE `id`='{$user['btid']}'");
        if (!$bt) {
            continue;
        }
        
        $site = $DB->get_row("SELECT * FROM `ym` WHERE `id`='{$user['webid']}'");
        if (!$site) {
            continue;
        }
        
        $site_root = '/www/wwwroot/' . $site['ym'];
        
        if (!is_dir($site_root)) {
            continue;
        }
        
        $zip_files = glob($site_root . '/archive_*.zip');
        foreach ($zip_files as $zip_file) {
            $file_time = filemtime($zip_file);
            
            if ($file_time < $cleanup_time_user) {
                $file_size = filesize($zip_file);
                if (unlink($zip_file)) {
                    $cleanup_stats['user_zip_files']++;
                    $cleanup_stats['total_size'] += $file_size;
                }
            }
        }
    }
    
    // ==================== 4. 清理uploads目录中的未使用文件 ====================
    $uploads_dir = '/www/wwwroot/www.a116.vip/uploads/';
    $cleanup_time_upload = time() - (30 * 86400); // 30天前
    
    if (is_dir($uploads_dir)) {
        $referenced_files = array();
        
        $res = $DB->query("SELECT tb, wj, images FROM `bs`");
        while ($row = $DB->fetch($res)) {
            if (!empty($row['tb'])) {
                $referenced_files[$row['tb']] = true;
            }
            if (!empty($row['wj'])) {
                $referenced_files[$row['wj']] = true;
            }
            if (!empty($row['images'])) {
                $images = json_decode($row['images'], true);
                if (is_array($images)) {
                    foreach ($images as $img) {
                        $referenced_files[$img] = true;
                    }
                }
            }
        }
        
        $iterator = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($uploads_dir, RecursiveDirectoryIterator::SKIP_DOTS),
            RecursiveIteratorIterator::CHILD_FIRST
        );
        
        foreach ($iterator as $fileinfo) {
            if ($fileinfo->isFile()) {
                $relative_path = str_replace($uploads_dir, '', $fileinfo->getPathname());
                
                if (!isset($referenced_files[$relative_path])) {
                    $file_time = $fileinfo->getMTime();
                    
                    if ($file_time < $cleanup_time_upload) {
                        $file_size = $fileinfo->getSize();
                        if (unlink($fileinfo->getPathname())) {
                            $cleanup_stats['unused_upload_files']++;
                            $cleanup_stats['total_size'] += $file_size;
                        }
                    }
                }
            }
        }
    }
    
    logjl('system', '临时文件清理', "清理完成，释放空间: " . formatSize($cleanup_stats['total_size']), true);
    
    return array(
        'code' => 1, 
        'msg' => '清理完成',
        'data' => $cleanup_stats
    );
}

function formatSize($bytes) {
    $units = array('B', 'KB', 'MB', 'GB', 'TB');
    $bytes = max($bytes, 0);
    $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
    $pow = min($pow, count($units) - 1);
    $bytes /= pow(1024, $pow);
    return round($bytes, 2) . ' ' . $units[$pow];
}

function getDirSize($dir) {
    $size = 0;
    $iterator = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
        RecursiveIteratorIterator::CHILD_FIRST
    );
    
    foreach ($iterator as $fileinfo) {
        if ($fileinfo->isFile()) {
            $size += $fileinfo->getSize();
        }
    }
    
    return $size;
}

function removeDir($dir) {
    if (!is_dir($dir)) {
        return false;
    }
    
    $iterator = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
        RecursiveIteratorIterator::CHILD_FIRST
    );
    
    foreach ($iterator as $fileinfo) {
        if ($fileinfo->isFile()) {
            unlink($fileinfo->getPathname());
        } elseif ($fileinfo->isDir()) {
            rmdir($fileinfo->getPathname());
        }
    }
    
    return rmdir($dir);
}

/**
 * 运行到期任务并记录日志
 */
function run_expire_task($task_type, $task_name, $callback) {
    global $DB;
    
    $start_time = microtime(true);
    $start_datetime = date('Y-m-d H:i:s');
    
    try {
        // 直接调用函数执行逻辑，不使用 shell_exec（Web环境可能禁用）
        $result = call_user_func($callback);
        
        $output = isset($result['output']) ? $result['output'] : json_encode($result, JSON_UNESCAPED_UNICODE);
        $execution_time = round(microtime(true) - $start_time, 3);
        $status = ($result['code'] == 1) ? 'success' : 'failed';
        
        // 记录执行日志
        $DB->query("INSERT INTO `cron_monitor_logs` (`task_name`, `task_type`, `status`, `output`, `execution_time`, `created_at`) VALUES ('{$task_name}', '{$task_type}', '{$status}', '" . daddslashes($output) . "', {$execution_time}, '{$start_datetime}')");
        
        // 更新统计信息
        $DB->query("INSERT INTO `cron_monitor_stats` (`task_type`, `task_name`, `total_count`, `success_count`, `fail_count`, `last_run_time`, `last_run_status`) VALUES ('{$task_type}', '{$task_name}', 1, " . ($status == 'success' ? 1 : 0) . ", " . ($status == 'failed' ? 1 : 0) . ", '{$start_datetime}', '{$status}') ON DUPLICATE KEY UPDATE total_count = total_count + 1, success_count = success_count + " . ($status == 'success' ? 1 : 0) . ", fail_count = fail_count + " . ($status == 'failed' ? 1 : 0) . ", last_run_time = '{$start_datetime}', last_run_status = '{$status}'");
        
        return $result;
        
    } catch (Exception $e) {
        $execution_time = round(microtime(true) - $start_time, 3);
        $status = 'failed';
        $output = $e->getMessage();
        
        // 记录错误日志
        $DB->query("INSERT INTO `cron_monitor_logs` (`task_name`, `task_type`, `status`, `output`, `execution_time`, `created_at`) VALUES ('{$task_name}', '{$task_type}', '{$status}', '" . daddslashes($output) . "', {$execution_time}, '{$start_datetime}')");
        
        // 更新统计信息
        $DB->query("INSERT INTO `cron_monitor_stats` (`task_type`, `task_name`, `total_count`, `success_count`, `fail_count`, `last_run_time`, `last_run_status`) VALUES ('{$task_type}', '{$task_name}', 1, 0, 1, '{$start_datetime}', '{$status}') ON DUPLICATE KEY UPDATE total_count = total_count + 1, fail_count = fail_count + 1, last_run_time = '{$start_datetime}', last_run_status = '{$status}'");
        
        return array('code' => -1, 'msg' => '执行失败: ' . $e->getMessage());
    }
}

/**
 * 执行自动停止到期主机
 */
function run_auto_stop_expire() {
    global $DB;
    
    $today = date('Y-m-d');
    $now = date('Y-m-d H:i:s');
    $output = "[{$now}] 开始检查到期用户...\n";
    
    // 获取设置
    $settings = array();
    $result = $DB->query("SELECT * FROM `expire_settings`");
    while ($row = $DB->fetch($result)) {
        $settings[$row['setting_key']] = $row['setting_value'];
    }
    
    $expire_pause_days = intval($settings['expire_pause_days'] ?? 0);
    $stop_deadline = date('Y-m-d', strtotime("-{$expire_pause_days} days"));
    
    $output .= "[{$now}] 设置: 到期后 {$expire_pause_days} 天暂停，停止截止日期: {$stop_deadline}\n";
    
    // 获取所有已到期且状态正常的用户（排除到期时间为空的主机）
    $users = $DB->query("SELECT * FROM `zj` WHERE `dqsj` IS NOT NULL AND `dqsj` != '' AND `dqsj` < '{$stop_deadline}' AND `zt`='正常'");
    
    $stopped_count = 0;
    $error_count = 0;
    
    while ($user = $DB->fetch($users)) {
        $username = $user['user'];
        $webid = $user['webid'];
        $btid = $user['btid'];
        
        $expired_days = floor((strtotime($today) - strtotime($user['dqsj'])) / (60 * 60 * 24));
        $output .= "[{$now}] 处理用户: {$username}, 到期时间: {$user['dqsj']}, 已过期 {$expired_days} 天\n";
        
        // 获取宝塔服务器信息
        $bt = $DB->get_row("SELECT * FROM `bt` WHERE `id`='{$btid}'");
        if (!$bt) {
            $output .= "[{$now}] 错误: 无法获取宝塔服务器信息\n";
            $error_count++;
            continue;
        }
        
        // 初始化宝塔API
        $bt_api = new bt_api();
        $protocol = isset($bt['aqfw']) && $bt['aqfw'] == 'true' ? 'https' : 'http';
        $bt_api->BT_PANEL = $protocol . '://' . $bt['ip'] . ':' . $bt['dk'];
        $bt_api->BT_KEY = $bt['key'];
        
        // 停止网站
        $stop_result = $bt_api->ztweb($webid, $username);
        
        if (isset($stop_result['status']) && $stop_result['status']) {
            // 更新用户状态为已过期
            $DB->query("UPDATE `zj` SET `zt`='已过期' WHERE `id`='{$user['id']}'");
            
            // 记录日志
            logjl($username, '到期自动停止', "主机已到期 {$expired_days} 天，自动停止服务", true);
            
            $output .= "[{$now}] 成功: 用户 {$username} 的网站已停止\n";
            $stopped_count++;
        } else {
            $error_msg = isset($stop_result['msg']) ? $stop_result['msg'] : '未知错误';
            $output .= "[{$now}] 错误: 停止用户 {$username} 的网站失败 - {$error_msg}\n";
            $error_count++;
        }
    }
    
    $output .= "[{$now}] 检查完成: 停止 {$stopped_count} 个网站, 失败 {$error_count} 个\n";
    
    return array('code' => 1, 'msg' => "检查完成: 停止 {$stopped_count} 个网站, 失败 {$error_count} 个", 'output' => $output);
}

/**
 * 执行自动删除到期主机
 */
function run_auto_delete_expire() {
    global $DB;
    
    $today = date('Y-m-d');
    $now = date('Y-m-d H:i:s');
    $output = "[{$now}] 开始检查需要删除的过期用户...\n";
    
    // 获取设置
    $settings = array();
    $result = $DB->query("SELECT * FROM `expire_settings`");
    while ($row = $DB->fetch($result)) {
        $settings[$row['setting_key']] = $row['setting_value'];
    }
    
    $pause_delete_days = intval($settings['pause_delete_days'] ?? 7);
    $delete_deadline = date('Y-m-d', strtotime("-{$pause_delete_days} days"));
    
    $output .= "[{$now}] 设置: 暂停后 {$pause_delete_days} 天删除，删除截止日期: {$delete_deadline}\n";
    
    // 获取所有已暂停超过指定天数的用户（排除到期时间为空的主机）
    $users = $DB->query("SELECT * FROM `zj` WHERE `zt`='已过期' AND `dqsj` IS NOT NULL AND `dqsj` != '' AND `dqsj` <= '{$delete_deadline}'");
    
    $deleted_count = 0;
    $error_count = 0;
    
    while ($user = $DB->fetch($users)) {
        $username = $user['user'];
        $webid = $user['webid'];
        $btid = $user['btid'];
        
        $paused_days = floor((strtotime($today) - strtotime($user['dqsj'])) / (60 * 60 * 24));
        $output .= "[{$now}] 处理用户: {$username}, 已暂停 {$paused_days} 天\n";
        
        // 获取宝塔服务器信息
        $bt = $DB->get_row("SELECT * FROM `bt` WHERE `id`='{$btid}'");
        if (!$bt) {
            $output .= "[{$now}] 错误: 无法获取宝塔服务器信息\n";
            $error_count++;
            continue;
        }
        
        // 初始化宝塔API
        $bt_api = new bt_api();
        $protocol = isset($bt['aqfw']) && $bt['aqfw'] == 'true' ? 'https' : 'http';
        $bt_api->BT_PANEL = $protocol . '://' . $bt['ip'] . ':' . $bt['dk'];
        $bt_api->BT_KEY = $bt['key'];
        
        // 使用delsite删除网站，它会同时删除FTP和数据库
        if ($webid) {
            $web_result = $bt_api->delsite($webid, $username);
            if (!isset($web_result['status']) || !$web_result['status']) {
                $error_msg = isset($web_result['msg']) ? $web_result['msg'] : '未知错误';
                $output .= "[{$now}] 警告: 删除网站失败 - {$error_msg}\n";
                $error_count++;
                continue;
            } else {
                $output .= "[{$now}] 成功: 删除网站及相关数据\n";
            }
        }
        
        // 从数据库删除用户记录
        $DB->query("DELETE FROM `zj` WHERE `id`='{$user['id']}'");
        
        // 记录日志
        logjl($username, '到期自动删除', "主机已暂停 {$paused_days} 天，自动删除", true);
        
        $output .= "[{$now}] 成功: 用户 {$username} 的所有数据已删除\n";
        $deleted_count++;
    }
    
    $output .= "[{$now}] 检查完成: 删除 {$deleted_count} 个用户, 失败 {$error_count} 个\n";
    
    return array('code' => 1, 'msg' => "检查完成: 删除 {$deleted_count} 个用户, 失败 {$error_count} 个", 'output' => $output);
}

/**
 * 执行所有监控任务
 */
function run_all_monitor_tasks() {
    global $DB;
    
    $now = date('Y-m-d H:i:s');
    $results = array();
    $total_success = 0;
    $total_failed = 0;
    $full_output = "[{$now}] 开始执行所有监控任务...\n\n";
    
    // 定义要执行的任务列表
    $tasks = array(
        array('type' => 'web', 'name' => '空间监控', 'callback' => 'monitor_web_space'),
        array('type' => 'sql', 'name' => '数据库监控', 'callback' => 'monitor_sql_space'),
        array('type' => 'fh', 'name' => '流量监控', 'callback' => 'monitor_flow'),
        array('type' => 'cleanup', 'name' => '临时文件清理', 'callback' => 'cleanup_temp_files'),
        array('type' => 'stop_expire', 'name' => '到期自动停止', 'callback' => 'run_auto_stop_expire'),
        array('type' => 'delete_expire', 'name' => '到期自动删除', 'callback' => 'run_auto_delete_expire'),
    );
    
    foreach ($tasks as $task) {
        $task_start = microtime(true);
        $full_output .= "===== {$task['name']} =====\n";
        
        try {
            $result = call_user_func($task['callback']);
            $task_time = round(microtime(true) - $task_start, 3);
            
            if ($result['code'] == 1) {
                $total_success++;
                $status = 'success';
                $full_output .= "✓ 成功 ({$task_time}s): {$result['msg']}\n";
            } else {
                $total_failed++;
                $status = 'failed';
                $full_output .= "✗ 失败 ({$task_time}s): {$result['msg']}\n";
            }
            
            if (isset($result['output'])) {
                $full_output .= $result['output'] . "\n";
            }
            
            $results[] = array(
                'name' => $task['name'],
                'status' => $status,
                'time' => $task_time,
                'msg' => $result['msg']
            );
            
        } catch (Exception $e) {
            $total_failed++;
            $task_time = round(microtime(true) - $task_start, 3);
            $full_output .= "✗ 异常 ({$task_time}s): {$e->getMessage()}\n\n";
            
            $results[] = array(
                'name' => $task['name'],
                'status' => 'error',
                'time' => $task_time,
                'msg' => $e->getMessage()
            );
        }
    }
    
    $full_output .= "\n[{$now}] 所有任务执行完成: 成功 {$total_success} 个, 失败 {$total_failed} 个\n";
    
    // 记录到专门的"全部执行"统计
    $start_datetime = date('Y-m-d H:i:s');
    $DB->query("INSERT INTO `cron_monitor_stats` (`task_type`, `task_name`, `total_count`, `success_count`, `fail_count`, `last_run_time`, `last_run_status`) VALUES ('all', '全部监控任务', 1, {$total_success}, {$total_failed}, '{$start_datetime}', '" . ($total_failed == 0 ? 'success' : 'failed') . "') ON DUPLICATE KEY UPDATE total_count = total_count + 1, success_count = success_count + {$total_success}, fail_count = fail_count + {$total_failed}, last_run_time = '{$start_datetime}', last_run_status = '" . ($total_failed == 0 ? 'success' : 'failed') . "'");
    
    return array(
        'code' => ($total_failed == 0 ? 1 : -1),
        'msg' => "全部任务执行完成: 成功 {$total_success} 个, 失败 {$total_failed} 个",
        'output' => $full_output,
        'details' => $results
    );
}
?>
