<?php
declare(strict_types=1);

const API_BASE_URL = 'http://bee20243000.com:5005';
const CONFIG_CATEGORY = '短链配置';
const ADMIN_TOKEN = 'bee2024888';
const DEVICE_NAME = '宝塔PHP短链';
const CACHE_TTL_SECONDS = 1800;
const REQUEST_TIMEOUT_SECONDS = 15;
const FALLBACK_LINKS = [
    'bzX4i' => 'https://link.3ceng.cn/view/6b68e5ee',
    '7fYSP' => 'https://pan.quark.cn/s/ff53221f81ec',
    'xYPZG' => 'https://qaci4lwnvmw.feishu.cn/docx/Nl4tdJj8poGZGUx99TdcHNvenyd',
    'lIWc1' => 'https://qaci4lwnvmw.feishu.cn/docx/UKNjdSCX3o6ugDxh5focXOZxnng',
];

$configListUrl = API_BASE_URL . '/api/config/list';
$sysLogAddUrl = API_BASE_URL . '/api/sys_log/add';
$cacheFile = __DIR__ . '/short_links_cache.json';

function json_response(array $data, int $status = 200): void
{
    http_response_code($status);
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

function post_json(string $url, array $payload): array
{
    $body = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);

    if (function_exists('curl_init')) {
        $curl = curl_init($url);
        curl_setopt_array($curl, [
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $body,
            CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => REQUEST_TIMEOUT_SECONDS,
        ]);
        $response = curl_exec($curl);
        $error = curl_error($curl);
        curl_close($curl);

        if ($response === false) {
            throw new RuntimeException('请求接口失败：' . $error);
        }
    } else {
        $context = stream_context_create([
            'http' => [
                'method' => 'POST',
                'header' => "Content-Type: application/json\r\n",
                'content' => $body,
                'timeout' => REQUEST_TIMEOUT_SECONDS,
                'ignore_errors' => true,
            ],
        ]);

        $response = @file_get_contents($url, false, $context);
    }

    if ($response === false) {
        throw new RuntimeException('请求接口失败：' . $url);
    }

    $result = json_decode($response, true);
    if (!is_array($result)) {
        throw new RuntimeException('接口返回不是有效 JSON');
    }

    return $result;
}

function is_success_response(array $result): bool
{
    return in_array($result['code'] ?? null, [0, 200], true);
}

function response_body(array $result): array
{
    $data = $result['data'] ?? $result['body'] ?? [];
    return is_array($data) ? $data : [];
}

