<template>
  <div class="app-layout">
    <SidebarNav />
    
    <div class="main-content">
      <header class="main-header">
        <h1 class="page-title">📈 Server Status</h1>
        <div class="header-info">
          <span class="current-time">{{ currentTime }}</span>
          <ThemeToggle />
        </div>
      </header>
      
      <main class="main-body">
        <!-- 상단 고정 영역 -->
        <div class="fixed-top">
          <!-- 첫 번째 줄: 조회 기간 -->
          <section class="filter-row">
            <span class="filter-label">조회 기간</span>
            <div class="period-buttons">
              <button 
                v-for="p in periods" 
                :key="p.value"
                :class="['period-btn', { active: selectedPeriod === p.value }]"
                @click="changePeriod(p.value)"
              >
                {{ p.label }}
              </button>
            </div>
          </section>
          
          <!-- 두 번째 줄: 서버 목록 -->
          <section class="server-row">
            <span class="filter-label">서버</span>
            <div class="server-buttons">
              <button 
                v-for="target in targets" 
                :key="target.target_id"
                :class="['server-btn', { active: selectedTargetId === target.target_id }]"
                @click="selectServer(target.target_id)"
              >
                <span class="server-status" :class="{ online: target.is_active }"></span>
                {{ target.server_name }}
              </button>
            </div>
            <div class="server-nav">
              <button class="nav-btn" @click="prevServer">◀</button>
              <button class="nav-btn" @click="nextServer">▶</button>
            </div>
            <div class="auto-rotate">
              <label class="rotate-checkbox">
                <input type="checkbox" v-model="autoRotate" @change="onAutoRotateChange">
                <span>자동순환</span>
              </label>
              <div class="rotate-intervals">
                <button 
                  :class="['rotate-btn', { active: rotateInterval === 1/6 }]"
                  :disabled="!autoRotate"
                  @click="changeRotateInterval(1/6)"
                >
                  10초
                </button>
                <button 
                  :class="['rotate-btn', { active: rotateInterval === 0.5 }]"
                  :disabled="!autoRotate"
                  @click="changeRotateInterval(0.5)"
                >
                  30초
                </button>
                <button 
                  v-for="min in [1, 3, 5]" 
                  :key="min"
                  :class="['rotate-btn', { active: rotateInterval === min }]"
                  :disabled="!autoRotate"
                  @click="changeRotateInterval(min)"
                >
                  {{ min }}분
                </button>
              </div>
              <span class="rotate-remaining" v-if="autoRotate">{{ formatRemaining(rotateRemaining) }}</span>
            </div>
          </section>

          <!-- 스냅샷 정보 -->
          <section class="snapshot-info" v-if="latestSnapshot">
            <div class="info-grid">
              <div class="info-item">
                <label>호스트명</label>
                <span>{{ latestSnapshot.host_name || '-' }}</span>
              </div>
              <div class="info-item">
                <label>OS</label>
                <span>{{ latestSnapshot.os_name }} {{ latestSnapshot.os_version }}</span>
              </div>
              <div class="info-item">
                <label>IP</label>
                <span>{{ latestSnapshot.ip_address || '-' }}</span>
              </div>
              <div class="info-item">
                <label>CPU</label>
                <span>{{ latestSnapshot.cpu_name || '-' }} ({{ latestSnapshot.cpu_count || '-' }} cores)</span>
              </div>
              <div class="info-item">
                <label>Memory</label>
                <span>{{ formatBytes(latestSnapshot.memory_total) }}</span>
              </div>
              <div class="info-item">
                <label>Swap</label>
                <span>{{ formatBytes(latestSnapshot.swap_total) }}</span>
              </div>
              <div class="info-item">
                <label>Uptime</label>
                <span>{{ latestSnapshot.uptime_str || '-' }}</span>
              </div>
              <div class="info-item">
                <label>컨테이너</label>
                <span>{{ containerData.length }}개</span>
              </div>
              <div class="info-item">
                <label>수집시간</label>
                <span>{{ latestSnapshot.collected_at }}</span>
              </div>
            </div>
            <div class="disk-list" v-if="diskList.length > 0">
              <label>Disks</label>
              <div class="disk-items">
                <span v-for="disk in diskList" :key="disk.mount_point" class="disk-item">
                  {{ disk.mount_point }} ({{ formatBytes(disk.disk_total) }}, {{ disk.disk_percent?.toFixed(1) }}%)
                </span>
              </div>
            </div>
          </section>
        </div>

        <!-- 하단 스크롤 영역 -->
        <div class="scroll-area">
          <!-- 시스템 차트 (4개) -->
          <section class="chart-row">
            <div class="chart-box">
              <div class="chart-header">
                <h4>CPU / 온도 / Load</h4>
              <span class="chart-avg" v-if="cpuAvg">{{ latestSnapshot?.cpu_name || '-' }} ({{ latestSnapshot?.cpu_count || '-' }} cores) | 평균: CPU <span class="val-cpu">{{ cpuAvg.cpu }}%</span> | 온도 <span class="val-temp">{{ cpuAvg.temp }}°C</span> | Load <span class="val-load">{{ cpuAvg.load }}%</span></span>
            </div>
            <div class="chart-container"><canvas ref="cpuChartRef"></canvas></div>
          </div>
          <div class="chart-box">
            <div class="chart-header">
              <h4>Memory / Swap</h4>
              <span class="chart-avg" v-if="memAvg">평균: Mem <span class="val-mem">{{ memAvg.mem }}% ({{ memAvg.used }}/{{ memAvg.total }} GB)</span> | Swap <span class="val-swap">{{ memAvg.swap }}% ({{ memAvg.swapUsed }}/{{ memAvg.swapTotal }} GB)</span></span>
            </div>
            <div class="chart-container"><canvas ref="memChartRef"></canvas></div>
          </div>
          <div class="chart-box">
            <div class="chart-header">
              <h4>Disk 사용률</h4>
              <span class="chart-avg" v-if="diskAvg">평균: <span class="val-disk">{{ diskAvg.percent }}% ({{ diskAvg.used }}/{{ diskAvg.total }} GB)</span></span>
            </div>
            <div class="chart-container"><canvas ref="diskChartRef"></canvas></div>
          </div>
          <div class="chart-box">
            <div class="chart-header">
              <h4>Network I/O</h4>
              <span class="chart-avg" v-if="networkAvg">평균: RX <span class="val-rx">{{ networkAvg.rx }}</span> | TX <span class="val-tx">{{ networkAvg.tx }}</span></span>
            </div>
            <div class="chart-container"><canvas ref="networkMainChartRef"></canvas></div>
          </div>
        </section>

        <!-- 컨테이너 영역 -->
        <section class="container-section">
          <h3 class="section-title">🐳 컨테이너</h3>
          <div class="container-cards">
            <div v-for="container in containerData" :key="container.name" class="container-card" :class="container.status">
              <div class="container-header">
                <span class="container-name">{{ container.name }}</span>
                <span class="container-status" :class="container.status">{{ container.status }}</span>
                <span class="container-uptime">{{ container.uptime || '-' }}</span>
              </div>
              <div class="container-charts">
                <div class="container-chart-box">
                  <div class="chart-header">
                    <span class="chart-title">CPU</span>
                    <span class="chart-avg">평균: <span class="val-cpu">{{ container.cpuAvg }}%</span></span>
                  </div>
                  <div class="container-chart"><canvas :ref="el => setContainerChartRef(container.name, 'cpu', el)"></canvas></div>
                </div>
                <div class="container-chart-box">
                  <div class="chart-header">
                    <span class="chart-title">Memory</span>
                    <span class="chart-avg">평균: <span class="val-mem">{{ container.memAvg }}</span> / {{ container.memLimit }}</span>
                  </div>
                  <div class="container-chart"><canvas :ref="el => setContainerChartRef(container.name, 'mem', el)"></canvas></div>
                </div>
                <div class="container-chart-box">
                  <div class="chart-header">
                    <span class="chart-title">Network</span>
                    <span class="chart-avg">RX <span class="val-rx">{{ container.rxAvg }}</span> | TX <span class="val-tx">{{ container.txAvg }}</span></span>
                  </div>
                  <div class="container-chart"><canvas :ref="el => setContainerChartRef(container.name, 'net', el)"></canvas></div>
                </div>
              </div>
            </div>
          </div>
        </section>
        </div>
      </main>
    </div>
  </div>
