'use strict';
/** v48 parity pack: v47 + mesh bridge toggle (mirror APK RelayPrefs.mesh_bridge) */

function $(id) { return document.getElementById(id); }

function loadV48State() {
  state.roomPin = store.get('p2p_room_pin', '');
  state.stayBehind = store.get('p2p_stay_behind', '0') === '1';
  state.meshBridge = store.get('p2p_mesh_bridge', '0') === '1';
  state.meshHopLog = store.getJSON('p2p_mesh_hops', []);
  state.taskBoard = store.getJSON('p2p_tasks', []);
  state.connStats = store.getJSON('p2p_conn_stats', { ok: 0, fail: 0 });
}

function bindRoomPinUI() {
  const inp = $('relayRoomPin');
  if (!inp) return;
  inp.value = state.roomPin || '';
  inp.oninput = (e) => {
    state.roomPin = e.target.value.trim();
    store.set('p2p_room_pin', state.roomPin);
  };
}

function bindMeshBridgeUI() {
  const sw = $('meshBridgeSwitch');
  if (!sw) return;
  sw.checked = !!state.meshBridge;
  sw.onchange = (e) => {
    state.meshBridge = e.target.checked;
    store.set('p2p_mesh_bridge', state.meshBridge ? '1' : '0');
    const hint = $('meshBridgeHint');
    if (hint) {
      hint.textContent = state.meshBridge
        ? '近距 P2P 連上時仍保持中繼在 Mesh 內。'
        : '近距 P2P 連上時會暫停中繼（與 APK 預設相同）。';
    }
    if (state.meshBridge && typeof connectRelay === 'function' && !ws) connectRelay(true);
  };
  sw.dispatchEvent(new Event('change'));
}

function relayUrlWithRoom(base, room) {
  const pin = (state.roomPin || '').trim();
  let url = base + (base.includes('?') ? '&' : '?') + 'room=' + encodeURIComponent(room || state.relayRoom || 'team1');
  if (pin) url += '&pin=' + encodeURIComponent(pin);
  return url;
}

function recordConnStat(ok) {
  state.connStats = state.connStats || { ok: 0, fail: 0 };
  if (ok) state.connStats.ok++; else state.connStats.fail++;
  store.setJSON('p2p_conn_stats', state.connStats);
}

function showOnboardingV48() {
  if (store.get('p2p_onboard', '0') === '1') return;
  const el = $('onboardModal');
  if (!el) return;
  el.classList.remove('hidden');
}

function closeOnboardingV48() {
  store.set('p2p_onboard', '1');
  $('onboardModal')?.classList.add('hidden');
}

function telemetryExtras() {
  const out = {};
  if (typeof state._batteryPct === 'number') out.battery = state._batteryPct;
  return out;
}

function refreshBatteryTelemetry() {
  if (!navigator.getBattery) return;
  navigator.getBattery().then((bat) => {
    state._batteryPct = Math.round(bat.level * 100);
    bat.onlevelchange = () => { state._batteryPct = Math.round(bat.level * 100); };
  }).catch(() => {});
}

function noteMeshHop(msg, fromConnId) {
  if (!msg || !msg.id || fromConnId === state.id) return;
  const entry = { id: msg.id, type: msg.type, ttl: msg.ttl, ts: Date.now() };
  state.meshHopLog = (state.meshHopLog || []).slice(-30);
  state.meshHopLog.push(entry);
  store.setJSON('p2p_mesh_hops', state.meshHopLog);
  const el = $('meshHopStatus');
  if (el) el.textContent = `最近轉發：${msg.type} TTL=${msg.ttl}`;
}

function detectPortableRouterMode() {
  const h = location.hostname;
  if (/^\d+\.\d+\.\d+\.\d+$/.test(h) && location.protocol === 'https:') {
    if (typeof setConnMode === 'function') setConnMode('hotspot');
    const el = $('connModeHint');
    if (el) el.textContent = '偵測到區網 IP，已切換熱點+QR 模式。';
  }
}

