<?php
// pages/admin_sysinfo.php — 시스템 정보
require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../includes/header.php';
$user = currentUser();
$db = (new Database())->getConnection();

$dbVersion = $db->query("SELECT VERSION()")->fetchColumn();
$dbSize = $db->query("SELECT ROUND(SUM(data_length + index_length)/1024/1024, 2) AS size_mb FROM information_schema.tables WHERE table_schema=DATABASE()")->fetchColumn();
$dbName = $db->query("SELECT DATABASE()")->fetchColumn();
$tableCount = $db->query("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema=DATABASE()")->fetchColumn();
$dbTables = $db->query("SELECT table_name, ROUND((data_length+index_length)/1024, 1) AS size_kb, table_rows FROM information_schema.tables WHERE table_schema=DATABASE() ORDER BY (data_length+index_length) DESC")->fetchAll();

$phpVer = phpversion(); $phpExts = get_loaded_extensions(); sort($phpExts);
$maxUpload = ini_get('upload_max_filesize'); $maxPost = ini_get('post_max_size'); $memoryLimit = ini_get('memory_limit');
$osInfo = php_uname(); $serverSoftware = $_SERVER['SERVER_SOFTWARE'] ?? 'N/A';
$isWindows = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');

$cpuModel = 'N/A'; $cpuCores = 'N/A'; $memTotal = 'N/A'; $memFree = 'N/A'; $memUsedPct = 0; $uptimeStr = 'N/A';

