/* Viamar Ops — Insights (PostHog-powered funnel & analytics).

   Issue #51: this view now reads the real booking funnel from the Worker
   (`GET /app/events/funnel?days=30`) instead of the static PH_FUNNEL.
   The PostHog "powered by" chrome is kept — the customer events that build
   the funnel are still PostHog-instrumented; the Worker is the privacy-safe
   aggregator so we don't ship a PostHog personal API key to the browser.

   Falls back to the hard-coded PH_FUNNEL (badged "demo data") if the API
   is unreachable, so the page never breaks. */

function InsightsScreen() {
  const RANGE_DAYS = 30;
  const REFRESH_MS = 60_000;

  const [data, setData] = React.useState(null);   // last good payload
  const [loading, setLoading] = React.useState(true);
  const [errorMsg, setErrorMsg] = React.useState(null);

  const track = React.useCallback(function (event, props) {
    try {
      if (window.ViamarAnalytics && typeof ViamarAnalytics.track === 'function') {
        ViamarAnalytics.track(event, props || {});
      }
    } catch (e) { /* analytics must never break the UI */ }
  }, []);

  const fetchInsights = React.useCallback(function (opts) {
    opts = opts || {};
    if (!window.ViamarOpsData || !ViamarOpsData.getInsights) return;
    if (opts.showLoading !== false) setLoading(true);
    ViamarOpsData.getInsights(RANGE_DAYS).then(function (resp) {
      setLoading(false);
      // resp is always defined — getInsights returns the fallback on failure.
      setData(resp);
      if (resp && resp.demo) {
        setErrorMsg(resp.reason || 'demo');
        track('ops_insights_error', { message: resp.reason || 'demo' });
      } else {
        setErrorMsg(null);
        track('ops_insights_viewed', {
          range_days: resp.range_days || RANGE_DAYS,
          total_events: resp.total_events || 0,
        });
      }
    }).catch(function (err) {
      setLoading(false);
      var message = (err && err.message) || 'unknown_error';
      setErrorMsg(message);
      track('ops_insights_error', { message: message });
      if (!data) {
        // No prior good response — drop the static fallback in so the page renders.
        setData(ViamarOpsData.insightsFallback ? ViamarOpsData.insightsFallback(message) : null);
      }
    });
  }, [track, data]);

  React.useEffect(function () {
    fetchInsights({ showLoading: true });
    var onFocus = function () { fetchInsights({ showLoading: false }); };
    window.addEventListener('focus', onFocus);
    var timer = setInterval(function () {
      if (!document.hidden) fetchInsights({ showLoading: false });
    }, REFRESH_MS);
    return function () {
      window.removeEventListener('focus', onFocus);
      clearInterval(timer);
    };
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // While we have no data yet, render the placeholder skeleton.
  if (!data) {
    return (
      <div className="vscroll" style={{ height: '100%', overflowY: 'auto' }}>
        <div style={{ padding: '28px 36px 44px', display: 'flex', flexDirection: 'column', gap: 24 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <div style={{ flex: 1 }}>
              <Display size={22} color={T.ink}>Insights</Display>
              <div style={{ fontFamily: FM, fontSize: 11.5, color: T.muted, marginTop: 4 }}>Booking funnel & product analytics</div>
            </div>
          </div>
          <Card>
            <div style={{ fontFamily: FM, fontSize: 12, color: T.muted, padding: '6px 2px' }}>
              {loading ? 'Loading funnel from the Viamar Worker…' : 'No insights available yet.'}
            </div>
          </Card>
        </div>
      </div>
    );
  }

  // Normalise the funnel rows into the shape the existing UI expects: { step, n }.
  const funnelRows = (data.funnel || []).map(function (row) {
    return { step: row.step, n: Math.max(0, Number(row.count) || 0) };
  });
  // Defensive fallback if every step has zero — show at least the labels so the page isn't blank bars.
  const safeFunnel = funnelRows.length ? funnelRows : (window.PH_FUNNEL || []);
  const first = safeFunnel[0] ? safeFunnel[0].n : 0;
  const last = safeFunnel.length ? safeFunnel[safeFunnel.length - 1].n : 0;
  const conv = first > 0 ? ((last / first) * 100).toFixed(1) : '0.0';

  // Biggest drop-off between consecutive steps (only count steps where prev > 0).
  let dropIdx = 1, dropPct = 0;
  for (let i = 1; i < safeFunnel.length; i++) {
    const prev = safeFunnel[i - 1].n;
    if (!prev) continue;
    const d = 1 - safeFunnel[i].n / prev;
    if (d > dropPct) { dropPct = d; dropIdx = i; }
  }
  if (dropIdx >= safeFunnel.length) dropIdx = Math.max(1, safeFunnel.length - 1);

  const isDemo = !!data.demo;
  const metrics = [
    { label: 'Quote→book conversion', value: conv + '%', sub: 'last ' + (data.range_days || RANGE_DAYS) + ' days', tone: T.green },
    { label: 'Quotes started', value: first.toLocaleString(), sub: isDemo ? 'demo data' : 'live', tone: T.navy3 },
    { label: 'Booked & prepaid', value: last.toLocaleString(), sub: isDemo ? 'demo data' : 'live', tone: T.red },
    { label: 'Biggest drop-off', value: (safeFunnel[dropIdx] && safeFunnel[dropIdx].step) || '—', sub: Math.round(dropPct * 100) + '% lost here', tone: T.amber, small: true },
  ];

  // Trend chart and live event stream are kept on the static prototype data for now
  // (no per-week aggregate endpoint yet). They will be replaced under follow-up issues.
  const trendData = (window.PH_TREND || []);
  const eventsData = (window.PH_EVENTS || []);
  const maxT = trendData.length ? Math.max.apply(null, trendData) : 1;

  return (
    <div className="vscroll" style={{ height: '100%', overflowY: 'auto' }}>
      <div style={{ padding: '28px 36px 44px', display: 'flex', flexDirection: 'column', gap: 24 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <div style={{ flex: 1 }}>
            <Display size={22} color={T.ink}>Insights</Display>
            <div style={{ fontFamily: FM, fontSize: 11.5, color: T.muted, marginTop: 4 }}>
              Booking funnel & product analytics{loading ? ' · refreshing…' : ''}
            </div>
          </div>
          {isDemo ? (
            <div title={errorMsg || 'demo'} style={{ display: 'inline-flex', alignItems: 'center', gap: 7, background: '#FFF7E6', border: '1px solid #F0C36D', borderRadius: 999, padding: '7px 13px' }}>
              <span style={{ width: 8, height: 8, borderRadius: '50%', background: T.amber }} />
              <span style={{ fontFamily: FM, fontSize: 11, fontWeight: 700, color: T.body, letterSpacing: 0.3 }}>Demo data · API not connected</span>
            </div>
          ) : null}
          <div style={{ display: 'inline-flex', alignItems: 'center', gap: 7, background: '#fff', border: '1px solid ' + T.line2, borderRadius: 999, padding: '7px 13px' }}>
            <span style={{ width: 8, height: 8, borderRadius: '50%', background: '#F54E00' }} />
            <span style={{ fontFamily: FM, fontSize: 11, fontWeight: 700, color: T.body, letterSpacing: 0.3 }}>Powered by PostHog</span>
          </div>
        </div>

        {/* metric cards */}
        <div style={{ display: 'flex', gap: 14 }}>
          {metrics.map((m, i) => (
            <div key={i} style={{ flex: 1, background: '#fff', borderRadius: 16, border: '1px solid ' + T.line2, padding: '16px 18px' }}>
              <div style={{ fontFamily: FD, fontWeight: 800, fontSize: m.small ? 18 : 28, color: T.ink, fontStretch: '115%', lineHeight: 1.05 }}>{m.value}</div>
              <div style={{ fontFamily: FB, fontWeight: 600, fontSize: 12.5, color: T.body, marginTop: 7 }}>{m.label}</div>
              <div style={{ fontFamily: FM, fontSize: 10.5, color: m.tone, marginTop: 3 }}>{m.sub}</div>
            </div>
          ))}
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1.4fr 1fr', gap: 24, alignItems: 'start' }}>
          {/* funnel */}
          <div>
            <SectionHead title="Quote → booking funnel" action={'Last ' + (data.range_days || RANGE_DAYS) + ' days'} />
            <Card>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
                {safeFunnel.map((f, i) => {
                  const pctOfFirst = first > 0 ? f.n / first : 0;
                  const prevN = i === 0 ? f.n : safeFunnel[i - 1].n;
                  const stepConv = i === 0 ? 100 : (prevN > 0 ? Math.round((f.n / prevN) * 100) : 0);
                  const isDrop = i === dropIdx && dropPct > 0;
                  return (
                    <div key={i}>
                      <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 6 }}>
                        <span style={{ fontFamily: FB, fontWeight: 600, fontSize: 13, color: T.ink }}>{i + 1}. {f.step}</span>
                        <span style={{ fontFamily: FM, fontSize: 11.5, color: T.muted }}>{f.n.toLocaleString()} · <span style={{ color: isDrop ? T.amber : T.green, fontWeight: 700 }}>{stepConv}%</span></span>
                      </div>
                      <div style={{ height: 22, borderRadius: 7, background: T.line2, overflow: 'hidden' }}>
                        <div style={{ width: (pctOfFirst * 100) + '%', height: '100%', background: isDrop ? T.amber : T.red, borderRadius: 7, transition: 'width .5s' }} />
                      </div>
                    </div>
                  );
                })}
              </div>
              <div style={{ fontFamily: FB, fontSize: 11.5, color: T.muted, lineHeight: 1.5, marginTop: 16, paddingTop: 14, borderTop: '1px solid ' + T.line2 }}>
                {safeFunnel[dropIdx] && dropPct > 0 ? (
                  <span>Biggest leak is at <span style={{ color: T.ink, fontWeight: 700 }}>{safeFunnel[dropIdx].step}</span> — {Math.round(dropPct * 100)}% drop. Worth an experiment: pre-fill consignee details and simplify the document upload.</span>
                ) : (
                  <span>No drop-off detected yet — waiting on more funnel events.</span>
                )}
              </div>
            </Card>
          </div>

          {/* trend + events */}
          <div style={{ display: 'flex', flexDirection: 'column', gap: 24 }}>
            <div>
              <SectionHead title="Bookings · 12 wks" />
              <Card>
                <div style={{ display: 'flex', alignItems: 'flex-end', gap: 6, height: 90 }}>
                  {trendData.map((v, i) => (
                    <div key={i} style={{ flex: 1, height: Math.max(6, (v / maxT) * 80), background: i === trendData.length - 1 ? T.red : T.navy3, borderRadius: 4, opacity: i === trendData.length - 1 ? 1 : 0.55 }} />
                  ))}
                </div>
              </Card>
            </div>
            <div>
              <SectionHead title="Live events" action="Stream" />
              <Card pad={0} style={{ overflow: 'hidden' }}>
                {eventsData.map((e, i) => (
                  <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '11px 15px', borderTop: i ? '1px solid ' + T.line2 : 'none' }}>
                    <span style={{ width: 7, height: 7, borderRadius: '50%', background: e.ev === 'quote_abandoned' ? T.amber : T.green, flexShrink: 0 }} />
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontFamily: FM, fontSize: 11.5, fontWeight: 700, color: T.ink }}>{e.ev}</div>
                      <div style={{ fontFamily: FM, fontSize: 10, color: T.muted, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{e.props}</div>
                    </div>
                    <span style={{ fontFamily: FM, fontSize: 9.5, color: T.faint, flexShrink: 0 }}>{e.time}</span>
                  </div>
                ))}
              </Card>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { InsightsScreen });
