<?php
/**
 * AES-128-CBC 加密接口（PHP 版）
 * 兼容原 Node 服务：/ 与 /cipher 返回 Base64 密文，/health 健康检查
 *
 * 宝塔 Nginx 伪静态（网站设置 → 伪静态）可加：
 *   location / {
 *     try_files $uri $uri/ /index.php?$query_string;
 *   }
 *   location ~* ^/(config\.json|plaintext\.txt|access\.log)$ {
 *     deny all;
 *   }
 */

header('Access-Control-Allow-Origin: *');

$baseDir = __DIR__;
$configPath = $baseDir . '/config.json';
$plaintextPath = $baseDir . '/plaintext.txt';
$logPath = $baseDir . '/access.log';

function load_config(string $path): array
{
    $raw = file_get_contents($path);
    if ($raw === false) {
        throw new RuntimeException('无法读取 config.json');
    }
    if (substr($raw, 0, 3) === "\xEF\xBB\xBF") {
        $raw = substr($raw, 3);
    }
    $data = json_decode($raw, true);
    if (!is_array($data) || empty($data['key']) || empty($data['iv'])) {
        throw new RuntimeException('config.json 无效或缺少 key/iv');
    }
    return $data;
}

function read_plaintext(string $path): string
{
    $raw = file_get_contents($path);
    if ($raw === false) {
        throw new RuntimeException('无法读取 plaintext.txt');
    }
    if (substr($raw, 0, 3) === "\xEF\xBB\xBF") {
        $raw = substr($raw, 3);
    }
    return rtrim($raw, "\r\n");
}

/** AES-128-CBC + PKCS7，返回 Base64（与 Node createCipheriv 一致） */
function aes128_cbc_encrypt(string $plaintext, string $key, string $iv): string
{
    if (strlen($key) !== 16 || strlen($iv) !== 16) {
        throw new RuntimeException('key/iv 必须各为 16 字节（AES-128）');
    }
    $raw = openssl_encrypt($plaintext, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);
    if ($raw === false) {
        throw new RuntimeException('加密失败: ' . (openssl_error_string() ?: 'unknown'));
    }
    return base64_encode($raw);
}

function client_ip(): string
{
    $ip = $_SERVER['HTTP_X_REAL_IP']
        ?? $_SERVER['HTTP_X_FORWARDED_FOR']
        ?? $_SERVER['REMOTE_ADDR']
        ?? 'unknown';
    if (strpos($ip, ',') !== false) {
        $ip = trim(explode(',', $ip)[0]);
    }
    if (strpos($ip, '::ffff:') === 0) {
        $ip = substr($ip, 7);
    }
    return $ip;
}

function write_log(string $logPath, string $method, string $url, int $status, ?string $extra = null): void
{
    $ua = substr($_SERVER['HTTP_USER_AGENT'] ?? '', 0, 100);
    $line = sprintf(
        "[%s]  IP: %s  %s %s  -> %d",
        date('Y-m-d H:i:s'),
        client_ip(),
        $method,
        $url,
        $status
    );
    if ($ua !== '') {
        $line .= '  UA: ' . $ua;
    }
    if ($extra !== null && $extra !== '') {
        $line .= '  错误: ' . $extra;
    }
    $line .= PHP_EOL;
    @file_put_contents($logPath, $line, FILE_APPEND | LOCK_EX);
}

function send_json(int $status, array $obj): void
{
    http_response_code($status);
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($obj, JSON_UNESCAPED_UNICODE);
}

$path = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH);
$path = $path === null || $path === '' ? '/' : $path;
// 若站点不在域名根目录（例如 /api/xxx），只取最后一段路由
$scriptDir = rtrim(str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME'] ?? '')), '/');
if ($scriptDir !== '' && $scriptDir !== '/' && strpos($path, $scriptDir) === 0) {
    $path = substr($path, strlen($scriptDir)) ?: '/';
}
$path = '/' . trim($path, '/');
if ($path !== '/') {
    $path = rtrim($path, '/');
}

$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
$reqUrl = $_SERVER['REQUEST_URI'] ?? $path;

if ($path === '/' || $path === '/cipher' || $path === '/index.php' || $path === '/cipher.php') {
    try {
        $config = load_config($configPath);
        $cipher = aes128_cbc_encrypt(read_plaintext($plaintextPath), $config['key'], $config['iv']);
        http_response_code(200);
        header('Content-Type: text/plain; charset=utf-8');
        header('Cache-Control: no-store');
        echo $cipher;
        write_log($logPath, $method, $reqUrl, 200);
    } catch (Throwable $e) {
        send_json(500, ['error' => $e->getMessage()]);
        write_log($logPath, $method, $reqUrl, 500, $e->getMessage());
    }
    exit;
}

if ($path === '/health' || $path === '/health.php') {
    send_json(200, ['status' => 'ok']);
    write_log($logPath, $method, $reqUrl, 200);
    exit;
}

send_json(404, ['error' => 'Not found']);
write_log($logPath, $method, $reqUrl, 404);