if ($isWindows) {
    // === CPU ===
    $cpuModel = @getenv('PROCESSOR_IDENTIFIER') ?: '';
    $rawCpu = @shell_exec('wmic cpu get Name /value 2>nul');
    if ($rawCpu) { $parsed = trim(preg_replace('/^Name=/i','',trim($rawCpu))); if (strlen($parsed)>3) $cpuModel = $parsed; }
    if (!$cpuModel || strlen($cpuModel)<4) { $rawCpu = @shell_exec('powershell -NoProfile -command "(Get-CimInstance Win32_Processor).Name" 2>nul'); if ($rawCpu) $cpuModel = trim($rawCpu); }
    if (!$cpuModel) $cpuModel = php_uname('m');
    $cpuModel = trim(preg_replace('/\s+/',' ',$cpuModel));

    // === CPU Cores ===
    $cpuCores = @getenv('NUMBER_OF_PROCESSORS') ?: '';
    if (!$cpuCores) { $raw=@shell_exec('wmic cpu get NumberOfCores /value 2>nul'); $cpuCores=$raw?preg_replace('/[^0-9]/','',preg_replace('/^NumberOfCores=/i','',trim($raw))):''; }
    if (!$cpuCores) $cpuCores = 'N/A';

    // === Memory ===
    $memTotalBytes = 0;
    // wmic total
    $raw = @shell_exec('wmic ComputerSystem get TotalPhysicalMemory /value 2>nul');
    $val = $raw ? preg_replace('/[^0-9]/','',preg_replace('/^TotalPhysicalMemory=/i','',trim($raw))) : '';
    if ($val && is_numeric($val)) $memTotalBytes = (float)$val;
    // powershell total
    if (!$memTotalBytes) { $raw=@shell_exec('powershell -NoProfile -command "(Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory" 2>nul'); $val=$raw?trim(preg_replace('/[^0-9]/','',$raw)):''; if($val&&is_numeric($val)) $memTotalBytes=(float)$val; }
    if ($memTotalBytes) $memTotal = round($memTotalBytes/1024/1024/1024, 1) . ' GB';

    // wmic free (in KB)
    $freeKB = 0;
    $raw = @shell_exec('wmic OS get FreePhysicalMemory /value 2>nul');
    $val = $raw ? preg_replace('/[^0-9]/','',preg_replace('/^FreePhysicalMemory=/i','',trim($raw))) : '';
    if ($val && is_numeric($val)) $freeKB = (float)$val;
    if (!$freeKB) { $raw=@shell_exec('powershell -NoProfile -command "(Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory" 2>nul'); $val=$raw?trim(preg_replace('/[^0-9]/','',$raw)):''; if($val&&is_numeric($val)) $freeKB=(float)$val; }
    if ($freeKB) {
        $freeBytes = $freeKB * 1024;
        $memFree = round($freeBytes/1024/1024/1024, 1) . ' GB';
        if ($memTotalBytes > 0) $memUsedPct = round((1 - $freeBytes/$memTotalBytes)*100, 1);
    }

    // systeminfo fallback
    if ($memTotal === 'N/A' || $memFree === 'N/A') {
        $si = @shell_exec('systeminfo 2>nul');
        if ($si) {
            if ($memTotal==='N/A' && preg_match('/Total Physical Memory[:\s]+([\d,\.]+)\s*(MB|GB)/i',$si,$sm)) { $v=(float)str_replace(',','',$sm[1]); $memTotal=($sm[2]==='GB'?round($v,1):round($v/1024,1)).' GB'; }
            if ($memFree==='N/A' && preg_match('/Available Physical Memory[:\s]+([\d,\.]+)\s*(MB|GB)/i',$si,$am)) { $v=(float)str_replace(',','',$am[1]); $memFree=($am[2]==='GB'?round($v,1):round($v/1024,1)).' GB'; }
        }
    }

    // === Uptime ===
    // wmic boot time
    $raw = @shell_exec('wmic os get LastBootUpTime /value 2>nul');
    $bootStr = $raw ? preg_replace('/[^0-9.]/','',preg_replace('/^LastBootUpTime=/i','',trim($raw))) : '';
    if (strlen($bootStr) >= 14) {
        $bt = substr($bootStr,0,4).'-'.substr($bootStr,4,2).'-'.substr($bootStr,6,2).' '.substr($bootStr,8,2).':'.substr($bootStr,10,2);
        $diff = time()-strtotime($bt);
        if ($diff>0) { $dd=floor($diff/86400); $hh=floor(($diff%86400)/3600); $mm=floor(($diff%3600)/60); $uptimeStr="{$dd}일 {$hh}시간 {$mm}분"; }
    }
    if ($uptimeStr==='N/A') {
        $raw=@shell_exec('powershell -NoProfile -command "((Get-Date)-(Get-CimInstance Win32_OperatingSystem).LastBootUpTime).TotalSeconds" 2>nul');
        if ($raw&&is_numeric(trim($raw))) { $s=(int)trim($raw); $dd=floor($s/86400); $hh=floor(($s%86400)/3600); $mm=floor(($s%3600)/60); $uptimeStr="{$dd}일 {$hh}시간 {$mm}분"; }
    }
    if ($uptimeStr==='N/A') {
        $raw=@shell_exec('net statistics workstation 2>nul');
        if ($raw && preg_match('/since\s+(.+)/i',$raw,$nsm)) { $bt=@strtotime(trim($nsm[1])); if($bt){$diff=time()-$bt;$dd=floor($diff/86400);$hh=floor(($diff%86400)/3600);$uptimeStr="{$dd}일 {$hh}시간";} }
    }
} else {
    $cpuInfo = @file_get_contents('/proc/cpuinfo');
    if ($cpuInfo && preg_match('/model name\s*:\s*(.+)/i', $cpuInfo, $m)) $cpuModel = trim($m[1]);
    $cpuCores = $cpuInfo ? substr_count($cpuInfo, 'processor') : 'N/A';
    $memInfo = @file_get_contents('/proc/meminfo');
    if ($memInfo) {
        if (preg_match('/MemTotal:\s+(\d+)/', $memInfo, $m)) $memTotal = round($m[1]/1024/1024, 1) . ' GB';
        if (preg_match('/MemAvailable:\s+(\d+)/', $memInfo, $m2) && preg_match('/MemTotal:\s+(\d+)/', $memInfo, $m3)) {
            $memFree = round($m2[1]/1024/1024, 1) . ' GB';
            $memUsedPct = round((1 - $m2[1]/$m3[1]) * 100, 1);
        }
    }
    $uptime = @file_get_contents('/proc/uptime');
    if ($uptime) { $sec = (int)$uptime; $d = floor($sec/86400); $h = floor(($sec%86400)/3600); $uptimeStr = "{$d}일 {$h}시간"; }
}