</template>

<script setup lang="ts">
import { Chart, registerables } from 'chart.js'
Chart.register(...registerables)

interface ServerTarget {
  target_id: number
  server_name: string
  server_ip: string
  is_active: number
}

const targets = ref<ServerTarget[]>([])
const selectedTargetId = ref<number | null>(null)
const selectedPeriod = ref('1h')
const currentTime = ref('')
const latestSnapshot = ref<any>(null)
const diskList = ref<any[]>([])

// 자동 순환 (rotateInterval은 분 단위, 10초 = 1/6분)
const autoRotate = ref(true)
const rotateInterval = ref(1/6)
const rotateRemaining = ref(10)
let rotateTimer: ReturnType<typeof setInterval> | null = null
let countdownTimer: ReturnType<typeof setInterval> | null = null

const periods = [
  { value: '1h', label: '1시간' },
  { value: '2h', label: '2시간' },
  { value: '3h', label: '3시간' },
  { value: '4h', label: '4시간' },
  { value: '5h', label: '5시간' },
  { value: '6h', label: '6시간' },
  { value: '12h', label: '12시간' },
  { value: '18h', label: '18시간' },
  { value: '24h', label: '24시간' },
  { value: '7d', label: '7일' },
  { value: '30d', label: '30일' }
]

const cpuChartRef = ref<HTMLCanvasElement | null>(null)
const memChartRef = ref<HTMLCanvasElement | null>(null)
const diskChartRef = ref<HTMLCanvasElement | null>(null)
const networkMainChartRef = ref<HTMLCanvasElement | null>(null)

let cpuChart: Chart | null = null
let memChart: Chart | null = null
let diskChart: Chart | null = null
let networkMainChart: Chart | null = null

// 컨테이너 차트 관리
interface ContainerInfo {
  name: string
  status: string
  uptime: string
  cpuAvg: string
  memAvg: string
  memLimit: string
  rxAvg: string
  txAvg: string
}
const containerData = ref<ContainerInfo[]>([])
const containerChartRefs: Record<string, Record<string, HTMLCanvasElement | null>> = {}
const containerCharts: Record<string, Record<string, Chart | null>> = {}

function setContainerChartRef(name: string, type: string, el: any) {
  if (!containerChartRefs[name]) containerChartRefs[name] = {}
  containerChartRefs[name][type] = el as HTMLCanvasElement | null
}

// 평균값
const cpuAvg = ref<{ cpu: string; temp: string; load: string } | null>(null)
const memAvg = ref<{ mem: string; swap: string; used: string; total: string; swapUsed: string; swapTotal: string } | null>(null)
const diskAvg = ref<{ percent: string; used: string; total: string } | null>(null)
const networkAvg = ref<{ rx: string; tx: string } | null>(null)

const chartColors = ['#3b82f6', '#22c55e', '#f59e0b', '#ef4444', '#8b5cf6', '#06b6d4', '#ec4899', '#14b8a6', '#f97316', '#6366f1']

function formatTime(date: Date): string {
  return date.toLocaleString('sv-SE', { timeZone: 'Asia/Seoul' }).replace('T', ' ')
}

function formatUptime(seconds: number | null): string {
  if (!seconds) return '-'
  const days = Math.floor(seconds / 86400)
  const hours = Math.floor((seconds % 86400) / 3600)
  const mins = Math.floor((seconds % 3600) / 60)
  if (days > 0) return `${days}일 ${hours}시간`
  if (hours > 0) return `${hours}시간 ${mins}분`
  return `${mins}분`
}

function formatBytes(bytes: number | null): string {
  if (!bytes) return '-'
  const gb = bytes / (1024 * 1024 * 1024)
  if (gb >= 1024) return `${(gb / 1024).toFixed(1)} TB`
  if (gb >= 1) return `${gb.toFixed(1)} GB`
  return `${(bytes / (1024 * 1024)).toFixed(0)} MB`
}

function formatBytesPerSec(bytes: number): string {
  if (bytes >= 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB/s`
  if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB/s`
  if (bytes >= 1024) return `${(bytes / 1024).toFixed(1)} KB/s`
  return `${bytes.toFixed(0)} B/s`
}

function createLineChart(canvas: HTMLCanvasElement, labels: string[], datasets: { label: string; data: number[]; borderColor: string }[], maxY: number | null = 100): Chart {
  return new Chart(canvas, {
    type: 'line',
    data: { labels, datasets: datasets.map(ds => ({ ...ds, fill: false, tension: 0.3, pointRadius: 1, borderWidth: 2 })) },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      plugins: { legend: { position: 'top', labels: { boxWidth: 12, font: { size: 11 } } } },
      scales: {
        x: { ticks: { maxTicksLimit: 8, font: { size: 10 } } },
        y: { beginAtZero: true, max: maxY || undefined }
      }
    }
  })
}

function createCpuTempLoadChart(canvas: HTMLCanvasElement, labels: string[], cpuData: number[], tempData: number[], loadData: number[]): Chart {
  return new Chart(canvas, {
    type: 'line',
    data: {
      labels,
      datasets: [
        { label: 'CPU %', data: cpuData, borderColor: chartColors[0], fill: false, tension: 0.3, pointRadius: 1, borderWidth: 2, yAxisID: 'y' },
        { label: 'Load %', data: loadData, borderColor: chartColors[4], fill: false, tension: 0.3, pointRadius: 1, borderWidth: 2, yAxisID: 'y' },
        { label: '온도 °C', data: tempData, borderColor: chartColors[3], fill: false, tension: 0.3, pointRadius: 1, borderWidth: 2, yAxisID: 'y1' }
      ]
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      plugins: { legend: { position: 'top', labels: { boxWidth: 12, font: { size: 11 } } } },
      scales: {
        x: { ticks: { maxTicksLimit: 8, font: { size: 10 } } },
        y: { type: 'linear', position: 'left', beginAtZero: true, max: 100, title: { display: true, text: '%', font: { size: 10 } } },
        y1: { type: 'linear', position: 'right', beginAtZero: true, max: 100, grid: { drawOnChartArea: false }, title: { display: true, text: '°C', font: { size: 10 } } }
      }
    }
  })
}

async function fetchTargets() {
  try {
    const res = await $fetch('/api/server/targets')
    targets.value = (res as ServerTarget[]) || []
    if (targets.value.length > 0 && !selectedTargetId.value) {
      selectedTargetId.value = targets.value[0].target_id
    }
  } catch (err) { console.error('Failed to fetch targets:', err) }
}

async function fetchLatestSnapshot() {
  if (!selectedTargetId.value) return
  try {
    latestSnapshot.value = await $fetch('/api/server/history/latest', { query: { target_id: selectedTargetId.value } })
  } catch (err) { console.error('Failed to fetch latest snapshot:', err) }
}

async function fetchDiskList() {
  if (!selectedTargetId.value) return
  try {
    const res = await $fetch('/api/server/history/disk-list', { query: { target_id: selectedTargetId.value } }) as any[]
    diskList.value = res || []
  } catch (err) { console.error('Failed to fetch disk list:', err) }
}

async function fetchSnapshots() {
  if (!selectedTargetId.value || !cpuChartRef.value) return
  try {
    const res = await $fetch('/api/server/history/snapshots', { query: { target_id: selectedTargetId.value, period: selectedPeriod.value } }) as any
    const data = res.data || []
    const labels = data.map((d: any) => d.collected_at?.substring(11, 16) || '')
    
    cpuChart?.destroy()
    memChart?.destroy()
    
    // CPU + 온도 + Load 차트 (듀얼 Y축: 왼쪽 %, 오른쪽 °C)
    const cpuData = data.map((d: any) => d.cpu_percent || 0)
    const tempData = data.map((d: any) => d.cpu_temp || 0)
    const loadData = data.map((d: any) => d.load_percent || 0)
    cpuChart = createCpuTempLoadChart(cpuChartRef.value!, labels, cpuData, tempData, loadData)
    
    // 평균 계산 (CPU, 온도, Load)
    const validCpu = cpuData.filter((v: number) => v > 0)
    const validTemp = tempData.filter((v: number) => v > 0)
    const validLoad = loadData.filter((v: number) => v > 0)
    cpuAvg.value = {
      cpu: validCpu.length ? (validCpu.reduce((a: number, b: number) => a + b, 0) / validCpu.length).toFixed(1) : '-',
      temp: validTemp.length ? (validTemp.reduce((a: number, b: number) => a + b, 0) / validTemp.length).toFixed(1) : '-',
      load: validLoad.length ? (validLoad.reduce((a: number, b: number) => a + b, 0) / validLoad.length).toFixed(1) : '-'
    }
    
    // Memory/Swap 라인 차트 - memory_percent 직접 사용
    const memData = data.map((d: any) => d.memory_percent || 0)
    const swapData = data.map((d: any) => {
      const total = Number(d.swap_total) || 0
      const used = Number(d.swap_used) || 0
      if (total === 0) return 0
      return (used / total) * 100
    })
    memChart = createLineChart(memChartRef.value!, labels, [
      { label: 'Memory %', data: memData, borderColor: chartColors[1] },
      { label: 'Swap %', data: swapData, borderColor: chartColors[2] }
    ])
    
    // 평균 계산 (Memory, Swap) + 사용량/전체용량 (BigInt는 문자열로 반환되므로 Number로 변환)
    // 메모리 사용량 = memory_used (DB에서 계산된 값)
    const validMem = memData.filter((v: number) => v > 0)
    const validSwap = swapData.filter((v: number) => v >= 0)
    const memUsedData = data.map((d: any) => Number(d.memory_used) || 0).filter((v: number) => v > 0)
    const avgMemUsedGB = memUsedData.length ? (memUsedData.reduce((a: number, b: number) => a + b, 0) / memUsedData.length / (1024 * 1024 * 1024)).toFixed(1) : '-'
    const memTotalGB = data[0]?.memory_total ? (Number(data[0].memory_total) / (1024 * 1024 * 1024)).toFixed(1) : '-'
    const swapUsedData = data.map((d: any) => Number(d.swap_used) || 0).filter((v: number) => v >= 0)
    const avgSwapUsedGB = swapUsedData.length ? (swapUsedData.reduce((a: number, b: number) => a + b, 0) / swapUsedData.length / (1024 * 1024 * 1024)).toFixed(1) : '0'
    const swapTotalGB = data[0]?.swap_total ? (Number(data[0].swap_total) / (1024 * 1024 * 1024)).toFixed(1) : '0'
    memAvg.value = {
      mem: validMem.length ? (validMem.reduce((a: number, b: number) => a + b, 0) / validMem.length).toFixed(1) : '-',
      swap: validSwap.length ? (validSwap.reduce((a: number, b: number) => a + b, 0) / validSwap.length).toFixed(1) : '-',
      used: avgMemUsedGB,
      total: memTotalGB,
      swapUsed: avgSwapUsedGB,
      swapTotal: swapTotalGB
    }
    
  } catch (err) { console.error('Failed to fetch snapshots:', err) }
}

