<?php
/**
 * 芋头CMS
 * ============================================================================
 * 版权所有 2016-2028 沅陵县乌托邦网络服务有限公司，并保留所有权利。
 * 网站地址: http://www.yutoucms.cn
 * ----------------------------------------------------------------------------
 * 如果商业用途务必到官方购买正版授权, 以免引起不必要的法律纠纷.
 * ============================================================================
 * Author: 芋头 <mxgsf@qq.com>
 * Date: 2026-6-10
 */

if (!defined('ROOT_PATH')) define('ROOT_PATH', dirname(__DIR__, 2) . '/');
if (!defined('LICENSE_CENTER_URL')) define('LICENSE_CENTER_URL', 'http://yutou.wtbidc.cn/license-center');

require_once ROOT_PATH . 'core/lib/license.php';
require_once ROOT_PATH . 'core/lib/cms_upgrade_workspace_support.php';
$license = new \Core\Lib\License();
$licenseInfo = $license->getStatus();
$currentVersion = \Core\Lib\License::VERSION;
$apiBase = LICENSE_CENTER_URL;
$msg = '';
$msgType = '';

$ch = curl_init($apiBase . '/api.php?action=check_update');
curl_setopt_array($ch, [
    CURLOPT_TIMEOUT => 10,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_SSL_VERIFYPEER => false,
]);
$resp = curl_exec($ch);
curl_close($ch);

$remoteInfo = $resp ? json_decode($resp, true) : null;
$latestVersion = $remoteInfo['data']['latest_version'] ?? $currentVersion;
$changelog = $remoteInfo['data']['changelog'] ?? '';

function versionCompareSafe($v1, $v2)
{
    $a1 = explode('.', $v1);
    $a2 = explode('.', $v2);
    $max = max(count($a1), count($a2));
    for ($i = 0; $i < $max; $i++) {
        $n1 = isset($a1[$i]) ? intval($a1[$i]) : 0;
        $n2 = isset($a2[$i]) ? intval($a2[$i]) : 0;
        if ($n1 > $n2) return 1;
        if ($n1 < $n2) return -1;
    }
    return 0;
}

function getUpgradeDirSize($dir)
{
    $metaFile = rtrim($dir, '/\\') . '/upgrade_meta.json';
    $meta = is_file($metaFile) ? json_decode((string) file_get_contents($metaFile), true) : null;
    return is_array($meta) ? intval($meta['backup_bytes'] ?? 0) : 0;
}

$hasNew = versionCompareSafe($latestVersion, $currentVersion) > 0;
$upgradeTargetVersion = versionCompareSafe($latestVersion, $currentVersion) >= 0 ? $latestVersion : $currentVersion;
$canUpgradeOnline = $license->canOnlineUpgrade();
$levelNames = [1 => '免费版', 2 => '基础版', 3 => '专业版'];