$diskFree = @disk_free_space(__DIR__); $diskTotal = @disk_total_space(__DIR__);
$diskUsedPct = ($diskTotal && $diskFree) ? round((1 - $diskFree/$diskTotal)*100, 1) : 0;
$diskUsed = $diskTotal ? $diskTotal - $diskFree : 0;

// 디스크 모델 정보
$diskDrives = [];
if ($isWindows) {
    $raw = @shell_exec('wmic diskdrive get Model,Size,MediaType,InterfaceType /format:csv 2>nul');
    if ($raw) {
        $lines = array_filter(array_map('trim', explode("\n", $raw)), fn($l) => $l && !str_starts_with($l, 'Node'));
        foreach ($lines as $line) {
            $cols = str_getcsv($line);
            if (count($cols) >= 5) {
                $iface = trim($cols[1] ?? '');
                $media = trim($cols[2] ?? '');
                $model = trim($cols[3] ?? '');
                $size = trim($cols[4] ?? '');
                if (!$model) continue;
                if (stripos($iface, 'USB') !== false) continue; // 외장하드 제외
                $sizeGB = is_numeric($size) ? round((float)$size / 1024/1024/1024, 0) : 0;
                $type = '';
                if (stripos($media, 'SSD') !== false || stripos($model, 'SSD') !== false || stripos($model, 'NVMe') !== false || stripos($iface, 'NVMe') !== false) $type = stripos($iface, 'NVMe') !== false ? 'NVMe SSD' : 'SSD';
                elseif (stripos($media, 'Fixed') !== false || stripos($media, 'HDD') !== false) $type = 'HDD';
                $diskDrives[] = ['model' => $model, 'size' => $sizeGB, 'type' => $type ?: $media, 'iface' => $iface];
            }
        }
    }
    if (empty($diskDrives)) {
        $raw = @shell_exec('powershell -NoProfile -command "Get-PhysicalDisk | Where-Object {$_.BusType -ne \'USB\'} | Select-Object Model,Size,MediaType,BusType | ConvertTo-Csv -NoTypeInformation" 2>nul');
        if ($raw) {
            $lines = array_filter(array_map('trim', explode("\n", $raw)));
            array_shift($lines); // header
            foreach ($lines as $line) {
                $cols = str_getcsv($line);
                if (count($cols) >= 3 && trim($cols[0])) {
                    $sizeGB = is_numeric(trim($cols[1])) ? round((float)trim($cols[1]) / 1024/1024/1024, 0) : 0;
                    $diskDrives[] = ['model' => trim($cols[0]), 'size' => $sizeGB, 'type' => trim($cols[2])];
                }
            }
        }
    }
} else {
    // Linux: lsblk
    $raw = @shell_exec('lsblk -d -o NAME,MODEL,SIZE,ROTA,TRAN -n 2>/dev/null');
    if ($raw) {
        foreach (array_filter(array_map('trim', explode("\n", $raw))) as $line) {
            $parts = preg_split('/\s+/', $line, 5);
            if (count($parts) >= 3 && !empty($parts[1]) && $parts[1] !== '-') {
                $tran = strtoupper($parts[4] ?? '');
                if ($tran === 'USB') continue; // 외장하드 제외
                $rota = ($parts[3] ?? '1') === '0' ? 'SSD' : 'HDD';
                if ($tran === 'NVME') $rota = 'NVMe SSD';
                $diskDrives[] = ['model' => $parts[1], 'size' => $parts[2], 'type' => $rota];
            }
        }
    }
}
?>
<div class="page-header"><h2>🖥️ 시스템 정보</h2><span id="sysRefreshTime" style="font-size:var(--fs-xs);color:var(--text-tertiary);margin-left:auto;">최종 갱신: -</span></div>