async function fetchDisks() {
  if (!selectedTargetId.value || !diskChartRef.value) return
  try {
    const res = await $fetch('/api/server/history/disks', { query: { target_id: selectedTargetId.value, period: selectedPeriod.value } }) as any
    const data = (res.data || []).filter((d: any) => d.device_name && !d.device_name.includes('loop') && !d.mount_point?.includes('/snap') && d.fs_type !== 'tmpfs' && d.fs_type !== 'squashfs')
    const mountPoints = [...new Set(data.map((d: any) => d.mount_point))]
    const timeLabels = [...new Set(data.map((d: any) => d.collected_at?.substring(11, 16)))] as string[]
    const datasets = mountPoints.map((mp, idx) => ({
      label: mp as string,
      data: timeLabels.map(time => data.find((d: any) => d.mount_point === mp && d.collected_at?.substring(11, 16) === time)?.disk_percent || 0),
      borderColor: chartColors[idx % chartColors.length]
    }))
    diskChart?.destroy()
    diskChart = createLineChart(diskChartRef.value!, timeLabels, datasets)
    
    // 평균 계산 (전체 디스크) + 사용량/전체용량 (BigInt는 문자열로 반환되므로 Number로 변환)
    const allPercents = data.map((d: any) => d.disk_percent || 0).filter((v: number) => v > 0)
    const allUsed = data.map((d: any) => Number(d.disk_used) || 0).filter((v: number) => v > 0)
    const allTotal = data.map((d: any) => Number(d.disk_total) || 0).filter((v: number) => v > 0)
    const avgUsedGB = allUsed.length ? (allUsed.reduce((a: number, b: number) => a + b, 0) / allUsed.length / (1024 * 1024 * 1024)).toFixed(1) : '-'
    const avgTotalGB = allTotal.length ? (allTotal.reduce((a: number, b: number) => a + b, 0) / allTotal.length / (1024 * 1024 * 1024)).toFixed(1) : '-'
    diskAvg.value = {
      percent: allPercents.length ? (allPercents.reduce((a: number, b: number) => a + b, 0) / allPercents.length).toFixed(1) : '-',
      used: avgUsedGB,
      total: avgTotalGB
    }
  } catch (err) { console.error('Failed to fetch disks:', err) }
}

async function fetchContainers() {
  if (!selectedTargetId.value) return
  try {
    const res = await $fetch('/api/server/history/containers', { query: { target_id: selectedTargetId.value, period: selectedPeriod.value } }) as any
    const data = res.data || []
    const names = [...new Set(data.map((d: any) => d.container_name))] as string[]
    
    // 기존 차트 정리
    Object.values(containerCharts).forEach(charts => {
      Object.values(charts).forEach(chart => chart?.destroy())
    })
    
    // 컨테이너별 데이터 구성
    const containers: ContainerInfo[] = []
    
    for (const name of names) {
      const containerRows = data.filter((d: any) => d.container_name === name)
      if (containerRows.length === 0) continue
      
      const latest = containerRows[containerRows.length - 1]
      const timeLabels = containerRows.map((d: any) => d.collected_at?.substring(11, 16))
      
      // CPU 평균
      const cpuValues = containerRows.map((d: any) => d.cpu_percent || 0)
      const cpuAvgVal = cpuValues.length ? (cpuValues.reduce((a: number, b: number) => a + b, 0) / cpuValues.length).toFixed(1) : '0'
      
      // Memory 평균 (bytes -> MB, BigInt는 문자열로 반환되므로 Number로 변환)
      const memValues = containerRows.map((d: any) => (Number(d.memory_usage) || 0) / 1024 / 1024)
      const memAvgVal = memValues.length ? (memValues.reduce((a: number, b: number) => a + b, 0) / memValues.length) : 0
      const memLimit = latest.memory_limit ? (Number(latest.memory_limit) / 1024 / 1024 / 1024).toFixed(1) + ' GB' : '-'
      
      // Network 평균 (bytes/s -> KB/s)
      const rxValues = containerRows.map((d: any) => (Number(d.network_rx) || 0) / 1024)
      const txValues = containerRows.map((d: any) => (Number(d.network_tx) || 0) / 1024)
      const rxAvgVal = rxValues.length ? (rxValues.reduce((a: number, b: number) => a + b, 0) / rxValues.length) : 0
      const txAvgVal = txValues.length ? (txValues.reduce((a: number, b: number) => a + b, 0) / txValues.length) : 0
      
      containers.push({
        name,
        status: latest.container_status || 'unknown',
        uptime: latest.uptime || '-',
        cpuAvg: cpuAvgVal,
        memAvg: formatBytes(memAvgVal * 1024 * 1024),
        memLimit,
        rxAvg: formatBytesPerSec(rxAvgVal * 1024),
        txAvg: formatBytesPerSec(txAvgVal * 1024)
      })
    }
    
    containerData.value = containers
    
    // 다음 틱에서 차트 생성 (DOM 업데이트 후)
    await nextTick()
    
    for (const name of names) {
      const containerRows = data.filter((d: any) => d.container_name === name)
      const timeLabels = containerRows.map((d: any) => d.collected_at?.substring(11, 16))
      
      const refs = containerChartRefs[name]
      if (!refs) continue
      
      if (!containerCharts[name]) containerCharts[name] = {}
      
      // CPU 차트 (0-200% - 컨테이너는 멀티코어로 100% 초과 가능)
      if (refs.cpu) {
        const cpuData = containerRows.map((d: any) => d.cpu_percent || 0)
        containerCharts[name].cpu = createLineChart(refs.cpu, timeLabels, [{ label: 'CPU %', data: cpuData, borderColor: '#3b82f6' }], 200)
      }
      
      // Memory 차트 (MB 단위) - 자동 스케일 (BigInt 문자열 변환)
      if (refs.mem) {
        const memData = containerRows.map((d: any) => (Number(d.memory_usage) || 0) / 1024 / 1024)
        containerCharts[name].mem = createLineChart(refs.mem, timeLabels, [{ label: 'Memory MB', data: memData, borderColor: '#22c55e' }], null)
      }
      
      // Network 차트 (KB/s 단위) - 자동 스케일 (BigInt 문자열 변환)
      if (refs.net) {
        const rxData = containerRows.map((d: any) => (Number(d.network_rx) || 0) / 1024)
        const txData = containerRows.map((d: any) => (Number(d.network_tx) || 0) / 1024)
        containerCharts[name].net = createLineChart(refs.net, timeLabels, [
          { label: 'RX KB/s', data: rxData, borderColor: '#06b6d4' },
          { label: 'TX KB/s', data: txData, borderColor: '#f59e0b' }
        ], null)
      }
    }
  } catch (err) { console.error('Failed to fetch containers:', err) }
}

async function fetchNetworkMain() {
  if (!selectedTargetId.value || !networkMainChartRef.value) return
  try {
    const res = await $fetch('/api/server/history/networks', { query: { target_id: selectedTargetId.value, period: selectedPeriod.value } }) as any
    const data = res.data || []
    const ifaces = [...new Set(data.map((d: any) => d.interface_name))]
    const timeLabels = [...new Set(data.map((d: any) => d.collected_at?.substring(11, 16)))] as string[]
    const datasets: any[] = []
    ifaces.forEach((iface, idx) => {
      datasets.push({ label: `${iface} RX`, data: timeLabels.map(t => data.find((d: any) => d.interface_name === iface && d.collected_at?.substring(11, 16) === t)?.speed_recv || 0), borderColor: chartColors[idx * 2 % chartColors.length] })
      datasets.push({ label: `${iface} TX`, data: timeLabels.map(t => data.find((d: any) => d.interface_name === iface && d.collected_at?.substring(11, 16) === t)?.speed_sent || 0), borderColor: chartColors[(idx * 2 + 1) % chartColors.length] })
    })
    networkMainChart?.destroy()
    networkMainChart = createLineChart(networkMainChartRef.value!, timeLabels, datasets, null)
    
    // 평균 계산 (전체 RX/TX)
    const allRx = data.map((d: any) => d.speed_recv || 0).filter((v: number) => v > 0)
    const allTx = data.map((d: any) => d.speed_sent || 0).filter((v: number) => v > 0)
    const avgRx = allRx.length ? allRx.reduce((a: number, b: number) => a + b, 0) / allRx.length : 0
    const avgTx = allTx.length ? allTx.reduce((a: number, b: number) => a + b, 0) / allTx.length : 0
    networkAvg.value = {
      rx: formatBytesPerSec(avgRx),
      tx: formatBytesPerSec(avgTx)
    }
  } catch (err) { console.error('Failed to fetch network main:', err) }
}

async function fetchAllData() {
  await Promise.all([fetchLatestSnapshot(), fetchSnapshots(), fetchDisks(), fetchDiskList(), fetchNetworkMain()])
  await fetchContainers()
}

async function selectServer(targetId: number) {
  selectedTargetId.value = targetId
  // 자동순환 중이면 카운트다운 리셋
  if (autoRotate.value) {
    rotateRemaining.value = rotateInterval.value * 60
  }
  await fetchAllData()
}

function prevServer() {
  if (targets.value.length === 0) return
  const idx = targets.value.findIndex(t => t.target_id === selectedTargetId.value)
  const newIdx = idx <= 0 ? targets.value.length - 1 : idx - 1
  selectServer(targets.value[newIdx].target_id)
}

function nextServer() {
  if (targets.value.length === 0) return
  const idx = targets.value.findIndex(t => t.target_id === selectedTargetId.value)
  const newIdx = idx >= targets.value.length - 1 ? 0 : idx + 1
  selectServer(targets.value[newIdx].target_id)
}

// 자동 순환 기능
function startRotateTimer() {
  stopRotateTimer()
  if (!autoRotate.value) return
  
  // 남은 시간 초기화
  rotateRemaining.value = rotateInterval.value * 60
  
  // 1초마다 카운트다운
  countdownTimer = setInterval(() => {
    rotateRemaining.value--
    if (rotateRemaining.value <= 0) {
      nextServer()
      rotateRemaining.value = rotateInterval.value * 60
    }
  }, 1000)
}

function stopRotateTimer() {
  if (rotateTimer) {
    clearInterval(rotateTimer)
    rotateTimer = null
  }
  if (countdownTimer) {
    clearInterval(countdownTimer)
    countdownTimer = null
  }
  rotateRemaining.value = 0
}

function onAutoRotateChange() {
  if (autoRotate.value) {
    rotateInterval.value = 1/6
    startRotateTimer()
  } else {
    stopRotateTimer()
  }
}

function changeRotateInterval(min: number) {
  rotateInterval.value = min
  startRotateTimer()
}

