<template>
  <div>
    <div class="page-header">
      <div class="page-title">
        <h2>Query Cache</h2>
        <span class="subtitle">In-memory LRU cache for compiled SQL queries — inspect and flush as needed</span>
      </div>
      <div class="header-actions">
        <NychButton @click="load">Refresh</NychButton>
        <NychButton severity="danger" @click="flushCache">Flush Cache</NychButton>
      </div>
    </div>

    <div class="stats-grid" v-if="stats">
      <div class="stat-card">
        <span class="stat-label">Entries</span>
        <span class="stat-value">{{ stats.size }}</span>
      </div>
      <div class="stat-card">
        <span class="stat-label">Cache Hits</span>
        <span class="stat-value success">{{ stats.hits }}</span>
      </div>
      <div class="stat-card">
        <span class="stat-label">Cache Misses</span>
        <span class="stat-value muted">{{ stats.misses }}</span>
      </div>
      <div class="stat-card hit-rate-card">
        <span class="stat-label">Hit Rate</span>
        <span class="stat-value" :class="hitRateClass">{{ hitRate }}%</span>
        <div class="hit-rate-bar">
          <div class="hit-rate-fill" :style="{ width: hitRate + '%' }"></div>
        </div>
      </div>
    </div>

    <div class="no-stats" v-else>
      <span class="empty-icon">◈</span>
      <span class="empty-label">Cache stats unavailable</span>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { useAuthStore } from '../../stores/auth'

const auth = useAuthStore()
const stats = ref<{ size: number; hits: number; misses: number } | null>(null)

const hitRate = computed(() => {
  if (!stats.value) return 0
  const total = stats.value.hits + stats.value.misses
  return total === 0 ? 0 : Math.round((stats.value.hits / total) * 100)
})

const hitRateClass = computed(() => {
  const r = hitRate.value
  if (r >= 80) return 'good'
  if (r >= 50) return 'ok'
  return 'poor'
})

async function load() {
  const res = await fetch('/api/admin/cache/stats', { headers: auth.authHeaders() })
  stats.value = await res.json()
}

async function flushCache() {
  if (!confirm('Flush the entire query cache?')) return
  await fetch('/api/admin/cache/', { method: 'DELETE', headers: auth.authHeaders() })
  load()
}

onMounted(load)
</script>

<style scoped>
.header-actions { display: flex; gap: 0.5rem; }

.stats-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
}

.stat-card {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1.5rem 1.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  box-shadow: 0 2px 8px rgba(0,0,0,0.05);
}

.stat-label {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.stat-value {
  font-family: var(--font-mono);
  font-size: 2.4rem;
  font-weight: 500;
  line-height: 1;
  color: var(--primary);
}
.stat-value.success { color: var(--success); }
.stat-value.muted   { color: var(--text-muted); }
.stat-value.good    { color: var(--success); }
.stat-value.ok      { color: var(--warn); }
.stat-value.poor    { color: var(--danger); }

.hit-rate-card { gap: 0.75rem; }

.hit-rate-bar {
  height: 4px;
  background: var(--surface-2);
  border-radius: 2px;
  overflow: hidden;
  margin-top: auto;
}

.hit-rate-fill {
  height: 100%;
  background: var(--primary);
  border-radius: 2px;
  transition: width 0.4s ease;
}

.no-stats {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  padding: 4rem;
  color: var(--text-dim);
}

.no-stats .empty-icon {
  font-size: 2.5rem;
  opacity: 0.3;
}

.no-stats .empty-label {
  font-family: var(--font-serif);
  font-size: 1rem;
  color: var(--text-muted);
}
</style>
