// RangerHQ Tuner — Options page controller.
// Manages the user's local data: history cap, clear actions, stats display.
// Broadcasts STORAGE_WIPED after destructive actions so the popup/newtab
// rerender immediately.

import { TARGETS, TYPES } from '../lib/messages.js';
import {
  getHistory, getFavourites,
  getHistoryCap, setHistoryCap,
  clearHistory, clearFavourites, clearAll,
} from '../lib/history.js';
import {
  THEME_KEY, THEME_DEFAULT, VALID_THEMES,
  getTheme, setTheme, applyTheme,
} from '../lib/theme.js';

const STORAGE_KEYS = {
  stations:    'tuner.stationsCache',
  currentId:   'tuner.currentStationId',
  volume:      'tuner.volume',
};

const els = {
  version:        document.getElementById('opt-version'),
  statHistory:    document.getElementById('opt-stat-history'),
  statFavs:       document.getElementById('opt-stat-favs'),
  statCache:      document.getElementById('opt-stat-cache'),
  statBytes:      document.getElementById('opt-stat-bytes'),
  capSlider:      document.getElementById('opt-cap'),
  capValue:       document.getElementById('opt-cap-value'),
  clearHistory:   document.getElementById('opt-clear-history'),
  clearFavs:      document.getElementById('opt-clear-favs'),
  clearAll:       document.getElementById('opt-clear-all'),
  volumeDisplay:  document.getElementById('opt-volume-display'),
  lastStation:    document.getElementById('opt-last-station'),
  toast:          document.getElementById('opt-toast'),
};

init().catch(err => {
  console.error('Options init failed:', err);
  toast(`Init failed: ${err.message}`, 'error');
});

async function init() {
  els.version.textContent = `v${chrome.runtime.getManifest().version}`;

  // Theme — apply stored preference + wire the radio group + listen for
  // cross-surface changes (popup/newtab pick a theme → Options reflects).
  await initThemeUI();

  await refreshStats();
  await refreshPlayback();

  const cap = await getHistoryCap();
  els.capSlider.value = String(cap);
  els.capValue.textContent = String(cap);

  els.capSlider.addEventListener('input', () => {
    els.capValue.textContent = els.capSlider.value;
  });
  els.capSlider.addEventListener('change', async () => {
    const newCap = await setHistoryCap(Number(els.capSlider.value));
    els.capValue.textContent = String(newCap);
    toast(`History cap set to ${newCap}`);
    await refreshStats();
  });

  els.clearHistory.addEventListener('click', async () => {
    if (!confirm('Clear all track history? Favourites will be preserved.')) return;
    await clearHistory();
    await refreshStats();
    notifyUis();
    toast('History cleared');
  });

  els.clearFavs.addEventListener('click', async () => {
    if (!confirm('Clear all favourites?')) return;
    await clearFavourites();
    await refreshStats();
    notifyUis();
    toast('Favourites cleared');
  });

  els.clearAll.addEventListener('click', async () => {
    if (!confirm('Wipe EVERYTHING — history, favourites, station cache, volume, last station? This cannot be undone.')) return;
    await clearAll();
    await refreshStats();
    await refreshPlayback();
    els.capSlider.value = '500';
    els.capValue.textContent = '500';
    notifyUis();
    toast('All local data wiped', 'danger');
  });

  // Refresh stats live if storage changes from another surface
  chrome.storage.onChanged.addListener((changes, area) => {
    if (area !== 'local') return;
    if (changes[THEME_KEY]) {
      const v = changes[THEME_KEY].newValue || THEME_DEFAULT;
      applyTheme(v);
      const radio = document.querySelector(`input[name="opt-theme"][value="${v}"]`);
      if (radio) radio.checked = true;
    }
    if (Object.keys(changes).some(k => k.startsWith('tuner.'))) {
      refreshStats();
      refreshPlayback();
    }
  });
}

/** Apply the stored theme, check the matching radio, wire change handlers. */
async function initThemeUI() {
  const current = await getTheme();
  applyTheme(current);
  const checked = document.querySelector(`input[name="opt-theme"][value="${current}"]`);
  if (checked) checked.checked = true;
  for (const r of document.querySelectorAll('input[name="opt-theme"]')) {
    r.addEventListener('change', async (e) => {
      const v = e.target.value;
      if (!VALID_THEMES.includes(v)) return;
      await setTheme(v);
      applyTheme(v);
      toast(`Theme: ${v}`);
    });
  }
}

async function refreshStats() {
  const [history, favs, all] = await Promise.all([
    getHistory(),
    getFavourites(),
    chrome.storage.local.get(null),
  ]);
  const cacheArr = Array.isArray(all[STORAGE_KEYS.stations]) ? all[STORAGE_KEYS.stations] : [];

  // Estimate "tuner.*" bytes — JSON stringification is close enough for
  // a user-facing display, no need for the exact storage-engine cost.
  let bytes = 0;
  for (const [k, v] of Object.entries(all)) {
    if (!k.startsWith('tuner.')) continue;
    try { bytes += k.length + JSON.stringify(v).length; } catch { /* nope */ }
  }

  els.statHistory.textContent = `${history.length} tracks`;
  els.statFavs.textContent    = `${favs.length} tracks`;
  els.statCache.textContent   = `${cacheArr.length} stations`;
  els.statBytes.textContent   = formatBytes(bytes);
}

async function refreshPlayback() {
  const stored = await chrome.storage.local.get([
    STORAGE_KEYS.volume,
    STORAGE_KEYS.currentId,
    STORAGE_KEYS.stations,
  ]);
  const vol = stored[STORAGE_KEYS.volume];
  els.volumeDisplay.textContent = typeof vol === 'number'
    ? `${Math.round(vol * 100)}%`
    : '—';

  const id = stored[STORAGE_KEYS.currentId];
  const cache = Array.isArray(stored[STORAGE_KEYS.stations]) ? stored[STORAGE_KEYS.stations] : [];
  const cur = cache.find(s => s.id === id);
  els.lastStation.textContent = cur?.name || (id || '—');
}

function notifyUis() {
  chrome.runtime.sendMessage({ target: TARGETS.POPUP, type: TYPES.STORAGE_WIPED })
    .catch(() => {}); // no listeners is fine
}

function formatBytes(n) {
  if (n < 1024)        return `${n} B`;
  if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
  return `${(n / (1024 * 1024)).toFixed(2)} MB`;
}

function toast(message, tone) {
  els.toast.textContent = message;
  els.toast.dataset.tone = tone || '';
  els.toast.hidden = false;
  clearTimeout(toast._t);
  toast._t = setTimeout(() => { els.toast.hidden = true; }, 2400);
}
