<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Lazzaro | Memory Dashboard</title>
    <!-- Vue 3 CDN -->
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <!-- Tailwind CSS CDN -->
    <script src="https://cdn.tailwindcss.com"></script>
    <!-- Lucide Icons CDN -->
    <script src="https://unpkg.com/lucide@latest"></script>
    <!-- Force Graph CDN -->
    <script src="https://unpkg.com/force-graph"></script>

    <style>
        @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono&display=swap');

        body {
            font-family: 'Inter', sans-serif;
            background-color: #0c0c0e;
            color: #e4e4e7;
            overflow: hidden;
        }

        .glass {
            background: rgba(23, 23, 26, 0.7);
            backdrop-filter: blur(12px);
            border: 1px solid rgba(255, 255, 255, 0.1);
        }

        .gradient-text {
            background: linear-gradient(135deg, #a78bfa 0%, #60a5fa 100%);
            -webkit-background-clip: text;
            background-clip: text;
            -webkit-text-fill-color: transparent;
        }

        .custom-scrollbar::-webkit-scrollbar {
            width: 4px;
        }

        .custom-scrollbar::-webkit-scrollbar-track {
            background: transparent;
        }

        .custom-scrollbar::-webkit-scrollbar-thumb {
            background: rgba(255, 255, 255, 0.1);
            border-radius: 10px;
        }

        #graph-container {
            width: 100%;
            height: 100%;
        }

        .node-label {
            pointer-events: none;
            text-shadow: 0 1px 4px rgba(0, 0, 0, 0.8);
        }
    </style>
</head>