$backupList = [];
$backupBaseDir = ROOT_PATH . 'core/backup/';
if (is_dir($backupBaseDir)) {
    $dirs = glob($backupBaseDir . '*', GLOB_ONLYDIR);
    foreach (array_reverse($dirs) as $dir) {
        $backupList[] = [
            'dir' => basename($dir),
            'time' => date('Y-m-d H:i:s', filemtime($dir)),
            'size' => getUpgradeDirSize($dir),
        ];
    }
}
?>
<div class="page-container fade-in">
    <div class="page-header">
        <div>
            <h2 style="font-size:16px;font-weight:600;color:var(--dark);margin:0;">
                <svg style="width:22px;height:22px;color:var(--primary);margin-right:8px;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                    <polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 1 0 .49-4.5"/>
                </svg> 版本管理
            </h2>
            <p style="font-size:12px;color:var(--text-light);margin:4px 0 0 0;">查看当前版本、检查更新并执行在线升级</p>
        </div>
        <div style="display:flex;gap:10px;">
            <?php if ($canUpgradeOnline): ?>
            <form class="js-upgrade-form" method="post" style="margin:0;">
                <input type="hidden" name="target_version" value="<?php echo htmlspecialchars($upgradeTargetVersion); ?>">
                <button type="submit" class="btn btn-primary" style="padding:10px 18px;">
                    <?php echo $hasNew ? ('升级到 v' . htmlspecialchars($latestVersion)) : '修复当前版本'; ?>
                </button>
            </form>
            <?php else: ?>
            <a href="/admin/main.php?act=auth" class="btn" style="padding:10px 18px;background:linear-gradient(135deg,#ea580c 0%,#dc2626 100%);color:#fff;border:none;border-radius:10px;text-decoration:none;font-weight:700;">
                <?php echo $canUpgradeOnline ? '授权信息' : '升级授权'; ?>
            </a>
            <?php endif; ?>
        </div>
    </div>

    <?php if ($msg): ?>
    <div style="padding:14px 16px;background:<?php echo $msgType === 'success' ? '#f0fdf4' : '#fef2f2'; ?>;color:<?php echo $msgType === 'success' ? '#16a34a' : '#dc2626'; ?>;border-radius:8px;font-size:13px;margin-top:16px;border:1px solid <?php echo $msgType === 'success' ? '#bbf7d0' : '#fecaca'; ?>;">
        <?php echo nl2br(htmlspecialchars($msg)); ?>
    </div>
    <?php endif; ?>

    <section class="upgrade-progress" id="upgradeProgress" hidden aria-live="polite">
        <div class="upgrade-progress__head"><div><span class="upgrade-progress__eyebrow">ONLINE UPDATE</span><h3 id="upgradeProgressTitle">准备升级</h3></div><strong id="upgradeProgressPercent">0%</strong></div>
        <div class="upgrade-progress__track"><span id="upgradeProgressBar"></span></div>
        <div class="upgrade-progress__steps">
            <div data-upgrade-step="download"><i>1</i><span><strong>下载升级包</strong><small>从授权中心安全获取</small></span></div>
            <div data-upgrade-step="extract"><i>2</i><span><strong>校验并解压</strong><small>核对版本与文件校验和</small></span></div>
            <div data-upgrade-step="copy"><i>3</i><span><strong>备份并更新</strong><small>分批覆盖，避免执行超时</small></span></div>
            <div data-upgrade-step="finalize"><i>4</i><span><strong>完成升级</strong><small>清理临时文件并记录备份</small></span></div>
        </div>
        <div class="upgrade-progress__status"><span class="upgrade-progress__pulse"></span><span id="upgradeProgressMessage">正在初始化升级任务…</span></div>
        <div class="upgrade-progress__error" id="upgradeProgressError" hidden></div>
    </section>

    <div class="page-context-bar">
        <div class="page-context-item"><span class="page-context-label">当前版本</span><span class="page-context-value">v<?php echo htmlspecialchars($currentVersion); ?></span></div>
        <div class="page-context-item"><span class="page-context-label">最新版本</span><span class="page-context-value"><?php echo $hasNew ? 'v' . htmlspecialchars($latestVersion) : '已是最新'; ?></span></div>
        <div class="page-context-item"><span class="page-context-label">在线升级权限</span><span class="page-context-value"><?php echo $canUpgradeOnline ? '已授权' : '未授权'; ?></span></div>
        <div class="page-context-item"><span class="page-context-label">授权说明</span><span class="page-context-value page-context-muted"><?php echo $canUpgradeOnline ? (($levelNames[$licenseInfo['level']] ?? '已授权') . ' 可在线升级') : '需基础版或专业版授权'; ?></span></div>
    </div>

    <div style="background:#fff;border:1px solid var(--border-light);border-radius:12px;padding:24px;margin-top:20px;box-shadow:var(--shadow-xs);">
        <div style="display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;">
            <div>
                <h3 style="font-size:16px;font-weight:600;color:var(--dark);margin:0;"><?php echo $hasNew ? ('发现新版本 v' . htmlspecialchars($latestVersion)) : '版本状态正常'; ?></h3>
                <p style="font-size:12px;color:var(--text-light);margin:6px 0 0 0;">在线升级前建议先备份数据库，程序升级时会自动生成文件备份。</p>
            </div>
            <div style="display:flex;gap:10px;flex-wrap:wrap;">
                <?php if ($canUpgradeOnline): ?>
                <form class="js-upgrade-form" method="post" style="margin:0;">
                    <input type="hidden" name="target_version" value="<?php echo htmlspecialchars($upgradeTargetVersion); ?>">
                    <button type="submit" class="btn" style="background:linear-gradient(135deg,#16a34a,#22c55e);color:#fff;padding:10px 20px;border:none;border-radius:10px;font-weight:700;cursor:pointer;">
                        <?php echo $hasNew ? '一键升级' : '重新安装当前版本'; ?>
                    </button>
                </form>
                <?php elseif (!$canUpgradeOnline): ?>
                <a href="/admin/main.php?act=auth" class="btn" style="background:linear-gradient(135deg,#ea580c 0%,#dc2626 100%);color:#fff;padding:10px 20px;border:none;border-radius:10px;text-decoration:none;font-weight:700;">
                    升级授权后使用
                </a>
                <?php endif; ?>
            </div>
        </div>

        <?php if ($changelog !== ''): ?>
        <div style="background:#f8fafc;border:1px solid var(--border-light);border-radius:8px;padding:16px;margin-top:18px;">
            <div style="font-size:13px;font-weight:600;color:var(--dark);margin-bottom:8px;">更新说明</div>
            <div style="font-size:13px;color:var(--text);line-height:1.8;white-space:pre-wrap;"><?php echo htmlspecialchars($changelog); ?></div>
        </div>
        <?php endif; ?>

        <?php if (!$canUpgradeOnline): ?>
        <div style="padding:16px;background:#fff7ed;border:1px solid #fdba74;border-radius:10px;color:#9a3412;font-size:13px;line-height:1.8;margin-top:18px;">
            当前版本为 <strong><?php echo htmlspecialchars($levelNames[$licenseInfo['level']] ?? '免费版'); ?></strong>，在线升级功能需要基础版或专业版授权。
            <a href="/admin/main.php?act=auth" style="color:#c2410c;font-weight:700;margin-left:8px;">前往授权信息</a>
        </div>
        <?php endif; ?>
    </div>

    <div style="background:#fff;border:1px solid var(--border-light);border-radius:12px;margin-top:20px;box-shadow:var(--shadow-xs);">
        <div style="padding:16px 20px;border-bottom:1px solid var(--border-light);">
            <h3 style="font-size:14px;font-weight:600;color:var(--dark);margin:0;">升级历史</h3>
        </div>
        <div>
            <?php if (empty($backupList)): ?>
            <div style="padding:30px;text-align:center;color:var(--text-light);font-size:13px;">暂无升级备份记录</div>
            <?php else: ?>
            <table class="data-table" style="margin:0;">
                <thead>
                    <tr>
                        <th>备份时间</th>
                        <th>版本信息</th>
                        <th>备份大小</th>
                    </tr>
                </thead>
                <tbody>
                    <?php foreach ($backupList as $backup): ?>
                    <?php $content = @file_get_contents($backupBaseDir . $backup['dir'] . '/version_backup.txt'); ?>
                    <tr>
                        <td style="font-size:13px;color:var(--text);"><?php echo htmlspecialchars($backup['time']); ?></td>
                        <td style="font-size:12px;color:var(--text-light);"><?php echo htmlspecialchars($content ? trim($content) : ('备份于 ' . $backup['time'])); ?></td>
                        <td style="font-size:12px;color:var(--text-light);"><?php echo $backup['size'] > 0 ? (round($backup['size'] / 1024 / 1024, 2) . ' MB') : '—'; ?></td>
                    </tr>
                    <?php endforeach; ?>
                </tbody>
            </table>
            <?php endif; ?>
        </div>
    </div>
