// Analytics — sources, interests, activity trend, and pipeline funnel.
// Wired to /analytics/sources, /analytics/interests, /analytics/activity,
// /analytics/funnel (cohort, period-windowed), and /pipeline-counts (lifetime
// snapshot used only for the hot/cold KPI tiles).

function BarRow({ label, value, max, accent, total }) {
  const pct = max > 0 ? (value / max) * 100 : 0;
  return (
    <div style={{display:'grid', gridTemplateColumns:'180px 1fr 90px', gap:16, alignItems:'center', padding:'9px 0'}}>
      <span style={{fontSize:13}}>{label}</span>
      <div style={{height:8, background:'var(--bone-2)', borderRadius:4, overflow:'hidden'}}>
        <div style={{height:'100%', width:pct+'%', background: accent || 'var(--ink)'}} />
      </div>
      <span style={{fontFamily:'var(--mono)', fontSize:12, textAlign:'right', color:'var(--muted)'}}>
        {value}{total ? <span style={{color:'var(--muted-2)'}}> · {((value/total)*100).toFixed(0)}%</span> : ''}
      </span>
    </div>
  );
}

function MiniArea({ buckets, width=800, height=220, accent='var(--ink)' }) {
  if (!buckets || buckets.length < 2) {
    return <div style={{height, display:'grid', placeItems:'center', color:'var(--muted-2)'}}>no data yet</div>;
  }
  const max = Math.max(1, ...buckets.map(b => b.count || 0));
  const step = width / (buckets.length - 1);
  const pts = buckets.map((b, i) => [i*step, height - ((b.count || 0) / max) * (height - 24) - 12]);
  const path = pts.map((p,i) => (i===0?'M':'L') + p[0].toFixed(1) + ' ' + p[1].toFixed(1)).join(' ');
  const areaPath = path + ` L ${width} ${height-6} L 0 ${height-6} Z`;
  return (
    <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`} style={{display:'block', width:'100%', height:'100%'}}>
      <path d={areaPath} fill={accent} opacity="0.08" />
      <path d={path} fill="none" stroke={accent} strokeWidth="1.6" />
      {pts.map((p, i) => (
        <g key={i}>
          <circle cx={p[0]} cy={p[1]} r="2.4" fill={accent} />
        </g>
      ))}
      {/* x-axis labels */}
      {buckets.map((b, i) => (
        <text key={i} x={i * step} y={height-2} fontSize="9"
          textAnchor={i === 0 ? 'start' : i === buckets.length - 1 ? 'end' : 'middle'}
          fontFamily="var(--mono)" fill="var(--muted-2)">
          {b.label}
        </text>
      ))}
    </svg>
  );
}

function AnalyticsView() {
  const [days, setDays] = React.useState(30);
  const [period, setPeriod] = React.useState('wtd');

  const sources   = useAsync(() => api.get('/api/v2/analytics/sources?days=' + days), [days]);
  const interests = useAsync(() => api.get('/api/v2/analytics/interests?days=' + days), [days]);
  const activity  = useAsync(() => api.get('/api/v2/analytics/activity?period=' + period), [period]);
  const funnelData = useAsync(() => api.get('/api/v2/analytics/funnel?days=' + days), [days]);
  const pipeline  = useAsync(() => api.get('/api/v2/pipeline-counts'), []);
  const tommy     = useAsync(() => api.get('/api/v2/tommy/stats'), []);

  const srcList = sources.data?.sources || [];
  const intList = interests.data?.interests || (interests.data?.items || []);
  const srcMax = Math.max(1, ...srcList.map(s => s.value));
  const intMax = Math.max(1, ...intList.map(s => s.value));
  const srcTot = srcList.reduce((s, x) => s + (x.value || 0), 0);

  const buckets = activity.data?.buckets || activity.data?.data || [];

  // Funnel: cohort of contacts created in the last `days` days. Each step
  // counts cohort members at-or-beyond that step (monotonically non-increasing).
  // "vs prev" compares the same cohort definition against the immediately
  // preceding window of equal length.
  const cur  = funnelData.data?.current  || { new_contacts: 0, booked: 0, showed: 0, joined: 0 };
  const prev = funnelData.data?.previous || { new_contacts: 0, booked: 0, showed: 0, joined: 0 };
  const membersTotal = funnelData.data?.members_total ?? 0;
  const funnel = [
    { key: 'new_contacts', label: 'New contacts',    value: cur.new_contacts, prev: prev.new_contacts },
    { key: 'booked',       label: 'Booked day pass', value: cur.booked,       prev: prev.booked },
    { key: 'showed',       label: 'Showed',          value: cur.showed,       prev: prev.showed },
    { key: 'joined',       label: 'Joined',          value: cur.joined,       prev: prev.joined },
  ];
  const funnelMax = Math.max(1, ...funnel.map(f => f.value));
  const cohortTotal = cur.new_contacts;

  return (
    <div className="app-main">
      <div className="page-hd">
        <div>
          <div className="kicker" style={{marginBottom:8}}>— Last {days} days</div>
          <h1>Analytics</h1>
          <div className="sub">Where contacts come from, what they ask for, who converts.</div>
        </div>
        <div className="actions">
          {/* Segmented control: do NOT use .btn.primary for the active state
              — that class is reserved for primary CTAs (e.g. "+ New lead")
              and the mobile rule forces full-width on it. Inline-style the
              active look like home.jsx:340-348 does. */}
          {[7, 30, 90].map(d => (
            <button key={d}
              className="btn"
              style={{
                background: d === days ? 'var(--ink)' : 'transparent',
                color: d === days ? 'var(--bone)' : 'var(--ink)',
              }}
              onClick={() => setDays(d)}>{d}d</button>
          ))}
        </div>
      </div>

      <div style={{display:'grid', gridTemplateColumns:'1.4fr 1fr', gap:16, marginBottom:16}}>
        <div className="card">
          <div className="hd">
            <div className="title">— <b>Activity</b> · contact volume</div>
            <div className="aside" style={{display:'flex', gap:6}}>
              {['today','yesterday','wtd','mtd'].map(p => (
                <button key={p}
                  className={p === period ? 'btn sm primary' : 'btn sm ghost'}
                  onClick={() => setPeriod(p)}
                >{p === 'wtd' ? 'WTD' : p === 'mtd' ? 'MTD' : p}</button>
              ))}
            </div>
          </div>
          <div className="bd" style={{height:260}}>
            <MiniArea buckets={buckets} width={800} height={240} accent="var(--ink)" />
          </div>
        </div>

        <div className="card">
          <div className="hd">
            <div className="title">— <b>Funnel</b> · cohort, last {days}d</div>
            <div className="aside" style={{fontFamily:'var(--mono)', fontSize:11, color:'var(--muted)'}}>
              {cohortTotal} new · {membersTotal} members lifetime
            </div>
          </div>
          <div className="bd">
            {funnelData.error && (
              <div className="empty" style={{marginBottom:8}}>Funnel unavailable.</div>
            )}
            {funnel.map((step, i) => {
              const pct = (step.value / funnelMax) * 100;
              // Conversion from previous step in current period (monotonic by construction).
              const conv = i > 0 && funnel[i-1].value > 0 ? (step.value / funnel[i-1].value) : null;
              // Real period-over-period delta vs the immediately preceding window.
              let deltaPct = null;
              if (step.prev > 0) deltaPct = ((step.value - step.prev) / step.prev) * 100;
              else if (step.value > 0) deltaPct = null; // no baseline — show "new"
              const deltaColor = deltaPct == null ? 'var(--muted-2)'
                : deltaPct >= 0 ? 'var(--signal)' : 'var(--muted)';
              return (
                <div key={step.label} style={{marginBottom:14}}>
                  <div style={{display:'flex', justifyContent:'space-between', marginBottom:6, alignItems:'baseline', gap:8}}>
                    <span style={{fontSize:13}}>{step.label}</span>
                    <span style={{fontFamily:'var(--mono)', fontSize:11, color:'var(--muted)', whiteSpace:'nowrap'}}>
                      <span style={{color:'var(--ink)', fontSize:14, fontWeight:500, marginRight:8}}>{step.value}</span>
                      {conv != null && <span style={{marginRight:8}}>{(conv*100).toFixed(0)}% of prev step</span>}
                      {deltaPct != null && (
                        <span style={{color:deltaColor}}>
                          {deltaPct >= 0 ? '+' : ''}{deltaPct.toFixed(0)}% vs prev {days}d
                        </span>
                      )}
                      {deltaPct == null && step.value > 0 && step.prev === 0 && (
                        <span style={{color:'var(--muted-2)'}}>new</span>
                      )}
                    </span>
                  </div>
                  <div style={{height:16, background:'var(--bone-2)', borderRadius:3, overflow:'hidden'}}>
                    <div style={{
                      height:'100%', width: pct+'%',
                      background: i === funnel.length-1 ? 'var(--signal)' : 'var(--ink)',
                      transition:'width 0.4s',
                    }} />
                  </div>
                </div>
              );
            })}
            <div style={{fontSize:10, color:'var(--muted-2)', marginTop:8, lineHeight:1.4}}>
              Cohort = contacts created in the last {days}d. Each step counts members
              who reached at-or-beyond that step. Showed is heuristic (no event log
              for SHOWED transitions yet). Members lifetime is shown separately and
              not mixed into Joined.
            </div>
          </div>
        </div>
      </div>

      <div style={{display:'grid', gridTemplateColumns:'1fr 1fr', gap:16, marginBottom:16}}>
        <div className="card">
          <div className="hd">
            <div className="title">— <b>Sources</b></div>
            <div className="aside" style={{fontFamily:'var(--mono)', fontSize:11, color:'var(--muted)'}}>
              {srcTot} new · {days}d
            </div>
          </div>
          <div className="bd">
            {srcList.length === 0 && !sources.loading && <div className="empty">No source data in range.</div>}
            {srcList.map((s, i) => (
              <BarRow key={s.label} label={s.label || 'Unknown'} value={s.value} max={srcMax} total={srcTot}
                accent={i===0 ? 'var(--signal)' : 'var(--ink)'} />
            ))}
          </div>
        </div>

        <div className="card">
          <div className="hd"><div className="title">— <b>Interests</b></div></div>
          <div className="bd">
            {intList.length === 0 && !interests.loading && <div className="empty">No tag data in range.</div>}
            {intList.map((s, i) => (
              <BarRow key={s.label} label={s.label || 'Unknown'} value={s.value} max={intMax}
                accent={i===0 ? 'var(--signal)' : 'var(--ink)'} />
            ))}
          </div>
        </div>
      </div>

      <div className="kpi-grid" style={{marginBottom:0}}>
        <div className="kpi">
          <div className="kpi-label">Tommy · sent today</div>
          <div className="kpi-value">{tommy.data?.messages_sent_today ?? '—'}</div>
          <div className="kpi-foot"><span style={{fontSize:12, color:'var(--muted)'}}>lifetime {tommy.data?.messages_sent_total ?? 0}</span></div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Active convos · 7d</div>
          <div className="kpi-value">{tommy.data?.convos_active ?? '—'}</div>
          <div className="kpi-foot"><span style={{fontSize:12, color:'var(--muted)'}}>distinct contacts</span></div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Hot leads · now</div>
          <div className="kpi-value">{pipeline.data?.hot_leads ?? '—'}</div>
          <div className="kpi-foot"><span style={{fontSize:12, color:'var(--muted)'}}>engaged + fresh</span></div>
        </div>
        <div className="kpi">
          <div className="kpi-label">Cold leads · 30d+</div>
          <div className="kpi-value">{pipeline.data?.cold_leads ?? '—'}</div>
          <div className="kpi-foot"><span style={{fontSize:12, color:'var(--muted)'}}>never contacted</span></div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { AnalyticsView });
