const { useState: useStateF, useMemo: useMemoF, useEffect: useEffectF } = React;

// -0.0 is a rounding artifact from the RPC's round(), not a real negative value.
// A genuinely negative "dropoff" means the step had MORE sessions than the one
// before it (steps aren't strictly sequential per session) — label that as
// growth rather than a confusing negative dropoff percentage.
function fmtDropoff(n) {
  const v = Math.abs(n) < 0.05 ? 0 : n;
  return v < 0 ? { label: `+${Math.abs(v).toFixed(1)}% more sessions`, kind: 'growth' } : { label: `-${v.toFixed(1)}% dropoff`, kind: 'drop' };
}

// Horizontal drop-off bars — same visual language as the order funnel in page-analytics.jsx.
const FunnelBars = ({ data }) => {
  const max = data[0]?.v || 1;
  return (
    <div style={{display:"flex", flexDirection:"column", gap:10}}>
      {data.map((d, i) => {
        const w = (d.v / max) * 100;
        const drop = d.dropoffPct != null ? fmtDropoff(d.dropoffPct) : null;
        return (
          <div key={d.step}>
            <div style={{display:"flex", justifyContent:"space-between", alignItems:"baseline", marginBottom:4}}>
              <span style={{fontSize:12.5, color:"var(--ink-2)", fontWeight:500}}>{d.step}</span>
              <span className="num" style={{fontSize:12, color:"var(--ink)"}}>
                {d.v.toLocaleString()} <span className="muted" style={{fontSize:10.5}}>sessions</span>
              </span>
            </div>
            <div style={{height:24, background:"var(--surface-2)", borderRadius:3, overflow:"hidden", position:"relative"}}>
              <div style={{
                width: w + "%", height:"100%",
                background:"var(--accent)", opacity: 0.85 - i*0.08,
                display:"flex", alignItems:"center", paddingLeft:8
              }}>
                {i > 0 && drop && (
                  <span style={{fontFamily:"var(--font-mono)", fontSize:10, color:"var(--paper)"}}>
                    {drop.label}
                  </span>
                )}
              </div>
            </div>
          </div>
        );
      })}
    </div>
  );
};

const RANGE_DAYS = { "7D": 7, "30D": 30, "90D": 90 };

// ── Drop-off sub-view ────────────────────────────────────────────────────────
const DropoffView = ({ sb, sinceIso, range }) => {
  const [funnels, setFunnels] = useStateF([]);
  const [selectedFunnel, setSelectedFunnel] = useStateF(null);
  const [steps, setSteps] = useStateF([]);
  const [loading, setLoading] = useStateF(true);
  const [loadingList, setLoadingList] = useStateF(true);

  const loadFunnelList = async () => {
    if (!sb) return;
    setLoadingList(true);
    const { data, error } = await sb.rpc("list_funnels", { p_since: sinceIso });
    if (!error && data) {
      setFunnels(data);
      setSelectedFunnel(prev => prev && data.some(f => f.funnel === prev) ? prev : (data[0]?.funnel ?? null));
    }
    setLoadingList(false);
  };

  const loadDropoff = async () => {
    if (!sb || !selectedFunnel) { setSteps([]); return; }
    setLoading(true);
    const { data, error } = await sb.rpc("get_funnel_dropoff", {
      p_funnel: selectedFunnel,
      p_start: sinceIso,
      p_end: new Date().toISOString(),
    });
    setSteps(!error && data ? data : []);
    setLoading(false);
  };

  useEffectF(() => { loadFunnelList(); }, [sinceIso]);
  useEffectF(() => { loadDropoff(); }, [selectedFunnel, sinceIso]);

  const barData = useMemoF(() => steps.map(s => ({
    step: s.step,
    v: s.sessions,
    dropoffPct: s.dropoff_from_prev_pct,
  })), [steps]);

  // Below this many entry sessions, percentages swing wildly on a single user's
  // behavior (e.g. "66.7% dropoff" from one of three users not returning) —
  // show the raw counts but withhold the headline percentages as misleading.
  const MIN_SAMPLE = 5;
  const entrySessions = steps[0]?.sessions ?? 0;
  const finalSessions = steps[steps.length - 1]?.sessions ?? 0;
  const lowSample = entrySessions > 0 && entrySessions < MIN_SAMPLE;
  const overallCompletion = entrySessions >= MIN_SAMPLE ? (finalSessions / entrySessions * 100) : null;
  const biggestDrop = useMemoF(() => {
    const withDrop = steps.filter(s => s.dropoff_from_prev_pct != null && s.sessions >= MIN_SAMPLE);
    if (withDrop.length === 0) return null;
    return withDrop.reduce((a, b) => (b.dropoff_from_prev_pct > a.dropoff_from_prev_pct ? b : a));
  }, [steps]);
  // -0.0 is a rounding artifact from the RPC, not a real negative value.
  const fmtPct = (n) => (Math.abs(n) < 0.05 ? 0 : n).toFixed(1);

  return (
    <>
      <div className="row gap-2" style={{marginBottom:16, flexWrap:"wrap"}}>
        {loadingList ? (
          <div className="muted" style={{fontSize:12, padding:"6px 0"}}>Loading funnels…</div>
        ) : funnels.length === 0 ? (
          <div className="muted" style={{fontSize:12, padding:"6px 0"}}>No funnel events in this range</div>
        ) : funnels.map(f => (
          <span key={f.funnel} onClick={() => setSelectedFunnel(f.funnel)} className="chip" style={{
            cursor: "pointer",
            background: selectedFunnel === f.funnel ? "var(--accent-soft)" : undefined,
            color: selectedFunnel === f.funnel ? "var(--accent-ink)" : undefined,
            borderColor: selectedFunnel === f.funnel ? "transparent" : undefined,
          }}>{f.funnel} <span className="muted" style={{fontSize:10}}>({f.event_count.toLocaleString()})</span></span>
        ))}
      </div>

      {selectedFunnel && <div className="kpi-grid">
        <div className="kpi">
          <div className="lbl">Entry sessions</div>
          <div className="val">{loading ? '—' : entrySessions.toLocaleString()}</div>
          <div className="sub"><span className="muted">{steps[0]?.step ?? ''}</span></div>
        </div>
        <div className="kpi">
          <div className="lbl">Completion rate</div>
          <div className="val">{loading || overallCompletion === null ? '—' : fmtPct(overallCompletion)}<span className="unit">{!loading && overallCompletion !== null ? '%' : ''}</span></div>
          <div className="sub"><span className="muted">{overallCompletion === null ? (lowSample ? 'too few sessions yet' : '') : steps[steps.length - 1]?.step ?? ''}</span></div>
        </div>
        <div className="kpi">
          <div className="lbl">Biggest drop-off</div>
          <div className="val">{loading || !biggestDrop ? '—' : fmtPct(biggestDrop.dropoff_from_prev_pct)}<span className="unit">{!loading && biggestDrop ? '%' : ''}</span></div>
          <div className="sub"><span className="muted">{biggestDrop ? `at ${biggestDrop.step}` : (lowSample ? 'too few sessions yet' : '')}</span></div>
        </div>
        <div className="kpi">
          <div className="lbl">Steps tracked</div>
          <div className="val">{loading ? '—' : steps.length}</div>
          <div className="sub"><span className="muted">{range}</span></div>
        </div>
      </div>}

      {selectedFunnel && (
        <div className="mob-stack" style={{display:"grid", gridTemplateColumns:"1.4fr 1fr", gap:14, marginTop:14}}>
          <div className="panel">
            <div className="panel-h">
              <span>Drop-off — {selectedFunnel}</span>
              <span className="meta">{range}</span>
            </div>
            <div style={{padding:16}}>
              {loading ? (
                <div className="muted" style={{fontSize:12}}>Loading…</div>
              ) : barData.length === 0 ? (
                <div className="muted" style={{textAlign:'center', fontSize:12, padding:24}}>No step data for this funnel</div>
              ) : <FunnelBars data={barData}/>}
            </div>
          </div>

          <div className="panel">
            <div className="panel-h">
              <span>Step detail</span>
              <span className="meta">sessions · users</span>
            </div>
            {loading ? (
              <div className="muted" style={{padding:16, fontSize:12}}>Loading…</div>
            ) : steps.length === 0 ? (
              <div className="muted" style={{padding:24, textAlign:'center', fontSize:12}}>No data</div>
            ) : (
              <div className="t-wrap"><table className="t">
                <thead><tr>
                  <th>Step</th>
                  <th style={{textAlign:"right"}}>Sessions</th>
                  <th style={{textAlign:"right"}}>Users</th>
                  <th style={{textAlign:"right"}}>% of entry</th>
                  <th style={{textAlign:"right"}}>Dropoff</th>
                </tr></thead>
                <tbody>
                  {steps.map(s => (
                    <tr key={s.step}>
                      <td style={{color:"var(--ink)", fontWeight:500}}>{s.step}</td>
                      <td className="num" style={{textAlign:"right"}}>{s.sessions.toLocaleString()}</td>
                      <td className="num" style={{textAlign:"right"}}>{s.users.toLocaleString()}</td>
                      <td className="num" style={{textAlign:"right"}}>{s.pct_of_entry != null ? `${s.pct_of_entry}%` : '—'}</td>
                      <td style={{textAlign:"right"}}>
                        {s.dropoff_from_prev_pct == null ? (
                          <span className="muted">—</span>
                        ) : (() => {
                          const d = fmtDropoff(s.dropoff_from_prev_pct);
                          const cls = d.kind === 'growth' ? 'info' : s.dropoff_from_prev_pct >= 50 ? 'neg' : s.dropoff_from_prev_pct >= 20 ? 'warn' : 'pos';
                          return <span className={`chip dot ${cls}`}>{d.label}</span>;
                        })()}
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table></div>
            )}
          </div>
        </div>
      )}
    </>
  );
};

// ── Where people close the app ──────────────────────────────────────────────
const AppCloseView = ({ sb, sinceIso }) => {
  const [rows, setRows] = useStateF([]);
  const [loading, setLoading] = useStateF(true);

  const load = async () => {
    if (!sb) return;
    setLoading(true);
    const { data, error } = await sb.rpc("get_app_close_points", { p_since: sinceIso, p_limit: 25 });
    setRows(!error && data ? data : []);
    setLoading(false);
  };
  useEffectF(() => { load(); }, [sinceIso]);

  const max = rows[0]?.session_count || 1;

  return (
    <div className="panel">
      <div className="panel-h">
        <span>Last screen before the app closed</span>
        <span className="meta">by session count</span>
      </div>
      {loading ? (
        <div className="muted" style={{padding:16, fontSize:12}}>Loading…</div>
      ) : rows.length === 0 ? (
        <div className="muted" style={{padding:24, textAlign:'center', fontSize:12}}>
          No closed sessions with navigation data yet in this range
        </div>
      ) : (
        <div style={{padding:16, display:"flex", flexDirection:"column", gap:10}}>
          {rows.map(r => (
            <div key={r.last_screen}>
              <div style={{display:"flex", justifyContent:"space-between", alignItems:"baseline", marginBottom:4}}>
                <span style={{fontSize:12.5, color:"var(--ink-2)", fontWeight:500}}>{r.last_screen}</span>
                <span className="num" style={{fontSize:12, color:"var(--ink)"}}>
                  {r.session_count.toLocaleString()} <span className="muted" style={{fontSize:10.5}}>sessions · avg {r.avg_duration_seconds != null ? `${Math.round(r.avg_duration_seconds)}s` : '—'}</span>
                </span>
              </div>
              <div style={{height:18, background:"var(--surface-2)", borderRadius:3, overflow:"hidden"}}>
                <div style={{width:(r.session_count/max*100)+"%", height:"100%", background:"var(--accent)", opacity:0.75}}/>
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
};

// ── Component click -> conversion ───────────────────────────────────────────
const EngagementView = ({ sb, sinceIso }) => {
  const [rows, setRows] = useStateF([]);
  const [loading, setLoading] = useStateF(true);

  const load = async () => {
    if (!sb) return;
    setLoading(true);
    const { data, error } = await sb.rpc("get_component_conversion", { p_since: sinceIso });
    setRows(!error && data ? data : []);
    setLoading(false);
  };
  useEffectF(() => { load(); }, [sinceIso]);

  return (
    <div className="panel">
      <div className="panel-h">
        <span>Home feed component → add-to-cart</span>
        <span className="meta">e.g. "Our Faves" card opens → cart adds tagged home_section:*</span>
      </div>
      {loading ? (
        <div className="muted" style={{padding:16, fontSize:12}}>Loading…</div>
      ) : rows.length === 0 ? (
        <div className="muted" style={{padding:24, textAlign:'center', fontSize:12}}>No component opens tracked in this range</div>
      ) : (
        <div className="t-wrap"><table className="t">
          <thead><tr>
            <th>Component</th>
            <th style={{textAlign:"right"}}>Opens</th>
            <th style={{textAlign:"right"}}>Add to carts</th>
            <th style={{textAlign:"right"}}>Conversion</th>
          </tr></thead>
          <tbody>
            {rows.map(r => (
              <tr key={r.component}>
                <td style={{color:"var(--ink)", fontWeight:500}}>{r.component}</td>
                <td className="num" style={{textAlign:"right"}}>{r.opens.toLocaleString()}</td>
                <td className="num" style={{textAlign:"right"}}>{r.add_to_carts.toLocaleString()}</td>
                <td style={{textAlign:"right"}}>
                  {r.conversion_pct == null
                    ? <span className="muted">—</span>
                    : <span className={`chip dot ${r.conversion_pct >= 15 ? 'pos' : r.conversion_pct >= 5 ? 'warn' : 'neg'}`}>{r.conversion_pct}%</span>}
                </td>
              </tr>
            ))}
          </tbody>
        </table></div>
      )}
      <div className="muted" style={{padding:"0 16px 16px", fontSize:11}}>
        Other tracked micro-interactions (e.g. subcategory row usage) don't yet have a direct downstream
        conversion tag and show up under Drop-off → "home_feed_engagement" instead.
      </div>
    </div>
  );
};

const FunnelsPage = () => {
  const I = window.Icons;
  const sb = window.supabaseClient;

  const [range, setRange] = useStateF("30D");
  const [view, setView] = useStateF("dropoff");
  const [refreshKey, setRefreshKey] = useStateF(0);

  const sinceIso = useMemoF(() => new Date(Date.now() - RANGE_DAYS[range] * 86400000).toISOString(), [range, refreshKey]);

  return (
    <div className="page" data-screen-label="Funnels">
      <div className="page-h">
        <div>
          <div className="ts"><span className="live">live</span> · All times NPT</div>
          <h1>Funnels</h1>
        </div>
        <div className="acts">
          <div className="row gap-2">
            {Object.keys(RANGE_DAYS).map(r =>
              <span key={r} onClick={() => setRange(r)} className="chip" style={{
                cursor: "pointer",
                background: r === range ? "var(--accent-soft)" : undefined,
                color: r === range ? "var(--accent-ink)" : undefined,
                borderColor: r === range ? "transparent" : undefined,
              }}>{r}</span>
            )}
          </div>
          <button className="btn" onClick={() => setRefreshKey(k => k + 1)}><I.refresh size={12}/>Refresh</button>
        </div>
      </div>

      <div className="ftabs" style={{marginBottom:16}}>
        {[
          ["dropoff", "Drop-off"],
          ["appclose", "Where they close the app"],
          ["engagement", "Component engagement"],
        ].map(([id, name]) => (
          <div key={id} className={"ftab" + (view === id ? " active" : "")} onClick={() => setView(id)}>{name}</div>
        ))}
      </div>

      {view === "dropoff" && <DropoffView sb={sb} sinceIso={sinceIso} range={range}/>}
      {view === "appclose" && <AppCloseView sb={sb} sinceIso={sinceIso}/>}
      {view === "engagement" && <EngagementView sb={sb} sinceIso={sinceIso}/>}
    </div>
  );
};

window.FunnelsPage = FunnelsPage;