async function runTurnNatHint() {
  const el = $('turnNatStatus');
  if (!el) return;
  el.textContent = '測試中…';
  try {
    const pc = new RTCPeerConnection({ iceServers: iceServers() });
    pc.createDataChannel('t');
    const offer = await pc.createOffer();
    await pc.setLocalDescription(offer);
    await new Promise((r) => setTimeout(r, 2500));
    const cands = (await new Promise((res) => {
      const found = [];
      pc.onicecandidate = (e) => { if (e.candidate) found.push(e.candidate.candidate); };
      setTimeout(() => res(found), 500);
    }));
    pc.close();
    const hasRelay = cands.some((c) => / typ relay /.test(c));
    const hasSrflx = cands.some((c) => / typ srflx /.test(c));
    if (hasRelay) el.textContent = '✓ 偵測到 TURN relay，跨網語音較穩';
    else if (hasSrflx) el.textContent = '⚠️ 僅 STUN，對稱 NAT 可能需自建 TURN';
    else el.textContent = '⚠️ 僅 host，請用中繼或熱點+QR';
  } catch (e) {
    el.textContent = '測試失敗：' + e.message;
  }
}

function bindStayBehindUI() {
  const sw = $('stayBehindSwitch');
  if (!sw) return;
  sw.checked = !!state.stayBehind;
  sw.onchange = (e) => {
    state.stayBehind = e.target.checked;
    store.set('p2p_stay_behind', state.stayBehind ? '1' : '0');
    const ptt = $('pttBtn');
    if (ptt && state.stayBehind) ptt.disabled = true;
  };
  if (sw.checked) { const ptt = $('pttBtn'); if (ptt) ptt.disabled = true; }
}

function renderTaskBoard() {
  const el = $('taskBoardList');
  if (!el) return;
  const tasks = state.taskBoard || [];
  if (!tasks.length) { el.innerHTML = '<div class="muted small">尚無任務</div>'; return; }
  el.innerHTML = tasks.map((t, i) =>
    `<label class="radio-row"><input type="checkbox" data-idx="${i}" ${t.done ? 'checked' : ''}/> ${escapeHtml(t.text)}</label>`
  ).join('');
  el.querySelectorAll('input').forEach((cb) => {
    cb.onchange = () => {
      const i = +cb.dataset.idx;
      state.taskBoard[i].done = cb.checked;
      store.setJSON('p2p_tasks', state.taskBoard);
    };
  });
}

function addTaskFromQuick(text) {
  state.taskBoard = state.taskBoard || [];
  state.taskBoard.push({ text, done: false, ts: Date.now() });
  store.setJSON('p2p_tasks', state.taskBoard);
  renderTaskBoard();
  if (typeof meshSend === 'function') meshSend({ type: 'TEXT', text: '📋 任務：' + text });
}

function checkAppVersionV48() {
  const el = $('versionCheckStatus');
  if (!el) return;
  fetch('./sw.js', { cache: 'no-store' }).then((r) => r.text()).then((t) => {
    const m = t.match(/pich2pich-v(\d+)/);
    const remote = m ? +m[1] : 0;
    const local = +(store.get('p2p_sw_ver', '0') || 0);
    if (local && remote > local) {
      el.textContent = `有新版本 v${remote}，請重新整理或清除 PWA 快取`;
      el.className = 'small warn';
    } else {
      el.textContent = `App 版本 v${remote || '?'}`;
      el.className = 'small muted';
    }
    if (remote) store.set('p2p_sw_ver', String(remote));
  }).catch(() => {});
}

function initStabilityV48() {
  loadV48State();
  bindRoomPinUI();
  bindMeshBridgeUI();
  bindStayBehindUI();
  renderTaskBoard();
  refreshBatteryTelemetry();
  detectPortableRouterMode();
  showOnboardingV48();
  checkAppVersionV48();
  const turnBtn = $('turnNatTestBtn');
  if (turnBtn) turnBtn.onclick = runTurnNatHint;
  const obClose = $('onboardDoneBtn');
  if (obClose) obClose.onclick = closeOnboardingV48;
  $('taskAddBtn')?.addEventListener('click', () => {
    const t = ($('taskInput')?.value || '').trim();
    if (!t) return;
    addTaskFromQuick(t);
    if ($('taskInput')) $('taskInput').value = '';
  });
}

window.telemetryExtras = telemetryExtras;
window.noteMeshHop = noteMeshHop;
window.recordConnStat = recordConnStat;
window.relayUrlWithRoom = relayUrlWithRoom;
window.initStabilityV48 = initStabilityV48;
window.initStabilityV47 = initStabilityV48;
window.addTaskFromQuick = addTaskFromQuick;
