<?php
// --- 为标题生成随机渐变色 (移植自 Nexus 项目) ---
$gradient_colors = ['#66d9ff', '#66ffc2', '#ffc966', '#ffb366', '#ff8282', '#ff8dff', '#82a2ff', '#7ed6df'];
$rand_keys = array_rand($gradient_colors, 2);
$color1 = $gradient_colors[$rand_keys[0]];
$color2 = $gradient_colors[$rand_keys[1]];
$angle = rand(0, 360);

// --- 为 Uptime 副标题生成随机渐变色 (移植自 Nexus 项目) ---
$rand_keys2 = array_rand($gradient_colors, 2);
$color3 = $gradient_colors[$rand_keys2[0]];
$color4 = $gradient_colors[$rand_keys2[1]];
$angle2 = rand(0, 360);

// --- 获取服务器 Uptime (秒) (移植自 Nexus 项目) ---
$uptime_seconds = 0;
if (is_readable('/proc/uptime')) {
    $uptime_str = file_get_contents('/proc/uptime');
    $uptime_seconds = (int)explode(' ', $uptime_str)[0];
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Aegis Infrastructure AegisAES 4.1M MongoDB</title>
    <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><path d='M60,10 C25,10 10,45 50,95 C90,75 95,30 60,10 Z' fill='%232ECC71' /><path d='M55,25 C70,45 65,70 50,90' stroke='%23FFFFFF' stroke-width='7' fill='none' stroke-linecap='round' /></svg>">


    <style>
        :root {
            --bg-color: #090a0f; --panel-bg-color: rgba(26, 26, 26, 0.6); --border-color: rgba(255, 255, 255, 0.1);
            --text-primary: #f0f0f0; --text-secondary: #a0a0a0; --accent-color: #00aaff;
            --font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
            --border-radius: 16px; --shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
            --body-padding: 1rem;
        }
        *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
        html, body { height: auto; overflow-x: hidden; }
        body {
            color: var(--text-primary); font-family: var(--font-family); padding: var(--body-padding);
            background-color: var(--bg-color);
            background-image: radial-gradient(circle at 50% 0%, rgba(120, 120, 180, 0.08) 0%, transparent 50%);
            display: flex; flex-direction: column;
        }
        .portal-wrapper { width: 100%; height: auto; display: flex; flex-direction: column; gap: 1rem; z-index: 1; }
        .portal-header {
            display: flex; justify-content: space-between; align-items: center;
            padding-bottom: 1rem; border-bottom: 1px solid var(--border-color);
            flex-shrink: 0; animation: fadeIn 0.5s ease-out forwards;
        }
        .portal-header h1 {
            font-size: 1.6rem; font-weight: 700; letter-spacing: -1px; margin: 0;
            display: flex; align-items: baseline; flex-wrap: wrap;
        }
        .portal-header h1 a {
            text-decoration: none;
            background: linear-gradient(<?php echo $angle; ?>deg, <?php echo $color1; ?>, <?php echo $color2; ?>);
            -webkit-background-clip: text;
            background-clip: text;
            color: transparent;
        }
        #uptime-display {
            font-size: 0.8em;
            font-weight: 700;
            letter-spacing: normal;
            margin-left: 1rem;
            background: linear-gradient(<?php echo $angle2; ?>deg, <?php echo $color3; ?>, <?php echo $color4; ?>);
            -webkit-background-clip: text;
            background-clip: text;
            color: transparent;
            white-space: nowrap;
        }
        .dashboard-layout { display: flex; gap: 1rem; }
        .sidebar-panel {
            flex: 0 0 300px; background-color: var(--panel-bg-color);
            border: 1px solid var(--border-color); border-radius: var(--border-radius);
            box-shadow: var(--shadow); overflow-y: visible; backdrop-filter: blur(20px);
            -webkit-backdrop-filter: blur(20px); padding: 1rem;
            animation: fadeInUp 0.6s ease-out forwards; opacity: 0;
            position: sticky; top: var(--body-padding);
        }
        .sidebar-panel a {
            display: flex; align-items: center; gap: 0.75rem; padding: 0.75rem 1rem;
            color: var(--text-secondary); text-decoration: none; border-radius: 12px;
            transition: background-color 0.2s ease, color 0.2s ease;
            font-weight: 500; word-break: break-all; position: relative;
        }
        .sidebar-panel a:hover { background-color: rgba(0, 170, 255, 0.1); color: var(--text-primary); }
        .sidebar-panel a.active { background-color: rgba(0, 170, 255, 0.15); color: var(--text-primary); font-weight: 600; }
        .sidebar-panel a.active::before {
            content: ''; position: absolute; left: -1rem; top: 50%;
            transform: translateY(-50%); width: 4px; height: 60%;
            background: var(--accent-color); border-radius: 0 4px 4px 0;
            box-shadow: 0 0 8px var(--accent-color);
        }
        .sidebar-panel a svg { flex-shrink: 0; width: 20px; height: 20px; transition: color 0.2s ease; }
        .sidebar-panel a .chevron { margin-left: auto; transition: transform 0.3s ease; }
        .sidebar-panel a.open .chevron { transform: rotate(90deg); }
        .projects, .components { display: none; padding-left: 20px; border-left: 1px solid var(--border-color); margin-left: 1rem; }
        .content-panel {
            flex-grow: 1; background-color: var(--panel-bg-color);
            border: 1px solid var(--border-color); border-radius: var(--border-radius);
            box-shadow: var(--shadow); overflow: hidden; backdrop-filter: blur(20px);
            -webkit-backdrop-filter: blur(20px); position: relative;
            animation: fadeInUp 0.7s ease-out forwards; opacity: 0;
            min-height: calc(100vh - (var(--body-padding) * 2) - 5rem);
        }
        .content-panel::after, .sidebar-panel::after {
            content: ''; position: absolute; top: 0; left: 0; right: 0; height: 1px;
            background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
        }
        iframe { width: 100%; height: 100%; border: none; min-height: 1900px; }
        @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
        @keyframes fadeInUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } }
        @media (max-width: 1024px) {
            body { padding: 1rem; --body-padding: 1rem; }
            .dashboard-layout { flex-direction: column; }
            .sidebar-panel { position: static; flex-basis: auto; }
            .content-panel { height: 80vh; min-height: 500px; }
            iframe { height: 100%; min-height: 0; }
        }
    </style>
