<template>
  <div class="page">
    <header class="bar">
      <router-link to="/" class="back">← 返回</router-link>
      <h1>设置</h1>
    </header>

    <main class="body">
      <section class="block">
        <h2>离线缓存</h2>
        <p class="desc">
          把所有曲目的 audio 和谱面 PNG 异步下载到浏览器 IndexedDB。下载完没网也能播放、看谱。
          默认 <b>关</b>。整库约 1.5 GB，移动网络下慎开。
        </p>

        <label class="row">
          <span class="lbl">启用自动缓存</span>
          <input type="checkbox" v-model="enabled" @change="onEnabled" />
        </label>

        <label class="row" :class="{ disabled: !enabled }">
          <span class="lbl">仅 WiFi 时下载</span>
          <input type="checkbox" v-model="wifiOnly" :disabled="!enabled" @change="onWifi" />
        </label>

        <div class="stats">
          <div class="stat">
            <span class="key">已缓存 audio</span>
            <span class="val">{{ stats.audioCount }} 个</span>
          </div>
          <div class="stat">
            <span class="key">已缓存谱面</span>
            <span class="val">{{ stats.imageCount }} 个</span>
          </div>
          <div class="stat">
            <span class="key">磁盘占用</span>
            <span class="val">{{ fmtMb(usage.usage) }} / {{ fmtMb(usage.quota) }}</span>
          </div>
        </div>

        <div v-if="stats.busy" class="progress">
          <div class="bar-bg">
            <div class="bar-fill" :style="{ width: pct + '%' }"></div>
          </div>
          <div class="progress-text">下载中 {{ stats.done }} / {{ stats.total }} ({{ pct }}%)</div>
        </div>

        <div class="actions">
          <button class="btn" :disabled="stats.busy || !enabled" @click="onStart">
            {{ stats.busy ? '运行中…' : '立即开始下载' }}
          </button>
          <button class="btn" :disabled="!stats.busy" @click="onStop">暂停</button>
          <button class="btn danger" :disabled="stats.busy" @click="onClear">清空所有缓存</button>
        </div>
      </section>

      <section class="block">
        <h2>关于</h2>
        <p class="desc">
          PWA 可"加到主屏幕"作为独立 app 启动。<br/>
          数据用 IndexedDB，可在浏览器开发者工具的 Application → IndexedDB → music-cache 看到详细条目。<br/>
          清空缓存只删本地数据，不影响服务端。
        </p>
      </section>
    </main>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
import {
  isCacheEnabled, setCacheEnabled,
  isWifiOnly, setWifiOnly,
  startCacheWorker, abortCacheWorker, clearCache,
  estimateUsage, cacheStats,
} from '../lib/cache.js'

const enabled = ref(isCacheEnabled())
const wifiOnly = ref(isWifiOnly())
const stats = cacheStats
const usage = ref({ usage: 0, quota: 0 })

const pct = ref(0)

function onEnabled() {
  setCacheEnabled(enabled.value)
  if (enabled.value) startCacheWorker()
  else abortCacheWorker()
}
function onWifi() {
  setWifiOnly(wifiOnly.value)
}
function onStart() {
  if (!enabled.value) {
    enabled.value = true
    setCacheEnabled(true)
  }
  startCacheWorker()
}
function onStop() {
  abortCacheWorker()
}
async function onClear() {
  if (!confirm('确认清空所有离线缓存？')) return
  await clearCache()
  await refreshUsage()
}

async function refreshUsage() {
  usage.value = await estimateUsage()
  pct.value = stats.value.total > 0
    ? Math.round((stats.value.done / stats.value.total) * 100)
    : 0
}

function onProgress() {
  pct.value = stats.value.total > 0
    ? Math.round((stats.value.done / stats.value.total) * 100)
    : 0
  refreshUsage()
}

onMounted(() => {
  refreshUsage()
  window.addEventListener('music-cache-progress', onProgress)
})
onBeforeUnmount(() => {
  window.removeEventListener('music-cache-progress', onProgress)
})

function fmtMb(b) {
  if (!b) return '?'
  if (b < 1024 * 1024) return (b / 1024).toFixed(0) + ' KB'
  if (b < 1024 * 1024 * 1024) return (b / 1024 / 1024).toFixed(1) + ' MB'
  return (b / 1024 / 1024 / 1024).toFixed(2) + ' GB'
}
</script>

<style scoped>
.page { min-height: 100%; display: flex; flex-direction: column; background: var(--bg); }
.bar {
  display: flex; align-items: center; gap: 18px;
  padding: 14px 22px;
  background: var(--bg-card);
  border-bottom: 1px solid var(--border-soft);
}
.bar h1 { font-size: 18px; font-weight: 600; }
.back { color: var(--text-dim); font-size: 14px; }
.back:hover { color: var(--accent); text-decoration: none; }

.body { max-width: 720px; margin: 0 auto; padding: 24px 22px 80px; width: 100%; }
.block {
  background: var(--bg-card);
  border-radius: 10px;
  padding: 20px;
  margin-bottom: 18px;
}
.block h2 {
  font-size: 14px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
  margin-bottom: 12px;
}
.desc { color: var(--text-dim); font-size: 13px; line-height: 1.7; margin-bottom: 14px; }
.desc b { color: var(--accent); }

.row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 0;
  border-bottom: 1px solid var(--border-soft);
}
.row:last-of-type { border-bottom: none; }
.row.disabled { opacity: 0.5; }
.row .lbl { font-size: 14px; }
.row input[type=checkbox] { width: 18px; height: 18px; cursor: pointer; }

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 10px;
  margin: 14px 0;
}
.stat {
  background: var(--bg-elev);
  border-radius: 6px;
  padding: 10px 14px;
  font-size: 12px;
}
.stat .key { color: var(--text-mute); display: block; margin-bottom: 4px; }
.stat .val { color: var(--text); font-weight: 600; }

.progress { margin: 14px 0; }
.bar-bg {
  height: 6px; background: var(--bg-elev); border-radius: 3px; overflow: hidden;
}
.bar-fill {
  height: 100%; background: var(--accent-strong); transition: width 0.3s;
}
.progress-text { font-size: 11px; color: var(--text-mute); margin-top: 6px; }

.actions { display: flex; gap: 10px; margin-top: 14px; flex-wrap: wrap; }
.btn {
  font-size: 13px; padding: 8px 16px; border-radius: 6px;
  background: var(--accent-strong); color: #fff; font-weight: 600;
}
.btn:hover:not(:disabled) { background: var(--accent); }
.btn:disabled { opacity: 0.4; cursor: not-allowed; }
.btn.danger { background: rgba(239,68,68,0.15); color: var(--accent-red); }
.btn.danger:hover:not(:disabled) { background: rgba(239,68,68,0.3); }
</style>
