document.addEventListener('DOMContentLoaded', init);

const CONNECTION_TEST_INTERVAL = 2 * 60 * 1000;

// A centered muted note div — the loading / empty state shared by the platform
// and sources lists.
function mutedNote(text) {
  const d = document.createElement('div');
  d.style.cssText = 'text-align:center;padding:18px;color:var(--on-surface-variant);';
  d.textContent = text;
  return d;
}

async function init() {
  try {
    const cfg = await browser.runtime.sendMessage({ type: 'GET_CONFIG' });
    if (!cfg || !cfg.apiUrl || !cfg.apiKey) {
      showSetupRequired();
      return;
    }
    document.getElementById('setup-required').classList.add('hidden');
    document.getElementById('main-content').classList.remove('hidden');
    setupEventListeners();
    showPlatformsLoading();
    testConnectionIfNeeded();
    checkForUpdate();
    loadPlatformStatus().catch(e => showError(`Failed to load platforms: ${e.message}`));
  } catch (e) {
    showSetupRequired();
    const alert = document.querySelector('#setup-required .alert');
    alert.textContent = '';
    const s = document.createElement('strong'); s.textContent = 'Error';
    const p = document.createElement('p'); p.textContent = e.message;
    alert.appendChild(s); alert.appendChild(p);
    alert.classList.add('alert-error');
  }
}

function showSetupRequired() {
  document.getElementById('setup-required').classList.remove('hidden');
  document.getElementById('main-content').classList.add('hidden');
  document.getElementById('open-settings-btn').addEventListener('click', () => {
    browser.runtime.openOptionsPage();
  });
}

function showPlatformsLoading() {
  const c = document.getElementById('platforms-list');
  c.textContent = '';
  c.appendChild(mutedNote('Loading platforms…'));
}

async function testConnectionIfNeeded() {
  const stored = await browser.storage.local.get(['lastConnectionTest', 'lastConnectionStatus']);
  const now = Date.now();
  if (now - (stored.lastConnectionTest || 0) < CONNECTION_TEST_INTERVAL && stored.lastConnectionStatus !== undefined) {
    updateConnectionDot(stored.lastConnectionStatus);
    if (!stored.lastConnectionStatus) showError('Cannot connect to backend (cached).');
    return;
  }
  const r = await browser.runtime.sendMessage({ type: 'TEST_CONNECTION' });
  await browser.storage.local.set({ lastConnectionTest: now, lastConnectionStatus: r.connected });
  updateConnectionDot(r.connected);
  if (!r.connected) showError(`Cannot connect to backend: ${r.error}`);
}

function updateConnectionDot(connected) {
  const d = document.getElementById('connection-status');
  d.classList.toggle('connected', connected);
  d.title = connected ? 'Connected to FabledCurator' : 'Disconnected';
}

// Nudge to reinstall when the configured instance publishes a newer signed XPI
// (the extension is self-hosted, so there's no Firefox auto-update). Never
// blocks the popup — a failed check just leaves the banner hidden.
async function checkForUpdate() {
  try {
    const r = await browser.runtime.sendMessage({ type: 'CHECK_UPDATE' });
    if (r && r.updateAvailable && r.xpiUrl) showUpdateBanner(r);
  } catch { /* non-fatal */ }
}

function showUpdateBanner(r) {
  // The channel names itself beside the version, never inside it (#3113).
  // Absent when the instance doesn't report one, and the banner then reads
  // exactly as it did before the field existed.
  const channel = r.channel ? ` (${r.channel})` : '';
  document.getElementById('update-text').textContent =
    `Update available${channel} — v${r.latestVersion} (installed v${r.currentVersion})`;
  // Opening the signed XPI triggers Firefox's native install prompt.
  document.getElementById('update-btn').addEventListener('click', () => {
    browser.tabs.create({ url: r.xpiUrl });
  });
  document.getElementById('update-banner').classList.remove('hidden');
}

async function loadPlatformStatus() {
  const status = await browser.runtime.sendMessage({ type: 'GET_PLATFORM_STATUS' });
  const c = document.getElementById('platforms-list');
  c.textContent = '';
  for (const [key, platform] of Object.entries(PLATFORMS)) {
    c.appendChild(createPlatformCard(key, platform, status[key] || {}));
  }
}

function createPlatformCard(key, platform, status) {
  const card = document.createElement('div');
  card.className = 'platform-card';
  card.dataset.platform = key;

  const isTokenOnly = platform.authType === 'token' && !['discord', 'pixiv'].includes(key);
  const discordNeedsToken = key === 'discord' && !status.hasToken;
  if (isTokenOnly || discordNeedsToken) card.classList.add('disabled');

  const icon = document.createElement('div');
  icon.className = 'platform-icon';
  icon.style.background = platform.color;
  icon.textContent = platform.name[0];

  const info = document.createElement('div');
  info.className = 'info';
  const name = document.createElement('div');
  name.className = 'name';
  name.textContent = platform.name;
  const st = document.createElement('div');
  st.className = `status ${statusClass(status, platform, key)}`;
  st.textContent = statusText(status, platform, key);
  info.appendChild(name); info.appendChild(st);

  const act = document.createElement('span');
  act.className = 'action-icon';
  act.textContent = '↥';

  card.appendChild(icon); card.appendChild(info); card.appendChild(act);

  if (!isTokenOnly && !discordNeedsToken) {
    card.addEventListener('click', () => exportPlatformCookies(key, card));
  }
  return card;
}