<div style="display:grid;grid-template-columns:repeat(3,1fr);gap:1rem;margin-bottom:1rem;">
    <div class="stat-card" style="text-align:center;">
        <div style="position:relative;width:6rem;height:6rem;margin:0 auto 0.5rem;">
            <svg viewBox="0 0 36 36" style="transform:rotate(-90deg);">
                <circle cx="18" cy="18" r="15.9" fill="none" stroke="rgba(255,255,255,0.06)" stroke-width="3"/>
                <circle id="cpuArc" cx="18" cy="18" r="15.9" fill="none" stroke="#2E7D32" stroke-width="3" stroke-dasharray="0 100" stroke-linecap="round" style="transition:stroke-dasharray 0.5s,stroke 0.5s;"/>
            </svg>
            <div style="position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;">
                <div id="cpuPct" style="font-size:1.25rem;font-weight:800;">0%</div>
            </div>
        </div>
        <div style="font-size:var(--fs-sm);font-weight:600;">CPU 사용률</div>
    </div>
    <div class="stat-card" style="text-align:center;">
        <div style="position:relative;width:6rem;height:6rem;margin:0 auto 0.5rem;">
            <svg viewBox="0 0 36 36" style="transform:rotate(-90deg);">
                <circle cx="18" cy="18" r="15.9" fill="none" stroke="rgba(255,255,255,0.06)" stroke-width="3"/>
                <circle id="memArc" cx="18" cy="18" r="15.9" fill="none" stroke="#2E7D32" stroke-width="3" stroke-dasharray="<?= $memUsedPct ?> <?= 100-$memUsedPct ?>" stroke-linecap="round" style="transition:stroke-dasharray 0.5s,stroke 0.5s;"/>
            </svg>
            <div style="position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;">
                <div id="memPct" style="font-size:1.25rem;font-weight:800;"><?= $memUsedPct ?>%</div>
            </div>
        </div>
        <div style="font-size:var(--fs-sm);font-weight:600;">메모리 사용률</div>
        <div id="memDetail" style="font-size:var(--fs-xs);color:var(--text-tertiary);margin-top:0.25rem;"><?= $memFree ?> / <?= $memTotal ?></div>
    </div>
    <div class="stat-card" style="text-align:center;">
        <div style="position:relative;width:6rem;height:6rem;margin:0 auto 0.5rem;">
            <svg viewBox="0 0 36 36" style="transform:rotate(-90deg);">
                <circle cx="18" cy="18" r="15.9" fill="none" stroke="rgba(255,255,255,0.06)" stroke-width="3"/>
                <circle cx="18" cy="18" r="15.9" fill="none" stroke="<?= $diskUsedPct>80?'#C62828':($diskUsedPct>60?'#F57F17':'#2E7D32') ?>" stroke-width="3" stroke-dasharray="<?= $diskUsedPct ?> <?= 100-$diskUsedPct ?>" stroke-linecap="round"/>
            </svg>
            <div style="position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;">
                <div style="font-size:1.25rem;font-weight:800;"><?= $diskUsedPct ?>%</div>
            </div>
        </div>
        <div style="font-size:var(--fs-sm);font-weight:600;">디스크 사용률</div>
        <div style="font-size:var(--fs-xs);color:var(--text-tertiary);margin-top:0.25rem;"><?= $diskFree?number_format($diskFree/1024/1024/1024,1):'?' ?> GB 사용 가능</div>
    </div>
</div>