function formatRemaining(seconds: number): string {
  const min = Math.floor(seconds / 60)
  const sec = seconds % 60
  return `${min}:${sec.toString().padStart(2, '0')}`
}

function changePeriod(period: string) {
  selectedPeriod.value = period
  fetchAllData()
}

let timeInterval: ReturnType<typeof setInterval> | null = null

onMounted(async () => {
  currentTime.value = formatTime(new Date())
  timeInterval = setInterval(() => { currentTime.value = formatTime(new Date()) }, 1000)
  await fetchTargets()
  if (selectedTargetId.value) await fetchAllData()
  // 자동 순환 기본 활성화
  if (autoRotate.value) startRotateTimer()
})

onUnmounted(() => {
  if (timeInterval) clearInterval(timeInterval)
  stopRotateTimer()
  cpuChart?.destroy()
  memChart?.destroy()
  diskChart?.destroy()
  networkMainChart?.destroy()
  // 컨테이너 차트 정리
  Object.values(containerCharts).forEach(charts => {
    Object.values(charts).forEach(chart => chart?.destroy())
  })
})
</script>

<style scoped>
.app-layout { display: flex; height: 100vh; background: var(--bg-primary); }
.main-content { flex: 1; display: flex; flex-direction: column; height: 100vh; overflow: hidden; }
.main-header { display: flex; justify-content: space-between; align-items: center; padding: 16px 24px; background: var(--bg-secondary); border-bottom: 1px solid var(--border-color); flex-shrink: 0; }
.page-title { font-size: 20px; font-weight: 600; color: var(--text-primary); margin: 0; }
.header-info { display: flex; align-items: center; gap: 16px; }
.current-time { font-family: monospace; color: var(--text-muted); }
.main-body { flex: 1; padding: 16px; display: flex; flex-direction: column; gap: 12px; overflow: hidden; }
.fixed-top { flex-shrink: 0; display: flex; flex-direction: column; gap: 12px; }
.scroll-area { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 12px; padding-bottom: 16px; }