function statusText(s, platform, key) {
  if (key === 'discord') return s.hasToken ? 'Token captured — ready' : 'Open Discord to capture token';
  if (key === 'pixiv') return s.hasToken ? 'Token captured — ready' : 'Click to authenticate via OAuth';
  if (platform.authType === 'token') return 'Manual token entry required';
  if (s.error) return 'Error checking cookies';
  if (!s.hasCookies || !s.cookieCount) return 'No cookies — log in first';
  return `${s.cookieCount} cookies ready`;
}
function statusClass(s, platform, key) {
  if (key === 'discord') return s.hasToken ? 'ready' : 'no-cookies';
  if (key === 'pixiv') return s.hasToken ? 'ready' : 'no-cookies';
  if (platform.authType === 'token') return 'no-cookies';
  if (s.error) return 'error';
  if (!s.hasCookies || !s.cookieCount) return 'no-cookies';
  return 'ready';
}

async function exportPlatformCookies(key, card) {
  card.classList.add('loading'); hideStatusMessage();
  try {
    const r = await browser.runtime.sendMessage({ type: 'EXPORT_COOKIES', platform: key });
    if (r.error) showError(r.error);
    else {
      const n = r.cookieCount ?? null;
      const verifiedSuffix = r.verified ? ' (verified ✓)' : '';
      const msg = n !== null
        ? `${PLATFORMS[key].name}: ${n} cookies exported${verifiedSuffix}`
        : `${PLATFORMS[key].name}: token exported`;
      showSuccess(msg);
      await loadPlatformStatus();
    }
  } catch (e) { showError(e.message); }
  finally { card.classList.remove('loading'); }
}

async function exportAllCookies() {
  const btn = document.getElementById('export-all-btn');
  btn.disabled = true; btn.textContent = 'Exporting…'; hideStatusMessage();
  try {
    const r = await browser.runtime.sendMessage({ type: 'EXPORT_ALL_COOKIES' });
    const wins = Object.values(r).filter(x => x.success).length;
    const fails = Object.values(r).filter(x => !x.success && !x.skipped).length;
    if (wins && !fails) showSuccess(`Exported ${wins} platforms`);
    else if (wins) showWarning(`${wins} succeeded, ${fails} failed`);
    else if (fails) showError('All exports failed. Are you logged in?');
    else showWarning('Nothing to export');
    await loadPlatformStatus();
  } catch (e) { showError(e.message); }
  finally { btn.disabled = false; btn.textContent = 'Export all platforms'; }
}

async function loadSources() {
  const c = document.getElementById('sources-list');
  c.textContent = '';
  c.appendChild(mutedNote('Loading sources…'));
  const r = await browser.runtime.sendMessage({ type: 'LIST_SOURCES' });
  c.textContent = '';
  if (r.error) {
    const e = document.createElement('div');
    e.style.cssText = 'padding:12px;color:var(--error);';
    e.textContent = r.error;
    c.appendChild(e);
    return;
  }
  if (!r.sources || r.sources.length === 0) {
    c.appendChild(mutedNote('No sources yet.'));
    return;
  }
  for (const src of r.sources) c.appendChild(createSourceRow(src));
}

function createSourceRow(src) {
  const row = document.createElement('div');
  row.className = 'source-row';
  const info = document.createElement('div');
  info.className = 'info';
  const name = document.createElement('div');
  name.className = 'name';
  name.textContent = `${src.platform} · #${src.id}`;
  const url = document.createElement('div');
  url.className = 'url';
  url.textContent = src.url;
  info.appendChild(name); info.appendChild(url);
  const play = document.createElement('button');
  play.className = 'play';
  play.textContent = '▶';
  play.title = 'Check now';
  play.addEventListener('click', async () => {
    play.disabled = true;
    const r = await browser.runtime.sendMessage({ type: 'CHECK_SOURCE', sourceId: src.id });
    play.disabled = false;
    if (r.error) showError(r.error);
    else showSuccess(`Triggered check for source #${src.id}`);
  });
  row.appendChild(info); row.appendChild(play);
  return row;
}

function setupEventListeners() {
  document.getElementById('export-all-btn').addEventListener('click', exportAllCookies);
  document.getElementById('settings-btn').addEventListener('click', () => browser.runtime.openOptionsPage());
  for (const tab of document.querySelectorAll('.tab')) {
    tab.addEventListener('click', () => {
      for (const t of document.querySelectorAll('.tab')) t.classList.remove('active');
      tab.classList.add('active');
      for (const p of document.querySelectorAll('.tab-panel')) p.classList.add('hidden');
      document.getElementById(`tab-${tab.dataset.tab}`).classList.remove('hidden');
      if (tab.dataset.tab === 'sources') loadSources();
    });
  }
}

function showSuccess(m) { showStatusMessage(m, 'success'); }
function showError(m) { showStatusMessage(m, 'error'); }
function showWarning(m) { showStatusMessage(m, 'warning'); }
function showStatusMessage(text, kind) {
  const el = document.getElementById('status-message');
  el.textContent = text;
  el.className = `status-message ${kind}`;
  el.classList.remove('hidden');
}
function hideStatusMessage() {
  document.getElementById('status-message').classList.add('hidden');
}
