<?php
/**
 * 跨站节点对接API - 被对接方
 * 提供给对接方调用的API接口
 */
define('IN_API', true);
define('A__A_AAA_', 'AAAAAAA_A');
require_once dirname(__DIR__) . '/includes/common.php';

header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET');
header('Access-Control-Allow-Headers: Content-Type');

$action = isset($_GET['action']) ? trim($_GET['action']) : '';
$appId = isset($_REQUEST['app_id']) ? trim($_REQUEST['app_id']) : '';
$timestamp = isset($_REQUEST['timestamp']) ? intval($_REQUEST['timestamp']) : 0;
$sign = isset($_REQUEST['sign']) ? trim($_REQUEST['sign']) : '';

/**
 * 返回JSON响应
 */
function jsonExit($code, $msg, $data = null) {
    global $auth;
    $response = ['code' => $code, 'msg' => $msg];
    if ($data !== null) {
        $response['data'] = $data;
    }
    // 添加响应签名
    if ($auth && isset($auth['app_secret'])) {
        $response['sign'] = strtoupper(md5(json_encode($response, JSON_UNESCAPED_UNICODE) . $auth['app_secret']));
    }
    exit(json_encode($response, JSON_UNESCAPED_UNICODE));
}

/**
 * 生成签名
 */
function generateSign($params, $secret) {
    ksort($params);
    $signStr = '';
    foreach ($params as $k => $v) {
        if ($k !== 'sign' && $v !== '') {
            $signStr .= $k . '=' . $v . '&';
        }
    }
    $signStr .= 'key=' . $secret;
    return strtoupper(md5($signStr));
}

/**
 * 验证签名
 */
function verifySign($params, $secret, $sign) {
    $expectedSign = generateSign($params, $secret);
    return $sign === $expectedSign;
}

/**
 * 记录访问日志
 */
function logAccess($appId, $nodeId, $action, $qq = null) {
    global $DB;
    $DB->exec("INSERT INTO pre_node_auth_log (app_id, node_id, action, qq, ip, addtime) VALUES (?, ?, ?, ?, ?, NOW())", 
        [$appId, $nodeId, $action, $qq, $_SERVER['REMOTE_ADDR'] ?? '']);
}

// 基础校验
if (empty($action)) {
    jsonExit(400, '缺少action参数');
}

if (empty($appId)) {
    jsonExit(400, '缺少app_id参数');
}

// 时间戳校验（5分钟有效期）
if ($timestamp <= 0 || abs(time() - $timestamp) > 300) {
    jsonExit(401, '请求已过期');
}

// 获取授权信息
$auth = $DB->getRow("SELECT * FROM pre_node_auth WHERE app_id = ?", [$appId]);
if (!$auth) {
    jsonExit(403, '未授权的app_id');
}

if ($auth['status'] != 1) {
    jsonExit(403, '授权已被禁用');
}

// 检查授权是否过期
if ($auth['expire_time'] && strtotime($auth['expire_time']) < time()) {
    jsonExit(403, '授权已过期');
}

// 验证签名
$params = array_merge($_GET, $_POST);
// 排除 action 和 debug 参数（这些是辅助参数，不参与签名）
unset($params['action']);
unset($params['debug']);

// 调试模式：可通过URL参数 debug=1 获取详细信息（仅用于调试，生产环境请删除）
$isDebug = isset($_REQUEST['debug']) && $_REQUEST['debug'] == '1';

if (!verifySign($params, $auth['app_secret'], $sign)) {
    if ($isDebug) {
        $expectedSign = generateSign($params, $auth['app_secret']);
        jsonExit(403, '签名验证失败', [
            'received_sign' => $sign,
            'expected_sign' => $expectedSign,
            'server_time' => time(),
            'client_timestamp' => $timestamp,
            'time_diff' => time() - $timestamp,
            'params' => $params
        ]);
    }
    jsonExit(403, '签名验证失败');
}

/**
 * 获取授权的节点ID列表
 */
function getAuthorizedNodeIds($auth) {
    global $DB;
    
    $nodeIds = [];
    
    switch ($auth['auth_type']) {
        case 1: // 全站节点
            $rs = $DB->query("SELECT id FROM pre_loginconfig WHERE status = 1");
            while ($row = $rs->fetch()) {
                $nodeIds[] = $row['id'];
            }
            break;
            
        case 2: // 分类节点
            $classId = intval($auth['class_id']);
            $rs = $DB->query("SELECT id FROM pre_loginconfig WHERE cids = ? AND status = 1", [$classId]);
            while ($row = $rs->fetch()) {
                $nodeIds[] = $row['id'];
            }
            break;
            
        case 3: // 单节点
            $nodeIds[] = intval($auth['node_id']);
            break;
    }
    
    return $nodeIds;
}

/**
 * 获取分类信息
 */
function getClassInfo($classId) {
    global $DB;
    return $DB->getRow("SELECT id, name FROM pre_login_class WHERE id = ?", [$classId]);
}