/* 필터 행 */
.filter-row, .server-row { display: flex; align-items: center; gap: 12px; background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: 8px; padding: 10px 16px; }
.filter-label { font-size: 13px; font-weight: 600; color: var(--text-muted); min-width: 60px; }
.period-buttons { display: flex; gap: 6px; flex-wrap: wrap; }
.server-buttons { display: flex; gap: 6px; flex-wrap: wrap; flex: 1; }
.period-btn, .server-btn { padding: 6px 14px; border: 1px solid var(--border-color); border-radius: 6px; background: var(--bg-primary); color: var(--text-muted); font-size: 13px; cursor: pointer; transition: all 0.2s; }
.period-btn:hover, .server-btn:hover { border-color: var(--text-muted); }
.period-btn.active, .server-btn.active { background: var(--btn-primary-bg); border-color: var(--btn-primary-bg); color: #fff; }
.server-btn { display: flex; align-items: center; gap: 6px; }
.server-status { width: 8px; height: 8px; border-radius: 50%; background: var(--text-muted); }
.server-status.online { background: #22c55e; }
.server-nav { display: flex; gap: 6px; margin-left: auto; }
.nav-btn { width: 36px; height: 32px; border: 1px solid var(--border-color); border-radius: 6px; background: var(--bg-primary); color: var(--text-primary); font-size: 14px; cursor: pointer; transition: all 0.2s; display: flex; align-items: center; justify-content: center; }
.nav-btn:hover { background: var(--btn-primary-bg); border-color: var(--btn-primary-bg); color: #fff; }

/* 자동 순환 */
.auto-rotate { display: flex; align-items: center; gap: 10px; margin-left: 12px; padding-left: 12px; border-left: 1px solid var(--border-color); }
.rotate-checkbox { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text-primary); cursor: pointer; white-space: nowrap; }
.rotate-checkbox input { width: 16px; height: 16px; cursor: pointer; }
.rotate-intervals { display: flex; gap: 4px; }
.rotate-btn { padding: 4px 10px; border: 1px solid var(--border-color); border-radius: 4px; background: var(--bg-primary); color: var(--text-muted); font-size: 12px; cursor: pointer; transition: all 0.2s; }
.rotate-btn:hover:not(:disabled) { border-color: var(--text-muted); }
.rotate-btn.active { background: var(--btn-primary-bg); border-color: var(--btn-primary-bg); color: #fff; }
.rotate-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.rotate-remaining { font-size: 13px; font-weight: 600; color: var(--btn-primary-bg); font-family: monospace; min-width: 40px; }

/* 스냅샷 정보 */
.snapshot-info { background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: 8px; padding: 10px 16px; }
.info-grid { display: flex; flex-wrap: wrap; gap: 12px 24px; }
.info-item { display: flex; flex-direction: column; gap: 2px; }
.info-item label { font-size: 10px; color: var(--text-muted); text-transform: uppercase; }
.info-item span { font-size: 13px; color: var(--text-primary); font-weight: 500; }
.disk-list { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border-color); display: flex; align-items: flex-start; gap: 12px; }
.disk-list label { font-size: 10px; color: var(--text-muted); text-transform: uppercase; min-width: 40px; }
.disk-items { display: flex; flex-wrap: wrap; gap: 8px; }
.disk-item { font-size: 12px; color: var(--text-primary); background: var(--bg-primary); padding: 4px 8px; border-radius: 4px; border: 1px solid var(--border-color); }

/* 차트 행 */
.chart-row { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
.chart-box { background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: 8px; padding: 12px; }
.chart-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.chart-header h4 { margin: 0; font-size: 13px; font-weight: 600; color: var(--text-primary); }
.chart-avg { font-size: 13px; color: #1e293b; font-weight: 500; background: #e2e8f0; padding: 4px 10px; border-radius: 4px; }
.val-cpu { color: #2563eb; font-weight: 600; }
.val-temp { color: #dc2626; font-weight: 600; }
.val-mem { color: #16a34a; font-weight: 600; }
.val-swap { color: #d97706; font-weight: 600; }
.val-disk { color: #3b82f6; font-weight: 600; }
.val-load { color: #8b5cf6; font-weight: 600; }
.val-rx { color: #0891b2; font-weight: 600; }
.val-tx { color: #ea580c; font-weight: 600; }
.chart-container { height: 360px; position: relative; }

/* 컨테이너 섹션 */
.container-section { background: var(--bg-tertiary, #f1f5f9); border-radius: 12px; padding: 16px; margin-top: 16px; }
.section-title { margin: 0 0 16px 0; font-size: 16px; font-weight: 700; color: var(--text-primary); }
.container-cards { display: flex; flex-direction: column; gap: 16px; }
.container-card { background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: 10px; padding: 14px; }
.container-card.running { background: var(--container-normal-bg, #f0fdf4); border-color: var(--container-normal-border, #86efac); }
.container-card.exited { background: var(--container-danger-bg, #fef2f2); border-color: var(--container-danger-border, #fca5a5); }
.container-card.paused { background: var(--container-warning-bg, #fffbeb); border-color: var(--container-warning-border, #fcd34d); }
.container-card.restarting { background: var(--container-critical-bg, #fef3c7); border-color: var(--container-critical-border, #f59e0b); }
.container-header { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; padding-bottom: 10px; border-bottom: 1px solid var(--border-color); }
.container-card.running .container-header { border-color: var(--container-normal-border, #86efac); }
.container-card.exited .container-header { border-color: var(--container-danger-border, #fca5a5); }
.container-card.paused .container-header { border-color: var(--container-warning-border, #fcd34d); }
.container-card.restarting .container-header { border-color: var(--container-critical-border, #f59e0b); }
.container-name { font-size: 16px; font-weight: 700; color: var(--btn-primary-bg); background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
.container-card.exited .container-name { background: linear-gradient(135deg, #dc2626 0%, #f97316 100%); -webkit-background-clip: text; background-clip: text; }
.container-card.paused .container-name { background: linear-gradient(135deg, #d97706 0%, #eab308 100%); -webkit-background-clip: text; background-clip: text; }
.container-card.restarting .container-name { background: linear-gradient(135deg, #ea580c 0%, #facc15 100%); -webkit-background-clip: text; background-clip: text; }
.container-status { font-size: 12px; padding: 3px 10px; border-radius: 12px; font-weight: 500; }
.container-status.running { background: var(--container-normal-bg, #dcfce7); color: var(--container-status-running, #166534); }
.container-status.exited { background: var(--container-danger-bg, #fee2e2); color: var(--container-status-exited, #991b1b); }
.container-status.paused { background: var(--container-warning-bg, #fef3c7); color: var(--container-status-paused, #92400e); }
.container-status.restarting { background: var(--container-critical-bg, #ffedd5); color: var(--container-status-restarting, #c2410c); }
.container-status.unknown { background: var(--bg-tertiary, #e2e8f0); color: var(--text-muted); }
.container-uptime { font-size: 12px; color: var(--text-muted); margin-left: auto; }
.container-charts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.container-chart-box { background: var(--bg-primary); border: 1px solid var(--border-color); border-radius: 8px; padding: 10px; }
.container-card.running .container-chart-box { background: var(--bg-primary); border-color: var(--container-normal-border, #bbf7d0); }
.container-card.exited .container-chart-box { background: var(--bg-primary); border-color: var(--container-danger-border, #fecaca); }
.container-card.paused .container-chart-box { background: var(--bg-primary); border-color: var(--container-warning-border, #fde68a); }
.container-card.restarting .container-chart-box { background: var(--bg-primary); border-color: var(--container-critical-border, #fed7aa); }
.container-chart-box .chart-header { margin-bottom: 6px; }
.container-chart-box .chart-title { font-size: 12px; font-weight: 600; color: var(--text-primary); }
.container-chart-box .chart-avg { font-size: 11px; padding: 2px 8px; }
.container-chart { height: 180px; position: relative; }

@media (max-width: 1200px) { .container-charts { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 900px) { .chart-row { grid-template-columns: 1fr; } .container-charts { grid-template-columns: 1fr; } }
</style>
