<?php
// 战双TCG · 前端呈现配置下发端点（api/site-ui.php）
//
// 后台「前端控制台」把配置写进 data/admin_frontend.json（该目录 Web 全禁，见 data/.htaccess），
// 本端点读盘后以 CSS / JS / JSON 三种形态下发给玩家前端：
//   GET  ?type=css    → 站点外观 + 模块显隐（在 index.html 的 <head> 用 <link> 引入，零闪烁）
//   GET  ?type=js     → window.ZS_SITE_UI 引导数据（<head> 同步 <script>，body 脚本前就绪）
//   GET  ?type=json   → 原始配置（后台预览与调试用）
//   GET  ?type=meta   → 版本与生效计数（不返回完整配置）
//   POST {cmd:'ack', v:N} → 玩家端回执「我已应用 vN」（后台据此确认配置真的生效了）
//
// 设计约束（与 api/gm.php 一致）：
//   - 只读配置，绝不写盘（唯一的写是 ack 计数，且与配置无关）
//   - 配置缺失 / JSON 损坏 / 任何异常 → 输出空 CSS/JS（HTTP 200），主程序行为与后台未装时完全一致
//   - ETag + 304：未改动时前端零成本；后台每次发布会改版本号，ETag 必变
//   - PHP 5.6~8.4 全兼容

error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
ini_set('display_errors', '0');

require_once __DIR__ . '/frontend-config.php';

$type = isset($_GET['type']) ? strtolower((string)$_GET['type']) : 'css';
if (!in_array($type, array('css', 'js', 'json', 'meta'), true)) $type = 'css';

// ---------------- ack：玩家端回执 ----------------
// 单独处理，避免与配置读取纠缠；失败一律静默（玩家侧不该因为统计失败而报错）

$method = isset($_SERVER['REQUEST_METHOD']) ? strtoupper((string)$_SERVER['REQUEST_METHOD']) : 'GET';
if ($method === 'POST') {
    $raw = @file_get_contents('php://input');
    $body = is_string($raw) ? json_decode($raw, true) : null;
    $cmd = is_array($body) && isset($body['cmd']) ? (string)$body['cmd'] : '';
    header('Content-Type: application/json; charset=utf-8');
    header('Cache-Control: no-store');
    if ($cmd === 'ack') {
        $v = is_array($body) && isset($body['v']) ? (int)$body['v'] : 0;
        zs_fc_ack($v);
        echo '{"ok":true}';
        exit;
    }
    http_response_code(400);
    echo '{"ok":false,"error":"unknown cmd"}';
    exit;
}

// ---------------- 读配置（任何异常都降级为空配置） ----------------

$cfg = null;
try {
    $cfg = zs_fc_read('live');
} catch (Exception $e) {
    $cfg = null;
}
if (!is_array($cfg)) $cfg = zs_fc_defaults();

$version = zs_fc_version($cfg);

// ---------------- 生成输出 ----------------

if ($type === 'css') {
    $text = '';
    try { $text = zs_fc_css($cfg); } catch (Exception $e) { $text = ''; }
    // 版本号为 0 表示「后台从未发布过配置」→ 不下发任何样式，主程序保持出厂外观
    if ($version <= 0) $text = "/* 战双TCG · 站点外观：后台尚未发布配置 */\n";
    $ctype = 'text/css; charset=utf-8';
} else if ($type === 'js') {
    $text = '';
    try { $text = zs_fc_js($cfg); } catch (Exception $e) { $text = ''; }
    if ($version <= 0) $text = "/* 战双TCG · 前端引导：后台尚未发布配置 */\nwindow.ZS_SITE_UI = null;\n";
    $ctype = 'application/javascript; charset=utf-8';
} else if ($type === 'json') {
    $text = json_encode($cfg, defined('JSON_UNESCAPED_UNICODE') ? JSON_UNESCAPED_UNICODE : 0);
    if (!is_string($text)) $text = '{}';
    $ctype = 'application/json; charset=utf-8';
} else {
    // meta：给后台/探针判断「前端是否真的能拿到」
    $ack = zs_fc_ack_read();
    $text = json_encode(array(
        'ok'         => true,
        'version'    => $version,
        'updatedAt'  => isset($cfg['updatedAt']) ? (int)$cfg['updatedAt'] : 0,
        'nodes'      => count($cfg['home']['nodes']),
        'roadmap'    => count($cfg['home']['roadmap']),
        'banners'    => count($cfg['campaign']['banners']),
        'ticker'     => count($cfg['campaign']['ticker']),
        'acks'       => $ack,
    ), defined('JSON_UNESCAPED_UNICODE') ? JSON_UNESCAPED_UNICODE : 0);
    $ctype = 'application/json; charset=utf-8';
}

// ---------------- ETag / 304 ----------------

$etag = zs_fc_etag($text, $cfg);
$inm = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? (string)$_SERVER['HTTP_IF_NONE_MATCH'] : '';
if ($inm !== '' && strpos($inm, $etag) !== false) {
    if (!headers_sent()) {
        header('ETag: ' . $etag);
        header('Cache-Control: no-cache, must-revalidate, max-age=0');
        http_response_code(304);
    }
    exit;
}

while (ob_get_level() > 0) { ob_end_clean(); }
header('Content-Type: ' . $ctype);
header('ETag: ' . $etag);
// 必须每次回源校验：后台发布后前端刷新即刻生效（ETag 命中时仍是 304，代价极低）
header('Cache-Control: no-cache, must-revalidate, max-age=0');
header('X-Content-Type-Options: nosniff');
header('X-ZS-Frontend-Version: ' . $version);
echo $text;
