// ===== API client: fetch wrappers for /api/* =====
// 所有 API call 都帶 credentials: 'include' (讓 sid cookie 送出去).
// 401 統一透過 window.dispatchEvent(new Event('auth:expired')) 讓 App 跳回登入頁.

async function _fetch(method, path, body) {
  const opt = { method, credentials: 'include', headers: {} };
  if (body != null) {
    opt.headers['Content-Type'] = 'application/json';
    opt.body = JSON.stringify(body);
  }
  const resp = await fetch(path, opt);
  const j = await resp.json().catch(() => ({}));
  if (resp.status === 401 && !path.startsWith('/api/auth/')) {
    // Session 過期 → 通知 App
    window.dispatchEvent(new CustomEvent('auth:expired'));
  }
  return { ok: resp.ok, status: resp.status, data: j };
}

const API = {
  // ---- Auth ----
  authMe:       ()             => _fetch('GET',  '/api/auth/me'),
  requestCode:  (email)        => _fetch('POST', '/api/auth/request-code', { email }),
  verifyCode:   (email, code)  => _fetch('POST', '/api/auth/verify-code',  { email, code }),
  logout:       ()             => _fetch('POST', '/api/auth/logout'),

  // ---- Months ----
  listMonths:   ()             => _fetch('GET',  '/api/months'),
  getMonth:     (m)            => _fetch('GET',  `/api/months/${m}`),
  importMonth:  (m, rows)      => _fetch('POST', `/api/months/${m}/import`, { rows }),
  deleteMonth:  (m)            => _fetch('DELETE', `/api/months/${m}`),

  // ---- State (一次拉齊所有小型狀態) ----
  getState:     ()             => _fetch('GET',  '/api/state'),

  // ---- 個別寫入 ----
  putStatus:       (month, dim, name, status)   => _fetch('PUT',    '/api/state/status',        { month, dim, name, status }),
  putRules:        (rules)                       => _fetch('PUT',    '/api/state/rules',         rules),
  putGroupRate:    (name, rate)                  => _fetch('PUT',    '/api/state/group-rate',    { name, rate }),
  putGuild:        (creatorId, on)               => _fetch('PUT',    '/api/state/guild',         { creatorId, on }),
  putMonthSetting: (month, patch)                => _fetch('PUT',    '/api/state/month-setting', { month, ...patch }),
  putInvoice:      (groupName, type)             => _fetch('PUT',    '/api/state/invoice',       { groupName, type }),
  addExtra:        (month, dim, name, label, amount) => _fetch('POST', '/api/state/extras', { month, dim, name, label, amount }),
  delExtra:        (id)                          => _fetch('DELETE', `/api/state/extras/${id}`),

  // ---- Sync ----
  syncFromLocal:   (snapshot)  => _fetch('POST', '/api/sync', snapshot),
};

// Debounce helper: 用來避免 rapid keystroke 每次都打 API.
// 對同一個 key, 300ms 內只送最後一次.
const _debouncers = new Map();
function debouncedCall(key, ms, fn) {
  if (_debouncers.has(key)) clearTimeout(_debouncers.get(key));
  const t = setTimeout(() => { _debouncers.delete(key); fn(); }, ms);
  _debouncers.set(key, t);
}

// ---- Legacy localStorage migration helpers ----
// 舊版本 (localStorage-only) 存在這些 key. 使用者升到 D1 版本第一次登入時,
// 我們掃描一下, 有東西就跳一個橫幅讓他一鍵推到雲端.
const LEGACY_KEYS = {
  imported:     'recon.importedMonths.v1',
  status:       'recon.status.v1',
  rules:        'recon.shareRules.v1',
  incrRate:     'recon.incrRate.v1',
  fx:           'recon.fx.v1',
  extras:       'recon.extraBonus.v1',
  invoiceTypes: 'recon.invoiceType.v1',
};

function collectLegacyData() {
  const snap = {};
  const summary = { months: 0, monthsRows: 0, statuses: 0, groupRates: 0, guildIds: 0, monthSettings: 0, invoiceTypes: 0, extras: 0, total: 0 };
  for (const [outKey, lsKey] of Object.entries(LEGACY_KEYS)) {
    const raw = localStorage.getItem(lsKey);
    if (!raw) continue;
    try {
      const v = JSON.parse(raw);
      if (!v || (typeof v === 'object' && Object.keys(v).length === 0)) continue;
      snap[outKey] = v;
    } catch (e) { /* skip broken */ }
  }
  // 統計
  if (snap.imported) {
    summary.months = Object.keys(snap.imported).length;
    for (const m in snap.imported) summary.monthsRows += (snap.imported[m] || []).length;
  }
  if (snap.status) summary.statuses = Object.keys(snap.status).length;
  if (snap.rules) {
    summary.groupRates = Object.keys(snap.rules.groupRates || {}).length;
    summary.guildIds = Object.keys(snap.rules.guildIds || {}).length;
  }
  if (snap.incrRate) summary.monthSettings += Object.keys(snap.incrRate).length;
  if (snap.fx) summary.monthSettings += Object.keys(snap.fx).length;
  if (snap.invoiceTypes) summary.invoiceTypes = Object.keys(snap.invoiceTypes).length;
  if (snap.extras) for (const k in snap.extras) summary.extras += (snap.extras[k] || []).length;
  summary.total = summary.months + summary.statuses + summary.groupRates + summary.guildIds + summary.monthSettings + summary.invoiceTypes + summary.extras;
  return { snap, summary };
}

function clearLegacyData() {
  for (const k of Object.values(LEGACY_KEYS)) localStorage.removeItem(k);
}

Object.assign(window, { API, debouncedCall, collectLegacyData, clearLegacyData });
