/* community-live.jsx — bridge: Supabase reports → the map layer + the feed + routing.

   The app already has TWO community representations:
     • window.VR_COMMUNITY  — geo data the map draws AND the safety engine scores against
     • CommStore (flows.jsx) — the list shown in the Community tab
   This module is the single place that pulls live reports from VR_DB and pushes them into
   BOTH, then rebuilds the safety model so confirmed reports actually steer routing.

   No-backend fallback: if VR_DB.enabled is false, hydrate() is a no-op and the app keeps
   running on its seed data unchanged. */

(function () {
  const LIVE = 'live-'; // id prefix marking entries we injected, so re-hydration replaces cleanly

  // DB cat → feed icon (names resolved from window at render time in the feed)
  const CAT_ICON = {
    danger: 'IconWarn', traffic: 'IconCar', pothole: 'IconWarn',
    blocked: 'IconBike', lighting: 'IconWarn', safe: 'IconShield', rough: 'IconWarn',
  };
  const CAT_LEVEL = { danger: 'danger', traffic: 'danger', pothole: 'moderate', blocked: 'moderate', lighting: 'moderate', safe: 'safe', rough: 'moderate' };

  function ago(iso) {
    if (!iso) return '';
    const s = Math.max(1, (Date.now() - new Date(iso).getTime()) / 1000);
    if (s < 90) return 'току-що';
    if (s < 3600) return `преди ${Math.round(s / 60)} мин`;
    if (s < 86400) return `преди ${Math.round(s / 3600)} ч`;
    return `преди ${Math.round(s / 86400)} дни`;
  }
  // a single-pin segment report gets a short stub polyline so it draws + samples for safety
  function stub(lat, lng) { return [[lat, lng], [lat + 0.0006, lng + 0.0004]]; }

  // split DB rows into map points/segments, tagging each so the map & safety engine consume them
  function toMap(rows) {
    const points = [], segments = [];
    rows.forEach((r) => {
      const id = LIVE + r.id;
      const status = r.status === 'active' ? 'confirmed' : 'pending';
      const affectsSafety = r.status === 'active' && r.affects_routing && r.visibility === 'public';
      const base = {
        id, cat: r.cat, label: r.label, area: r.area || '', by: r.author_name, ago: ago(r.created_at),
        votes: r.confirm_count, desc: r.note || '', comments: [], live: true, status, affectsSafety,
        reportId: r.id, visibility: r.visibility,
      };
      if (r.type === 'point') {
        points.push({ ...base, at: [r.lat, r.lng] });
      } else {
        const coords = Array.isArray(r.coords) && r.coords.length > 1 ? r.coords : stub(r.lat, r.lng);
        segments.push({ ...base, coords });
      }
    });
    return { points, segments };
  }

  // a feed item for the Community tab list (public point/danger reports only)
  function toFeed(rows) {
    return rows
      .filter((r) => r.visibility === 'public' && r.type !== 'safe')
      .map((r) => ({
        id: LIVE + r.id, reportId: r.id, cat: r.kind || r.label, Icon: CAT_ICON[r.cat] || 'IconWarn',
        level: CAT_LEVEL[r.cat] || 'moderate', loc: r.area || r.label, ago: ago(r.created_at),
        author: r.author_name, votes: r.confirm_count, voted: false, onMap: r.status === 'active', live: true,
      }));
  }

  const listeners = new Set();
  window.vrOnCommunityChange = function (cb) { listeners.add(cb); return () => listeners.delete(cb); };
  const notify = () => listeners.forEach((f) => { try { f(); } catch (e) {} });

  // merge live rows into VR_COMMUNITY + CommStore, replacing any previously-injected live entries
  function apply(rows) {
    const C = window.VR_COMMUNITY;
    if (!C) return;
    const { points, segments } = toMap(rows);
    // include a live entry in the safety model only if it's confirmed + public + routing-on
    const safe = (e) => !e.live || e.affectsSafety;

    C.points = C.points.filter((p) => !(p.id || '').startsWith(LIVE)).concat(points);
    C.segments = C.segments.filter((s) => !(s.id || '').startsWith(LIVE)).concat(segments);
    // hand the safety builder a community view that omits unconfirmed/private live reports
    const prev = window.VR_COMMUNITY;
    window.VR_COMMUNITY = { ...C, points: C.points.filter(safe), segments: C.segments.filter(safe) };
    if (window.vrRebuildSafety) window.vrRebuildSafety();
    window.VR_COMMUNITY = prev; // restore the full set (incl. pending) for the map to draw

    // feed: keep seed items, drop old live ones, prepend fresh
    if (window.CommStore) {
      const feed = toFeed(rows);
      window.CommStore.set((l) => feed.concat(l.filter((x) => !(x.id || '').startsWith(LIVE))));
    }
    notify();
  }

  let started = false;
  window.vrHydrateCommunity = async function () {
    const DB = window.VR_DB;
    if (!DB || !DB.enabled) return false;
    try {
      const rows = await DB.fetchReports();
      apply(rows);
      if (!started) {
        started = true;
        DB.onReportsChange(() => { window.vrHydrateCommunity(); }); // realtime: other devices' reports appear
      }
      return true;
    } catch (e) { console.warn('[community-live] hydrate failed:', e); return false; }
  };
})();