<div style="display:grid;grid-template-columns:1fr 1fr;gap:1rem;margin-bottom:1rem;">
    <div class="card" style="padding:1.25rem;">
        <h3 style="font-size:var(--fs-sm);margin-bottom:1rem;color:var(--accent-text);">⚙️ 서버 사양</h3>
        <table><tbody>
            <tr><td style="color:var(--text-tertiary);width:9rem;">CPU</td><td><strong style="word-break:break-all;"><?= htmlspecialchars($cpuModel) ?></strong></td></tr>
            <tr><td style="color:var(--text-tertiary);">CPU 코어</td><td><strong><?= $cpuCores ?>개</strong></td></tr>
            <tr><td style="color:var(--text-tertiary);">총 메모리</td><td><strong><?= $memTotal ?></strong></td></tr>
            <tr><td style="color:var(--text-tertiary);">사용 가능 메모리</td><td><strong><?= $memFree ?></strong></td></tr>
            <tr><td style="color:var(--text-tertiary);">메모리 사용률</td><td>
                <div style="display:flex;align-items:center;gap:0.5rem;">
                    <div style="flex:1;height:0.75rem;background:rgba(255,255,255,0.08);border-radius:4px;overflow:hidden;">
                        <div id="memBar" style="width:<?= $memUsedPct ?>%;height:100%;background:<?= $memUsedPct>80?'#C62828':($memUsedPct>60?'#F57F17':'#2E7D32') ?>;border-radius:4px;transition:width 0.5s,background 0.5s;"></div>
                    </div>
                    <strong id="memBarPct" style="font-size:var(--fs-xs);"><?= $memUsedPct ?>%</strong>
                </div>
            </td></tr>
            <tr><td style="color:var(--text-tertiary);">서버 가동시간</td><td><strong><?= $uptimeStr ?></strong></td></tr>
        </tbody></table>
    </div>
    <div class="card" style="padding:1.25rem;">
        <h3 style="font-size:var(--fs-sm);margin-bottom:1rem;color:var(--accent-text);">💾 저장소</h3>
        <?php if (!empty($diskDrives)): ?>
        <table style="margin-bottom:0.75rem;"><thead><tr><th style="font-size:var(--fs-xs);">디스크</th><th style="font-size:var(--fs-xs);">유형</th><th style="font-size:var(--fs-xs);">용량</th></tr></thead><tbody>
        <?php foreach ($diskDrives as $dd): ?>
        <tr>
            <td style="font-size:var(--fs-xs);"><strong><?= htmlspecialchars($dd['model']) ?></strong></td>
            <td><span class="badge" style="font-size:10px;padding:2px 6px;background:<?= stripos($dd['type'],'SSD')!==false||stripos($dd['type'],'NVMe')!==false?'rgba(46,125,50,0.2);color:#66BB6A':'rgba(255,152,0,0.2);color:#FFB74D' ?>;"><?= htmlspecialchars($dd['type']) ?></span></td>
            <td style="font-size:var(--fs-xs);"><?= is_numeric($dd['size']) ? $dd['size'].' GB' : $dd['size'] ?></td>
        </tr>
        <?php endforeach; ?>
        </tbody></table>
        <?php endif; ?>
        <table><tbody>
            <tr><td style="color:var(--text-tertiary);width:9rem;">전체 용량</td><td><strong><?= $diskTotal ? number_format($diskTotal/1024/1024/1024, 1) . ' GB' : 'N/A' ?></strong></td></tr>
            <tr><td style="color:var(--text-tertiary);">사용 중</td><td><strong><?= $diskUsed ? number_format($diskUsed/1024/1024/1024, 1) . ' GB' : 'N/A' ?></strong></td></tr>
            <tr><td style="color:var(--text-tertiary);">사용 가능</td><td><strong><?= $diskFree ? number_format($diskFree/1024/1024/1024, 1) . ' GB' : 'N/A' ?></strong></td></tr>
        </tbody></table>
    </div>
    <div class="card" style="padding:1.25rem;">
        <h3 style="font-size:var(--fs-sm);margin-bottom:1rem;color:var(--accent-text);">🗄️ 데이터베이스</h3>
        <table><tbody>
            <tr><td style="color:var(--text-tertiary);width:9rem;">엔진</td><td><strong><?= htmlspecialchars($dbVersion) ?></strong></td></tr>
            <tr><td style="color:var(--text-tertiary);">DB 이름</td><td><strong><?= htmlspecialchars($dbName) ?></strong></td></tr>
            <tr><td style="color:var(--text-tertiary);">테이블 수</td><td><strong><?= $tableCount ?>개</strong></td></tr>
            <tr><td style="color:var(--text-tertiary);">DB 크기</td><td><strong><?= $dbSize ?> MB</strong></td></tr>
        </tbody></table>
        <?php if ($dbTables): ?><details style="margin-top:0.75rem;"><summary style="cursor:pointer;font-size:var(--fs-xs);color:var(--accent-text);">테이블 상세 (<?= count($dbTables) ?>개)</summary>
        <table style="margin-top:0.5rem;font-size:var(--fs-xs);"><thead><tr><th>테이블</th><th>크기</th><th>행 수</th></tr></thead><tbody>
        <?php foreach ($dbTables as $t): ?><tr><td><code><?= $t['table_name'] ?></code></td><td style=""><?= number_format($t['size_kb'],1) ?> KB</td><td style=""><?= number_format($t['table_rows']) ?></td></tr><?php endforeach; ?>
        </tbody></table></details><?php endif; ?>
    </div>
    <div class="card" style="padding:1.25rem;">
        <h3 style="font-size:var(--fs-sm);margin-bottom:1rem;color:var(--accent-text);">🐘 PHP / OS</h3>
        <table><tbody>
            <tr><td style="color:var(--text-tertiary);width:9rem;">OS 정보</td><td><strong style="word-break:break-all;font-size:var(--fs-xs);"><?= htmlspecialchars($osInfo) ?></strong></td></tr>
            <tr><td style="color:var(--text-tertiary);">웹서버</td><td><strong><?= htmlspecialchars($serverSoftware) ?></strong></td></tr>
            <tr><td style="color:var(--text-tertiary);">PHP 버전</td><td><strong><?= $phpVer ?></strong></td></tr>
            <tr><td style="color:var(--text-tertiary);">최대 업로드</td><td><strong><?= $maxUpload ?></strong></td></tr>
            <tr><td style="color:var(--text-tertiary);">최대 POST</td><td><strong><?= $maxPost ?></strong></td></tr>
            <tr><td style="color:var(--text-tertiary);">메모리 제한</td><td><strong><?= $memoryLimit ?></strong></td></tr>
        </tbody></table>
        <details style="margin-top:0.75rem;"><summary style="cursor:pointer;font-size:var(--fs-xs);color:var(--accent-text);">PHP 확장 모듈 (<?= count($phpExts) ?>개)</summary>
        <p style="font-size:var(--fs-xs);line-height:1.8;margin-top:0.5rem;color:var(--text-secondary);"><?= implode(', ', $phpExts) ?></p></details>
    </div>