</div>
<style>
.page-context-bar{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin-top:20px;}
.page-context-item{background:#fff;border:1px solid #e2e8f0;border-radius:14px;padding:14px 16px;}
.page-context-label{display:block;font-size:12px;color:#94a3b8;margin-bottom:6px;}
.page-context-value{display:block;font-size:14px;font-weight:700;color:#1e293b;line-height:1.6;}
.page-context-muted{color:#475569;font-weight:600;}
.upgrade-progress{margin-top:16px;padding:22px;border:1px solid #bfdbfe;border-radius:14px;background:#fff;box-shadow:0 12px 34px rgba(37,99,235,.09)}
.upgrade-progress__head{display:flex;align-items:flex-end;justify-content:space-between;gap:20px}.upgrade-progress__eyebrow{display:block;margin-bottom:4px;color:#2563eb;font-size:10px;font-weight:800;letter-spacing:.12em}.upgrade-progress__head h3{margin:0;color:#172033;font-size:18px}.upgrade-progress__head>strong{color:#2563eb;font-size:24px;font-variant-numeric:tabular-nums}.upgrade-progress__track{overflow:hidden;height:8px;margin-top:18px;border-radius:999px;background:#eaf1fb}.upgrade-progress__track span{display:block;width:0;height:100%;border-radius:inherit;background:#2563eb;transition:width .28s ease}.upgrade-progress.is-busy .upgrade-progress__track span:after{display:block;width:80px;height:100%;background:linear-gradient(90deg,transparent,rgba(255,255,255,.52),transparent);animation:upgradeShimmer 1.2s linear infinite;content:""}.upgrade-progress__steps{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin-top:20px}.upgrade-progress__steps>div{display:flex;gap:10px;align-items:flex-start;padding:12px;border:1px solid #e2e8f0;border-radius:9px;background:#f8fafc;color:#64748b}.upgrade-progress__steps i{display:grid;width:24px;height:24px;flex:0 0 auto;place-items:center;border:1px solid #cbd5e1;border-radius:50%;background:#fff;font-size:11px;font-style:normal;font-weight:800}.upgrade-progress__steps strong,.upgrade-progress__steps small{display:block}.upgrade-progress__steps strong{font-size:12px}.upgrade-progress__steps small{margin-top:2px;font-size:10px;line-height:1.5}.upgrade-progress__steps>div.is-active{border-color:#bfdbfe;background:#eff6ff;color:#1d4ed8}.upgrade-progress__steps>div.is-active i{border-color:#2563eb;background:#2563eb;color:#fff}.upgrade-progress__steps>div.is-done{border-color:#bbf7d0;background:#f0fdf4;color:#15803d}.upgrade-progress__steps>div.is-done i{border-color:#16a34a;background:#16a34a;color:#fff}.upgrade-progress__status{display:flex;align-items:center;gap:9px;margin-top:16px;color:#475569;font-size:12px}.upgrade-progress__pulse{width:8px;height:8px;border-radius:50%;background:#2563eb;box-shadow:0 0 0 5px rgba(37,99,235,.1);animation:upgradePulse 1.4s ease infinite}.upgrade-progress__error{margin-top:14px;padding:11px 13px;border:1px solid #fecaca;border-radius:8px;background:#fff7f7;color:#b91c1c;font-size:12px;line-height:1.7}.upgrade-progress.is-error{border-color:#fecaca}.upgrade-progress.is-error .upgrade-progress__pulse{background:#dc2626;box-shadow:none;animation:none}.upgrade-progress.is-complete{border-color:#bbf7d0}.upgrade-progress.is-complete .upgrade-progress__pulse{background:#16a34a;box-shadow:none;animation:none}@keyframes upgradePulse{50%{opacity:.4;transform:scale(.78)}}@keyframes upgradeShimmer{from{transform:translateX(-80px)}to{transform:translateX(700px)}}
@media (max-width: 1200px){.page-context-bar{grid-template-columns:repeat(2,minmax(0,1fr));}}
@media (max-width: 900px){.upgrade-progress__steps{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (max-width: 768px){.page-context-bar{grid-template-columns:1fr}.upgrade-progress__steps{grid-template-columns:1fr}.upgrade-progress__head{align-items:flex-start}.upgrade-progress__head>strong{font-size:20px}}
</style>
<script>
(function(){
    var forms=document.querySelectorAll('.js-upgrade-form'),panel=document.getElementById('upgradeProgress');
    if(!forms.length||!panel)return;
    var bar=document.getElementById('upgradeProgressBar'),percent=document.getElementById('upgradeProgressPercent'),title=document.getElementById('upgradeProgressTitle'),message=document.getElementById('upgradeProgressMessage'),errorBox=document.getElementById('upgradeProgressError');
    var token=<?php echo json_encode(getAdminCsrfToken(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); ?>;
    var labels={download:'正在下载升级包',extract:'正在校验升级包',copy:'正在更新程序文件',finalize:'正在完成升级'};
    function paint(value,phase,text){value=Math.max(0,Math.min(100,Number(value)||0));bar.style.width=value+'%';percent.textContent=value+'%';title.textContent=labels[phase]||'正在升级';message.textContent=text||'请勿关闭当前页面';panel.classList.toggle('is-busy',value<100);document.querySelectorAll('[data-upgrade-step]').forEach(function(node){var order=['download','extract','copy','finalize'],current=order.indexOf(phase),index=order.indexOf(node.dataset.upgradeStep);node.classList.toggle('is-active',index===current&&value<100);node.classList.toggle('is-done',index<current||value===100)})}
    async function request(phase,target){var data=new FormData();data.append('phase',phase);data.append('target_version',target);data.append('csrf_token',token);if(phase==='copy')data.append('batch_size','120');var response=await fetch('/admin/upgrade.php',{method:'POST',body:data,headers:{'Accept':'application/json','X-Requested-With':'XMLHttpRequest'}}),raw=await response.text(),result=null;try{result=JSON.parse(raw)}catch(e){var plain=raw.replace(/<[^>]*>/g,' ').replace(/\s+/g,' ').trim();throw new Error('服务器返回非 JSON（HTTP '+response.status+'）：'+(plain.slice(0,500)||'响应为空，请确认 admin/upgrade.php 已上传且 PHP-FPM 可访问'))}if(!response.ok||!result||result.code!==200)throw new Error(((result&&result.msg)||('升级请求失败，HTTP '+response.status))+((result&&result.debug)?'（'+result.debug+'）':''));return result.data}
    async function run(target){panel.hidden=false;panel.className='upgrade-progress is-busy';errorBox.hidden=true;forms.forEach(function(form){form.querySelector('button').disabled=true});paint(5,'download','正在连接授权中心，请稍候…');try{var result=await request('download',target);paint(result.progress,'extract',result.message);result=await request('extract',target);paint(result.progress,'copy',result.message);do{result=await request('copy',target);paint(result.progress,'copy',result.message+'（'+result.current+'/'+result.total+'）')}while(!result.done);paint(94,'finalize','正在清理临时文件并写入升级记录…');result=await request('finalize',target);paint(100,'finalize',result.message);panel.className='upgrade-progress is-complete';setTimeout(function(){location.reload()},1600)}catch(error){panel.className='upgrade-progress is-error';title.textContent='升级未完成';message.textContent='已停止升级，请根据提示处理后重试';errorBox.textContent=error.message||String(error);errorBox.hidden=false;forms.forEach(function(form){form.querySelector('button').disabled=false})}}
    forms.forEach(function(form){form.addEventListener('submit',function(event){event.preventDefault();var target=(form.querySelector('[name="target_version"]')||{}).value||'';if(!target)return;if(!confirm('升级过程中请勿关闭页面。确认开始更新到 v'+target+' 吗？'))return;run(target)})});
}());
</script>