</head>
<body>

<div class="portal-wrapper">
    <header class="portal-header">
        <h1>
            <a href="./">Aegis Infrastructure AegisAES 4.1M MongoDB</a>
            <span id="uptime-display"></span>
        </h1>
    </header>

    <main class="dashboard-layout">
        <aside class="sidebar-panel">
            <?php
            // ########## START: MODIFIED FOR 4-COLLECTION SCHEMA ##########
            include 'db.php';

            // 定义图标和颜色 (与原版逻辑保持一致)
            $icon_colors = ['#66d9ff', '#66ffc2', '#ffc966', '#ffb366', '#ff8282', '#ff8dff', '#82a2ff', '#7ed6df'];
            $tech_icons = [
                'server'   => "<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><rect x='2' y='2' width='20' height='8' rx='2' ry='2'></rect><rect x='2' y='14' width='20' height='8' rx='2' ry='2'></rect><line x1='6' y1='6' x2='6.01' y2='6'></line><line x1='6' y1='18' x2='6.01' y2='18'></line></svg>",
                'database' => "<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><ellipse cx='12' cy='5' rx='9' ry='3'></ellipse><path d='M21 12c0 1.66-4 3-9 3s-9-1.34-9-3'></path><path d='M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5'></path></svg>",
                'cloud'    => "<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M18 10h-1.26A8 8 0 1 0 9 20h9a5 5 0 0 0 0-10z'></path></svg>",
                'code'     => "<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='4 17 10 11 4 5'></polyline><line x1='12' y1='19' x2='20' y2='19'></line></svg>",
                'globe'    => "<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='12' cy='12' r='10'></circle><line x1='2' y1='12' x2='22' y2='12'></line><path d='M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z'></path></svg>"
            ];
            $color_index = 0;
            $chevron_svg = "<svg class='chevron' xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='9 18 15 12 9 6'></polyline></svg>";

            try {
                // 1. Fetch all data from the three collections
                $repositories = $db->REPOSITORY->find([], ['sort' => ['REPOSITORY_NAME' => 1]])->toArray();
                $projects = $db->PROJECT->find([], ['sort' => ['PROJECT_NAME' => 1]])->toArray();
                $components = $db->COMPONENT->find([], ['sort' => ['COMPONENT_NAME' => 1]])->toArray();

                // 2. Create lookup maps for efficient hierarchy building
                $projectsByRepoId = [];
                foreach ($projects as $project) {
                    // Group projects by their parent REPOSITORY_ID (the integer/long key)
                    $repoIdKey = (string)$project['REPOSITORY_ID'];
                    if (!isset($projectsByRepoId[$repoIdKey])) {
                        $projectsByRepoId[$repoIdKey] = [];
                    }
                    $projectsByRepoId[$repoIdKey][] = $project;
                }

                $componentsByProjectId = [];
                foreach ($components as $component) {
                    // Group components by their parent PROJECT_ID (the integer/long key)
                    $projIdKey = (string)$component['PROJECT_ID'];
                    if (!isset($componentsByProjectId[$projIdKey])) {
                        $componentsByProjectId[$projIdKey] = [];
                    }
                    $componentsByProjectId[$projIdKey][] = $component;
                }

                // 3. Loop through repositories and render the full hierarchy
                foreach ($repositories as $repo) {
                    $repoIdStr = (string)$repo['_id'];
                    $repoName = htmlspecialchars($repo['REPOSITORY_NAME'], ENT_QUOTES, 'UTF-8');
                    $repoIntId = (string)$repo['REPOSITORY_ID'];

                    // Assign icon and color (same logic as before)
                    $color = $icon_colors[$color_index % count($icon_colors)];
                    $color_index++;
                    $random_icon_key = array_rand($tech_icons);
                    $icon_html = str_replace('<svg', "<svg style='color: {$color};'", $tech_icons[$random_icon_key]);
                    
                    // Output repository link
                    echo "<a href='#' class='repository' onclick=\"event.preventDefault(); loadProject('{$repoIdStr}', this)\">
                            {$icon_html}
                            <span>{$repoName}</span>
                            {$chevron_svg}
                          </a>";

                    // Start projects list
                    echo "<div id='projects-{$repoIdStr}' class='projects'>";
                    
                    // Check if there are projects for this repository
                    if (isset($projectsByRepoId[$repoIntId])) {
                        foreach ($projectsByRepoId[$repoIntId] as $project) {
                            $projectIdStr = (string)$project['_id'];
                            $projectName = htmlspecialchars($project['PROJECT_NAME'], ENT_QUOTES, 'UTF-8');
                            $projectIntId = (string)$project['PROJECT_ID'];
                            $project_icon = "<svg style='color: {$color}; opacity: 0.8;' xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z'></path></svg>";
                            
                            // Output project link
                            echo "<a href='#' class='project' onclick=\"event.preventDefault(); event.stopPropagation(); loadComponent('{$repoIdStr}', '{$projectIdStr}', this)\">
                                    {$project_icon}
                                    <span>{$projectName}</span>
                                    {$chevron_svg}
                                  </a>";

                            // Start components list
                            echo "<div id='components-{$projectIdStr}' class='components'>";

                            // Check if there are components for this project
                            if (isset($componentsByProjectId[$projectIntId])) {
                                foreach ($componentsByProjectId[$projectIntId] as $component) {
                                    $componentIdStr = (string)$component['_id'];
                                    $componentName = htmlspecialchars($component['COMPONENT_NAME'], ENT_QUOTES, 'UTF-8');
                                    $component_icon = "<svg style='color: {$color}; opacity: 0.7;' xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z'></path><polyline points='14 2 14 8 20 8'></polyline><line x1='16' y1='13' x2='8' y2='13'></line><line x1='16' y1='17' x2='8' y2='17'></line><polyline points='10 9 9 9 8 9'></polyline></svg>";
                                    
                                    // Output component link (final node in this view)
                                    echo "<a href='#' class='component' onclick=\"event.preventDefault(); event.stopPropagation(); loadFile('{$projectIdStr}', '{$componentIdStr}', this)\">
                                            {$component_icon}
                                            <span>{$componentName}</span>
                                          </a>";
                                }
                            }
                            echo "</div>"; // end components
                        }
                    }
                    echo "</div>"; // end projects
                }
            } catch(MongoDB\Driver\Exception\Exception $e) {
                echo "数据库查询错误: " . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8');
            }
            // ########## END: MODIFIED FOR 4-COLLECTION SCHEMA ##########
            ?>
        </aside>
        <div class="content-panel">
            <iframe name="contentFrame" id="contentFrame" src="dashboard.php"></iframe>
        </div>
    </main>