// 处理不同操作
switch ($action) {
    // 获取节点列表
    case 'list':
        $nodeIds = getAuthorizedNodeIds($auth);
        
        if (empty($nodeIds)) {
            jsonExit(404, '没有可用的授权节点');
        }
        
        $nodes = [];
        $placeholders = implode(',', array_fill(0, count($nodeIds), '?'));
        $rs = $DB->query(
            "SELECT id, citybz, cids, biz, msg, max, online_census, show_online_census, status 
             FROM pre_loginconfig 
             WHERE id IN ($placeholders) AND status = 1 
             ORDER BY sort ASC, id ASC", 
            $nodeIds
        );
        
        $classList = [];
        while ($row = $rs->fetch()) {
            // 获取分类名称
            $className = '';
            if ($row['cids']) {
                if (!isset($classList[$row['cids']])) {
                    $classInfo = getClassInfo($row['cids']);
                    $classList[$row['cids']] = $classInfo ? $classInfo['name'] : '';
                }
                $className = $classList[$row['cids']];
            }
            
            $rowBiz = isset($row['biz']) ? trim((string)$row['biz']) : 'cloud';
            if (!in_array($rowBiz, ['cloud', 'dg'], true)) {
                $rowBiz = 'cloud';
            }
            $nodes[] = [
                'node_id' => (int)$row['id'],
                'name' => $row['citybz'],
                'class_id' => (int)$row['cids'],
                'class_name' => $className,
                'biz' => $rowBiz,
                'msg' => $row['msg'],
                'max' => (int)$row['max'],
                'online_census' => (int)$row['online_census'],
                'show_online_census' => (int)$row['show_online_census'],
                'status' => (int)$row['status']
            ];
        }
        
        logAccess($appId, 0, 'list');
        
        jsonExit(0, 'success', [
            'nodes' => $nodes,
            'expire_time' => $auth['expire_time'],
            'auth_type' => (int)$auth['auth_type']
        ]);
        break;
        
    // 获取节点配置（同步用）
    case 'sync':
        $nodeId = isset($_REQUEST['node_id']) ? intval($_REQUEST['node_id']) : 0;
        
        if ($nodeId <= 0) {
            jsonExit(400, '缺少node_id参数');
        }
        
        $nodeIds = getAuthorizedNodeIds($auth);
        if (!in_array($nodeId, $nodeIds)) {
            jsonExit(403, '无权访问该节点');
        }
        
        $row = $DB->getRow("SELECT type, cid, protocol FROM pre_loginconfig WHERE id = ? AND status = 1", [$nodeId]);
        if (!$row) {
            jsonExit(404, '节点不存在');
        }
        
        logAccess($appId, $nodeId, 'sync');
        
        // 获取协议列表：优先使用节点自定义协议，否则从协议表获取
        $protocolList = null;
        if (!empty($row['protocol'])) {
            // 节点有自定义协议
            $protocolList = $row['protocol'];
        } elseif (!empty($row['cid'])) {
            // 从协议表获取该 cid 的协议列表
            $protocolArr = [];
            $rs = $DB->query("SELECT type, name, is_pwd FROM pre_protocol WHERE cid = ? AND status = 1 ORDER BY sort ASC", [$row['cid']]);
            while ($p = $rs->fetch(PDO::FETCH_ASSOC)) {
                $protocolArr[] = [
                    'type' => $p['type'],
                    'name' => $p['name'],
                    'is_pwd' => $p['is_pwd']
                ];
            }
            if (!empty($protocolArr)) {
                $protocolList = json_encode($protocolArr, JSON_UNESCAPED_UNICODE);
            }
        }
        
        jsonExit(0, 'success', [
            'node_id' => $nodeId,
            'type' => $row['type'],
            'cid' => $row['cid'],
            'protocol' => $protocolList
        ]);
        break;
        
    // 获取敏感配置（登录时实时获取）
    case 'config':
        $nodeId = isset($_REQUEST['node_id']) ? intval($_REQUEST['node_id']) : 0;
        
        if ($nodeId <= 0) {
            jsonExit(400, '缺少node_id参数');
        }
        
        $nodeIds = getAuthorizedNodeIds($auth);
        if (!in_array($nodeId, $nodeIds)) {
            jsonExit(403, '无权访问该节点');
        }
        
        $row = $DB->getRow("SELECT url, query_api, type, cid FROM pre_loginconfig WHERE id = ? AND status = 1", [$nodeId]);
        if (!$row) {
            jsonExit(404, '节点不存在');
        }
        
        logAccess($appId, $nodeId, 'config');
        
        // 获取框架通讯密钥：使用全局配置
        global $conf;
        $httpkey = $conf['httpkey'] ?? '';
        
        jsonExit(0, 'success', [
            'node_id' => $nodeId,
            'url' => $row['url'],
            'query_api' => $row['query_api'],
            'type' => $row['type'],
            'cid' => $row['cid'],
            'httpkey' => $httpkey
        ]);
        break;
        
    // 获取分类列表
    case 'classes':
        $nodeIds = getAuthorizedNodeIds($auth);
        
        if (empty($nodeIds)) {
            jsonExit(404, '没有可用的授权节点');
        }
        
        $placeholders = implode(',', array_fill(0, count($nodeIds), '?'));
        $classIds = [];
        $rs = $DB->query("SELECT DISTINCT cids FROM pre_loginconfig WHERE id IN ($placeholders) AND cids > 0", $nodeIds);
        while ($row = $rs->fetch()) {
            $classIds[] = $row['cids'];
        }
        
        $classes = [];
        if (!empty($classIds)) {
            $placeholders = implode(',', array_fill(0, count($classIds), '?'));
            $rs = $DB->query("SELECT id, name, biz FROM pre_login_class WHERE id IN ($placeholders) ORDER BY sort ASC", $classIds);
            while ($row = $rs->fetch()) {
                $classes[] = [
                    'id' => (int)$row['id'],
                    'name' => $row['name'],
                    'biz' => $row['biz']
                ];
            }
        }
        
        jsonExit(0, 'success', [
            'classes' => $classes
        ]);
        break;
        
    default:
        jsonExit(400, '无效的操作');
}