function submit_sync_log(string $title, string $level, array $detail): void
{
    global $configListUrl, $sysLogAddUrl;

    try {
        post_json($sysLogAddUrl, [
            'category' => CONFIG_CATEGORY,
            'title' => $title,
            'detail' => json_encode($detail, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
            'level' => $level,
            'device_name' => DEVICE_NAME,
            'url' => $configListUrl,
        ]);
    } catch (Throwable $e) {
        error_log('短链同步日志提交失败：' . $e->getMessage());
    }
}

function refresh_links(): array
{
    global $configListUrl, $cacheFile;

    $startedAt = microtime(true);
    $page = 1;
    $pages = 0;
    $total = 0;
    $links = [];

    while (true) {
        $result = post_json($configListUrl, [
            'category' => CONFIG_CATEGORY,
            'key' => '',
            'value' => '',
            'page' => $page,
            'page_size' => 1000,
            'sort_by' => 'sort',
        ]);

        if (!is_success_response($result)) {
            throw new RuntimeException((string)($result['msg'] ?? '短链配置加载失败'));
        }

        $data = response_body($result);
        $items = $data['items'] ?? [];
        $pages++;

        if (is_array($items)) {
            foreach ($items as $item) {
                if (!is_array($item)) {
                    continue;
                }
                $key = trim((string)($item['key'] ?? ''));
                $value = trim((string)($item['value'] ?? ''));
                if ($key !== '' && $value !== '') {
                    $links[$key] = $value;
                }
            }
        }

        $total = (int)($data['total'] ?? 0);
        $pageSize = (int)($data['page_size'] ?? (is_countable($items) ? count($items) : 1000));
        if ($pageSize <= 0 || $page * $pageSize >= $total || empty($items)) {
            break;
        }
        $page++;
    }

    if (!$links) {
        $links = FALLBACK_LINKS;
    }

    $cache = [
        'category' => CONFIG_CATEGORY,
        'links' => $links,
        'count' => count($links),
        'last_loaded_at' => time(),
        'last_error' => null,
    ];

    file_put_contents($cacheFile, json_encode($cache, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX);

    submit_sync_log('短链配置同步成功', 'INFO', [
        'category' => CONFIG_CATEGORY,
        'loaded_count' => count($links),
        'api_total' => $total,
        'pages' => $pages,
        'duration_ms' => (int)((microtime(true) - $startedAt) * 1000),
    ]);

    return $cache;
}

function read_cache(): array
{
    global $cacheFile;

    if (!is_file($cacheFile)) {
        return [
            'category' => CONFIG_CATEGORY,
            'links' => [],
            'count' => 0,
            'last_loaded_at' => null,
            'last_error' => null,
        ];
    }

    $cache = json_decode((string)file_get_contents($cacheFile), true);
    return is_array($cache) ? $cache : [
        'category' => CONFIG_CATEGORY,
        'links' => [],
        'count' => 0,
        'last_loaded_at' => null,
        'last_error' => '缓存文件格式错误',
    ];
}

function load_links(bool $force = false): array
{
    global $cacheFile;

    $cache = read_cache();
    $expired = !is_file($cacheFile) || time() - (int)($cache['last_loaded_at'] ?? 0) >= CACHE_TTL_SECONDS;

    if (!$force && !$expired) {
        return $cache;
    }

    try {
        return refresh_links();
    } catch (Throwable $e) {
        $cache['last_error'] = $e->getMessage();
        submit_sync_log('短链配置同步失败', 'ERROR', [
            'category' => CONFIG_CATEGORY,
            'error' => $e->getMessage(),
            'cached_count' => count($cache['links'] ?? []),
        ]);
        return $cache;
    }
}

function check_admin_token(): bool
{
    return ($_GET['token'] ?? '') === ADMIN_TOKEN || ($_POST['token'] ?? '') === ADMIN_TOKEN;
}

function format_time($timestamp): string
{
    return $timestamp ? date('Y-m-d H:i:s', (int)$timestamp) : '-';
}

function render_admin_page(array $cache, ?string $message = null, ?string $error = null): void
{
    $links = $cache['links'] ?? [];
    ksort($links);

    header('Content-Type: text/html; charset=utf-8');
    ?>
<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>短链列表</title>
  <style>
    body { font-family: Arial, sans-serif; margin: 32px; color: #222; }
    main { max-width: 1100px; }
    .toolbar { display: flex; gap: 12px; align-items: center; margin: 16px 0; flex-wrap: wrap; }
    button { padding: 8px 12px; border: 0; border-radius: 5px; background: #222; color: #fff; cursor: pointer; }
    table { width: 100%; border-collapse: collapse; table-layout: fixed; }
    th, td { padding: 9px 10px; border-bottom: 1px solid #e5e5e5; text-align: left; vertical-align: top; }
    th { background: #f5f5f5; }
    td { overflow-wrap: anywhere; }
    .code { width: 220px; font-family: Consolas, monospace; }
    .muted { color: #666; }
    .ok { color: #147a31; }
    .error { color: #b00020; }
    a { color: #0645ad; }
  </style>
</head>
<body>
  <main>
    <h1>短链列表</h1>
    <?php if ($message): ?><p class="ok"><?= htmlspecialchars($message, ENT_QUOTES, 'UTF-8') ?></p><?php endif; ?>
    <?php if ($error): ?><p class="error"><?= htmlspecialchars($error, ENT_QUOTES, 'UTF-8') ?></p><?php endif; ?>
    <div class="toolbar">
      <form method="post">
        <input type="hidden" name="token" value="<?= htmlspecialchars(ADMIN_TOKEN, ENT_QUOTES, 'UTF-8') ?>">
        <button type="submit">主动刷新</button>
      </form>
      <span class="muted">共 <?= count($links) ?> 条，最近成功同步：<?= htmlspecialchars(format_time($cache['last_loaded_at'] ?? null), ENT_QUOTES, 'UTF-8') ?></span>
    </div>
    <table>
      <thead>
        <tr>
          <th class="code">短码</th>
          <th>目标链接</th>
        </tr>
      </thead>
      <tbody>
      <?php if ($links): ?>
        <?php foreach ($links as $code => $target): ?>
          <tr>
            <td class="code"><?= htmlspecialchars((string)$code, ENT_QUOTES, 'UTF-8') ?></td>
            <td><a href="<?= htmlspecialchars((string)$target, ENT_QUOTES, 'UTF-8') ?>" target="_blank" rel="noopener noreferrer"><?= htmlspecialchars((string)$target, ENT_QUOTES, 'UTF-8') ?></a></td>
          </tr>
        <?php endforeach; ?>
      <?php else: ?>
        <tr><td colspan="2" class="muted">当前缓存为空，可以先点击主动刷新。</td></tr>
      <?php endif; ?>
      </tbody>
    </table>
  </main>
</body>
</html>
    <?php
    exit;
}

$path = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH) ?: '/';
$shortCode = trim(rawurldecode($path), '/');

if ($path === '/' || $path === '') {
    $cache = load_links();
    json_response([
        'service' => 'short-link',
        'total_links' => count($cache['links'] ?? []),
        'cache' => [
            'category' => CONFIG_CATEGORY,
            'count' => count($cache['links'] ?? []),
            'last_loaded_at' => $cache['last_loaded_at'] ?? null,
            'last_error' => $cache['last_error'] ?? null,
        ],
        'admin' => [
            'links' => '/admin/links?token=' . ADMIN_TOKEN,
        ],
    ]);
}

if ($shortCode === 'admin/links') {
    if (!check_admin_token()) {
        json_response(['error' => 'forbidden'], 403);
    }

    $message = null;
    $error = null;
    $cache = load_links();

    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $cache = load_links(true);
        if (!empty($cache['last_error'])) {
            $error = '刷新失败：' . $cache['last_error'];
        } else {
            $message = '刷新成功，当前缓存 ' . count($cache['links'] ?? []) . ' 条短链。';
        }
    }

    render_admin_page($cache, $message, $error);
}

if (in_array($shortCode, ['favicon.ico', 'robots.txt'], true)) {
    http_response_code(404);
    exit;
}

$cache = load_links();
$links = $cache['links'] ?? [];
$target = is_array($links) ? ($links[$shortCode] ?? null) : null;

if (!$target) {
    json_response([
        'error' => "短链 '{$shortCode}' 不存在",
        'tip' => '请检查短码是否正确',
    ], 404);
}

header('Location: ' . $target, true, 302);
exit;