<body class="h-screen flex flex-col">
    <div id="app" class="h-full flex flex-col relative" v-cloak>

        <!-- Header -->
        <header class="h-16 flex items-center justify-between px-6 glass z-30 border-b border-white/5">
            <div class="flex items-center gap-3">
                <div
                    class="w-8 h-8 rounded-lg bg-gradient-to-br from-indigo-500 to-blue-600 flex items-center justify-center font-bold text-white">
                    L</div>
                <h1 class="text-xl font-semibold tracking-tight gradient-text">Lazzaro Dashboard</h1>
                <span
                    class="px-2 py-0.5 rounded-full bg-white/5 border border-white/10 text-[10px] font-medium text-zinc-400 uppercase tracking-widest ml-2">v0.1.2.3</span>
            </div>

            <div class="flex items-center gap-6">
                <div class="flex gap-4 text-xs font-medium text-zinc-500">
                    <div class="flex items-center gap-1.5"><span class="w-1.5 h-1.5 rounded-full bg-emerald-500"></span>
                        API Status: Active</div>
                    <div class="flex items-center gap-1.5"><span
                            class="w-1.5 h-1.5 rounded-full bg-blue-500 underline decoration-blue-500/30"></span> Port:
                        5299</div>
                </div>
                <button @click="refreshData" class="p-2 rounded-full hover:bg-white/5 text-zinc-400 transition-colors">
                    <i data-lucide="refresh-cw" class="w-5 h-5"></i>
                </button>
            </div>
        </header>

        <main class="flex-1 flex flex-col md:flex-row overflow-hidden relative">
            <!-- Sidebar: Stats & Metrics -->
            <aside
                class="w-full md:w-80 glass border-b md:border-b-0 md:border-r border-white/5 flex flex-col z-20 transition-all">
                <div class="p-4 md:p-6 overflow-y-auto custom-scrollbar flex-1">
                    <h2 class="text-xs font-semibold text-zinc-400 uppercase tracking-widest mb-6">System Health</h2>

                    <div class="grid grid-cols-2 gap-3 mb-8">
                        <div class="p-3 md:p-4 rounded-xl bg-white/5 border border-white/5">
                            <div class="text-[9px] text-zinc-500 mb-1 uppercase tracking-wider">Nodes</div>
                            <div class="text-xl md:text-2xl font-bold font-mono tracking-tight text-indigo-300">[[
                                stats.buffer_nodes || 0 ]]</div>
                        </div>
                        <div class="p-3 md:p-4 rounded-xl bg-white/5 border border-white/5">
                            <div class="text-[9px] text-zinc-500 mb-1 uppercase tracking-wider">Shards</div>
                            <div class="text-xl md:text-2xl font-bold font-mono tracking-tight text-blue-300">[[
                                stats.num_shards || 0 ]]</div>
                        </div>
                    </div>

                    <div class="p-4 rounded-xl bg-indigo-500/5 border border-indigo-500/10 mb-8">
                        <div class="text-[9px] text-zinc-400 mb-1 uppercase tracking-wider flex items-center gap-1.5">
                            <span class="w-1.5 h-1.5 rounded-full bg-indigo-500"></span>
                            Vector Backend
                        </div>
                        <div class="text-sm font-bold font-mono text-zinc-300">[[ stats.vector_store || 'None' ]]</div>
                    </div>

                    <h2 class="text-xs font-semibold text-zinc-400 uppercase tracking-widest mb-4">Performance</h2>
                    <div class="space-y-4 mb-8">
                        <div v-for="(val, key) in stats.performance" :key="key"
                            class="flex justify-between items-center text-[13px]">
                            <span class="text-zinc-500 capitalize">[[ key.replace(/_/g, ' ') ]]</span>
                            <span class="font-mono text-zinc-300">[[ val ]]</span>
                        </div>
                    </div>

                    <h2 class="text-xs font-semibold text-zinc-400 uppercase tracking-widest mb-4">Auto-Management</h2>
                    <div class="space-y-3">
                        <div
                            class="flex items-center justify-between p-3 rounded-lg bg-white/5 border border-white/5 text-xs">
                            <span class="text-zinc-400">Consolidation</span>
                            <span class="px-2 py-0.5 rounded bg-emerald-500/10 text-emerald-500 font-medium">[[
                                stats.auto_consolidate ? 'ENABLED' : 'DISABLED' ]]</span>
                        </div>
                        <button @click="runConsolidation"
                            class="w-full py-2.5 rounded-lg bg-indigo-500/10 border border-indigo-500/30 text-indigo-400 text-sm font-medium hover:bg-indigo-500/20 transition-all flex items-center justify-center gap-2">
                            <i data-lucide="box" class="w-4 h-4"></i> Run Consolidation
                        </button>
                    </div>
                </div>

                <!-- Profile Snippet -->
                <div class="p-4 md:p-6 border-t border-white/5 bg-black/20">
                    <div class="flex items-center justify-between mb-3">
                        <h2 class="text-xs font-semibold text-zinc-400 uppercase tracking-widest">User Profile</h2>
                        <i data-lucide="user" class="w-4 h-4 text-zinc-500"></i>
                    </div>
                    <div class="text-[12px] text-zinc-500 leading-relaxed italic line-clamp-4">
                        [[ profileContext || 'No profile data available yet.' ]]
                    </div>
                </div>
            </aside>

            <!-- Main Stage: Graph -->
            <section class="flex-1 relative bg-[#09090b] min-h-[400px] overflow-hidden">
                <div id="graph-container" class="w-full h-full"></div>

                <!-- Legend -->
                <div
                    class="absolute bottom-6 left-6 p-4 rounded-xl glass border border-white/5 z-20 pointer-events-none hidden md:block">
                    <div class="text-[10px] text-zinc-500 uppercase tracking-widest mb-3">Node Types</div>
                    <div class="space-y-2">
                        <div class="flex items-center gap-2 text-xs text-zinc-400">
                            <span class="w-3 h-3 rounded-full bg-blue-500"></span> Semantic
                        </div>
                        <div class="flex items-center gap-2 text-xs text-zinc-400">
                            <span class="w-3 h-3 rounded-full bg-emerald-500"></span> Episodic
                        </div>
                        <div class="flex items-center gap-2 text-xs text-zinc-400">
                            <span class="w-3 h-3 rounded-full bg-amber-500"></span> Super Node
                        </div>
                    </div>
                </div>

                <!-- Active Node Inspector (Floating Panel) -->
                <div v-if="selectedNode"
                    class="absolute top-6 right-10 w-80 md:w-96 glass border border-white/10 p-6 rounded-2xl animate-in slide-in-from-right-4 transition-all z-50 shadow-2xl backdrop-blur-xl">
                    <div class="flex justify-between items-start mb-4">
                        <span
                            class="px-2 py-0.5 rounded bg-indigo-500/10 text-indigo-400 text-[10px] font-bold uppercase tracking-widest">[[
                            selectedNode.type ]]</span>
                        <button @click="selectedNode = null"
                            class="text-zinc-600 hover:text-white transition-colors bg-white/5 p-1 rounded-md"><i
                                data-lucide="x" class="w-4 h-4"></i></button>
                    </div>
                    <div class="text-xs font-mono text-zinc-500 mb-3 uppercase tracking-tighter">ID: [[ selectedNode.id
                        ]] <span class="mx-2 opacity-30">|</span> Shard: [[ selectedNode.shard ]]</div>
                    <p class="text-sm md:text-base font-medium leading-relaxed mb-6 text-white text-wrap">"[[
                        selectedNode.content
                        ]]"</p>
                    <div class="grid grid-cols-2 gap-3">
                        <div class="p-3 rounded-xl bg-white/5 border border-white/5">
                            <div class="text-[9px] text-zinc-500 uppercase tracking-wider mb-1">Salience</div>
                            <div class="text-lg font-bold font-mono text-indigo-300">[[ selectedNode.salience.toFixed(2)
                                ]]</div>
                        </div>
                        <div class="p-3 rounded-xl bg-white/5 border border-white/5">
                            <div class="text-[9px] text-zinc-500 uppercase tracking-wider mb-1">Accesses</div>
                            <div class="text-lg font-bold font-mono text-blue-300">[[ selectedNode.access_count ]]x
                            </div>
                        </div>
                    </div>
                </div>
            </section>
        </main>

    </div>

    <script>
        const { createApp, ref, onMounted, nextTick } = Vue;

        createApp({
            setup() {
                const stats = ref({});
                const graphData = ref({ nodes: [], links: [] });
                const profileContext = ref("");
                const selectedNode = ref(null);
                let graph = null;

                const refreshData = async () => {
                    try {
                        const [statsRes, graphRes, profileRes] = await Promise.all([
                            fetch('/api/stats').then(r => r.json()),
                            fetch('/api/graph').then(r => r.json()),
                            fetch('/api/profile').then(r => r.json())
                        ]);

                        stats.value = statsRes;
                        graphData.value = graphRes;

                        // Humanize profile
                        if (profileRes.data) {
                            const domains = [];
                            for (const [k, v] of Object.entries(profileRes.data)) {
                                if (v) domains.push(`${k.replace('_', ' ')}: ${v}`);
                            }
                            profileContext.value = domains.join(' | ');
                        }

                        updateGraph();
                        lucide.createIcons();
                    } catch (err) {
                        console.error("Failed to fetch dashboard data", err);
                    }
                };

                const updateGraph = () => {
                    if (!graph) return;
                    graph.graphData(graphData.value);
                };

                const initGraph = () => {
                    const container = document.getElementById('graph-container');
                    graph = ForceGraph()(container)
                        .graphData(graphData.value)
                        .nodeId('id')
                        .nodeLabel(node => `${node.id}: ${node.content.substring(0, 50)}...`)
                        .nodeColor(node => {
                            if (node.is_super_node) return '#f59e0b';
                            if (node.type === 'episodic') return '#10b981';
                            return '#3b82f6';
                        })
                        .nodeVal(node => Math.max(2, node.salience * 10))
                        .linkColor(() => 'rgba(255, 255, 255, 0.08)')
                        .linkWidth(link => link.weight * 2)
                        .backgroundColor('#09090b')
                        .onNodeClick(node => {
                            selectedNode.value = node;
                            nextTick(() => lucide.createIcons());
                        })
                        .nodeRelSize(6)
                        .cooldownTicks(100);

                    // Add glow effect or customized particles if needed
                    graph.d3Force('charge').strength(-150);
                };

                const runConsolidation = async () => {
                    try {
                        await fetch('/api/consolidate', { method: 'POST' });
                        setTimeout(refreshData, 1000);
                    } catch (err) {
                        console.error("Consolidation failed");
                    }
                };

                onMounted(() => {
                    initGraph();
                    refreshData();
                    lucide.createIcons();

                    window.addEventListener('resize', () => {
                        if (graph) {
                            const container = document.getElementById('graph-container');
                            graph.width(container.clientWidth);
                            graph.height(container.clientHeight);
                        }
                    });

                    // Periodic refresh
                    setInterval(refreshData, 10000);
                });

                return {
                    stats,
                    graphData,
                    profileContext,
                    selectedNode,
                    refreshData,
                    runConsolidation
                };
            },
            delimiters: ['[[', ']]']
        }).mount('#app');
    </script>
</body>

</html>