</div>

<script>
    // --- Uptime counter (移植自 Nexus 项目) ---
    let uptimeSeconds = <?php echo $uptime_seconds; ?>;
    const uptimeElement = document.getElementById('uptime-display');

    if (uptimeElement && uptimeSeconds > 0) {
        const updateUptimeText = () => {
            const days = Math.floor(uptimeSeconds / 86400);
            const hours = Math.floor((uptimeSeconds % 86400) / 3600).toString().padStart(2, '0');
            const minutes = Math.floor((uptimeSeconds % 3600) / 60).toString().padStart(2, '0');
            const seconds = (uptimeSeconds % 60).toString().padStart(2, '0');
            uptimeElement.textContent = `${days}d ${hours}:${minutes}:${seconds}`;
        };
        updateUptimeText();
        setInterval(() => {
            uptimeSeconds++;
            updateUptimeText();
        }, 1000);
    } else if (uptimeElement) {
        uptimeElement.textContent = 'Uptime N/A';
    }
    
    // --- JS Logic (完全无变化) ---
    function loadProject(repoId, element) {
        document.getElementById('contentFrame').src = 'PROJECT.php?repository_id=' + repoId;
        toggleMenu('projects-' + repoId, element);
    }

    function loadComponent(repoId, projectId, element) {
        document.getElementById('contentFrame').src = 'COMPONENT.php?repository_id=' + repoId + '&project_id=' + projectId;
        toggleMenu('components-' + projectId, element);
    }

    function loadFile(projectId, componentId, element) {
        document.getElementById('contentFrame').src = 'FILE.php?project_id=' + projectId + '&component_id=' + componentId;
        const sidebarLinks = document.querySelectorAll('.sidebar-panel a');
        sidebarLinks.forEach(l => l.classList.remove('active'));
        element.classList.add('active');
    }

    function toggleMenu(menuId, anchorElement) {
        var menuDiv = document.getElementById(menuId);
        if (menuDiv) {
            if (menuDiv.style.display === 'none' || menuDiv.style.display === '') {
                menuDiv.style.display = 'block';
                if (anchorElement) anchorElement.classList.add('open');
            } else {
                menuDiv.style.display = 'none';
                if (anchorElement) anchorElement.classList.remove('open');
            }
        }
        const sidebarLinks = document.querySelectorAll('.sidebar-panel a');
        sidebarLinks.forEach(l => l.classList.remove('active'));
        if (anchorElement) anchorElement.classList.add('active');
    }

    window.onload = function() {
        document.getElementById('contentFrame').src = 'dashboard.php';
        const sidebarLinks = document.querySelectorAll('.sidebar-panel a');
        sidebarLinks.forEach(link => {
            link.addEventListener('click', function(e) {
                sidebarLinks.forEach(l => l.classList.remove('active'));
                e.currentTarget.classList.add('active');
            });
        });
    };
</script>

</body>
</html>