</div>
<script>
function arcColor(pct){return pct>80?'#C62828':pct>60?'#F57F17':'#2E7D32';}
function refreshSysInfo(){
    fetch('api_sysinfo.php').then(r=>r.json()).then(d=>{
        // CPU
        document.getElementById('cpuPct').textContent=d.cpu_usage+'%';
        document.getElementById('cpuArc').setAttribute('stroke-dasharray',d.cpu_usage+' '+(100-d.cpu_usage));
        document.getElementById('cpuArc').setAttribute('stroke',arcColor(d.cpu_usage));
        // Memory circle
        document.getElementById('memPct').textContent=d.mem_used_pct+'%';
        document.getElementById('memArc').setAttribute('stroke-dasharray',d.mem_used_pct+' '+(100-d.mem_used_pct));
        document.getElementById('memArc').setAttribute('stroke',arcColor(d.mem_used_pct));
        document.getElementById('memDetail').textContent=d.mem_free+' GB / '+d.mem_total+' GB';
        // Memory bar
        document.getElementById('memBar').style.width=d.mem_used_pct+'%';
        document.getElementById('memBar').style.background=arcColor(d.mem_used_pct);
        document.getElementById('memBarPct').textContent=d.mem_used_pct+'%';
        // Timestamp
        document.getElementById('sysRefreshTime').textContent='최종 갱신: '+d.timestamp;
    }).catch(e=>{});
}
refreshSysInfo();
setInterval(refreshSysInfo, 5000);
</script>
<?php require_once __DIR__ . '/../includes/footer.php'; ?>
