// ============ Overview view ============
const ViewOverview = ({ t, setRoute }) => {
  const [period, setPeriod] = React.useState("30d");
  const { loading, data, error } = useStats(period);

  const series = (data?.series || []).map(x => x.c);
  const labels = (data?.series || []).map(x => x.d.slice(5)); // MM-DD
  const total = data?.kpis.total || 0;
  const uniqueTerms = data?.kpis.unique_terms || 0;
  const avgDaily = data?.kpis.avg_daily || 0;
  const zeroTotal = data?.kpis.zero_total || 0;
  const zeroRatio = data?.kpis.zero_ratio || 0;

  const spark = series.slice(-12);
  const topTerms = data?.top_terms || [];
  const topZero = data?.top_zero_terms || [];

  return (
    <div className="view">
      {error && <ApiError t={t} message={error}/>}

      {/* KPIs */}
      <div className="kpi-grid">
        <Card className="kpi">
          <div className="label"><Icon name="search" size={12}/> {t("kpi_searches")} <InfoTip text={t("tip_searches")}/></div>
          <div className="value">{loading && !data ? "…" : <CountUp value={total}/>}</div>
          <div className="delta up"><Icon name="arrow-up" size={12}/> {period.toUpperCase()}</div>
          {spark.length > 1 && <div className="spark"><Sparkline data={spark} width={90} height={28}/></div>}
        </Card>
        <Card className="kpi">
          <div className="label"><Icon name="sparkle" size={12}/> {t("kpi_unique_terms")} <InfoTip text={t("tip_unique_terms")}/></div>
          <div className="value">{loading && !data ? "…" : <CountUp value={uniqueTerms}/>}</div>
          <div className="delta up"><Icon name="sparkle" size={12}/> {total ? ((uniqueTerms/total)*100).toFixed(1) : "0"}% {t("pct_of_total")}</div>
        </Card>
        <Card className="kpi">
          <div className="label"><Icon name="x" size={12}/> {t("kpi_zero")} <InfoTip text={t("tip_zero_kpi")}/></div>
          <div className="value">{loading && !data ? "…" : <CountUp value={zeroRatio * 100} format={(v) => v.toFixed(1)} suffix="%"/>}</div>
          <div className="delta down"><Icon name="arrow-down" size={12}/> {zeroTotal.toLocaleString()} {t("searches").toLowerCase()}</div>
          {data && <div className="spark"><Donut value={zeroRatio * 100} size={52} stroke={6} color="var(--danger)" label={`${(zeroRatio*100).toFixed(0)}%`}/></div>}
        </Card>
        <Card className="kpi">
          <div className="label"><Icon name="clock" size={12}/> {t("kpi_avg_daily")} <InfoTip text={t("tip_avg_daily")}/></div>
          <div className="value">{loading && !data ? "…" : <CountUp value={avgDaily}/>}</div>
          <div className="delta up"><Icon name="arrow-up" size={12}/> {data?.kpis.days_covered || 0} d</div>
          {spark.length > 1 && <div className="spark"><Sparkline data={spark} color="var(--accent-2)" width={90} height={28}/></div>}
        </Card>
      </div>

      {/* Load balancer health — latency + traffic */}
      <LbHealthKpi t={t} />

      {/* Volume + top terms */}
      <div className="grid-2" style={{ marginBottom: 16 }}>
        <Card title={<SectionTitle icon="analytics" tip={t("tip_volume")}>{t("trend_searches")}</SectionTitle>}
          right={<Segment options={TOKENS.period.map(p => ({ value: p.value, label: t(p.labelKey)}))} value={period} onChange={setPeriod}/>}>
          {loading && !data
            ? <LoadingBlock t={t}/>
            : series.length === 0
              ? <EmptyBlock t={t}/>
              : <LineChart data={series} labels={labels} />
          }
          {data && <div className="faint" style={{ fontSize: 11, padding: "6px 2px 0" }}>
            {t("data_range")} {data.anchor?.slice(0,10)}
          </div>}
        </Card>

        <Card title={<SectionTitle icon="trending" tip={t("tip_top_terms")}>{t("top_terms")}</SectionTitle>}
          right={<Button variant="ghost" size="sm" onClick={() => setRoute("analytics")}>{t("view_all")}<Icon name="chevron" size={12}/></Button>}>
          <div style={{ padding: "6px 4px 0" }}>
            {loading && !data && <LoadingBlock t={t}/>}
            {topTerms.slice(0, 8).map((row) => (
              <BarRow key={row.term} label={row.term} value={row.searches} max={topTerms[0]?.searches || 1}/>
            ))}
            {!loading && topTerms.length === 0 && <EmptyBlock t={t}/>}
          </div>
        </Card>
      </div>

      {/* Zero-result top */}
      <Card title={<SectionTitle icon="x" color="var(--danger)" tip={t("tip_zero_list")}>{t("zero_list")}</SectionTitle>}
        right={<Button variant="ghost" size="sm" onClick={() => setRoute("analytics")}>{t("view_all")}<Icon name="chevron" size={12}/></Button>}
        style={{ marginBottom: 16 }}>
        <div style={{ padding: "4px 0" }}>
          {loading && !data && <LoadingBlock t={t}/>}
          {topZero.slice(0, 7).map((r) => (
            <div key={r.term} style={{ display: "flex", alignItems: "center", gap: 10, padding: "10px 4px", borderBottom: "1px solid var(--line)" }}>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 13, fontWeight: 500, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{r.term}</div>
                <div style={{ fontSize: 11, color: "var(--text-faint)" }}>{r.days} {t("days")}</div>
              </div>
              <div className="num-mono" style={{ fontSize: 13, color: "var(--danger)", fontWeight: 600 }}>{r.count.toLocaleString()}</div>
            </div>
          ))}
          {!loading && topZero.length === 0 && <EmptyBlock t={t}/>}
        </div>
      </Card>

      {/* Latest run */}
      <Card title={<SectionTitle icon="workflow" tip={t("tip_latest_run")}>{t("latest_run")}</SectionTitle>}
        right={<Button variant="ghost" size="sm" onClick={() => setRoute("workflow")}>{t("view_all")}<Icon name="chevron" size={12}/></Button>}>
        <MiniDag t={t}/>
      </Card>
    </div>
  );
};

const LoadingBlock = ({ t }) => (
  <div style={{ display: "grid", placeItems: "center", padding: 40, color: "var(--text-faint)", fontSize: 13, gap: 8 }}>
    <div style={{ width: 24, height: 24, borderRadius: "50%", border: "2px solid var(--line-2)", borderTopColor: "var(--accent)", animation: "spin 900ms linear infinite" }}/>
    <div>{t("loading")}</div>
  </div>
);

const EmptyBlock = ({ t }) => (
  <div style={{ display: "grid", placeItems: "center", padding: 40, color: "var(--text-faint)", fontSize: 13 }}>
    {t("no_data")}
  </div>
);

const ApiError = ({ t, message }) => (
  <div style={{
    background: "rgba(248,113,113,.08)", border: "1px solid rgba(248,113,113,.35)",
    color: "var(--danger)", padding: "10px 14px", borderRadius: 10, fontSize: 13, marginBottom: 16,
    display: "flex", alignItems: "center", gap: 10
  }}>
    <Icon name="x" size={14}/> {t("api_error")}: <span className="mono" style={{ fontSize: 12 }}>{message}</span>
  </div>
);

// Mini DAG showing the real latest execution of lacomer-sync
const STAGE_TO_KEY_MINI  = { setup: "s_setup", ingest: "s_ingest", enhance: "s_enhance", vector: "s_vector", confirm: "s_confirm" };
const STAGE_TO_ICON_MINI = { setup: "check",   ingest: "database", enhance: "sparkle",   vector: "cube",     confirm: "rocket"   };

const MiniDag = ({ t }) => {
  const [latest, setLatest] = React.useState(null);
  const [error, setError] = React.useState(null);

  const load = React.useCallback(async () => {
    try {
      const data = await apiAuth("/api/workflow/runs?limit=1");
      setLatest(data.runs?.[0] || null);
      setError(null);
    } catch (e) { setError(e.message); }
  }, []);

  React.useEffect(() => { load(); }, [load]);

  // Poll while running
  React.useEffect(() => {
    if (latest?.status !== "running") return;
    const iv = setInterval(load, 5000);
    return () => clearInterval(iv);
  }, [latest?.status, load]);

  if (error) return <div style={{ padding: 20, fontSize: 12, color: "var(--danger)" }}>{error}</div>;
  if (!latest) return <LoadingBlock t={t}/>;

  return (
    <div style={{ padding: "20px 8px 8px" }}>
      <div className="dag-row" style={{ gap: 0 }}>
        {latest.stages.map((st, i) => (
          <React.Fragment key={st.key}>
            <div className={`dag-node ${st.state}`} style={{ width: 110, minHeight: 62, padding: "8px 10px" }}>
              <div className="node-icon" style={{ width: 22, height: 22 }}><Icon name={STAGE_TO_ICON_MINI[st.key] || "check"} size={12}/></div>
              <div className="node-title" style={{ fontSize: 11, marginTop: 6 }}>{t(STAGE_TO_KEY_MINI[st.key] || st.key)}</div>
              <div className="node-sub" style={{ fontSize: 9 }}>
                {st.state === "success" ? t("success") : st.state === "running" ? t("running") : st.state === "failed" ? t("failed") : t("pending")}
              </div>
            </div>
            {i < latest.stages.length - 1 && (
              <div className={`dag-edge ${st.state === "success" ? "done" : st.state === "running" ? "active" : ""}`}>
                {st.state === "running" && <div className="pulse"/>}
              </div>
            )}
          </React.Fragment>
        ))}
      </div>
      <div className="dag-meta">
        <Chip tone={latest.status === "running" ? "running" : latest.status === "success" ? "success" : "danger"} dot>
          {latest.id.slice(0, 8)}
        </Chip>
        {latest.records != null && <Chip>{latest.records.toLocaleString()} {t("records_count")}</Chip>}
        {latest.duration != null && <Chip>{Math.floor(latest.duration/60)}m {latest.duration%60}s</Chip>}
      </div>
    </div>
  );
};

// ----- Load balancer health: latency (p95) + traffic (req/s) -----
const LbHealthKpi = ({ t }) => {
  const hours = 24;
  const lat = useApi(`/api/latency?hours=${hours}`, [hours]);
  const tr  = useApi(`/api/traffic?hours=${hours}`, [hours]);

  // Hide silently if both endpoints fail (misconfig or perms).
  if (lat.error && tr.error) return null;

  const latPts = lat.data?.points || [];
  const trPts  = tr.data?.points  || [];
  const latSeries = latPts.map(p => p.v);
  const trSeries  = trPts.map(p => p.v);

  const fmtMs = (v) => v == null ? "—" : v < 1000 ? `${Math.round(v)} ms` : `${(v/1000).toFixed(2)} s`;
  const fmtRps = (v) => v == null ? "—" : v < 1 ? v.toFixed(2) : v < 100 ? v.toFixed(1) : Math.round(v).toLocaleString();
  const tone = (ms) => ms == null ? "default" : ms < 500 ? "success" : ms < 1500 ? "warn" : "danger";

  const loadingLat = lat.loading && !lat.data;
  const loadingTr  = tr.loading  && !tr.data;

  return (
    <div className="lb-kpi-grid" style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(360px, 1fr))", gap: 12, marginBottom: 16 }}>
      {/* Latency */}
      {!lat.error && (
        <Card>
          <div style={{ display: "flex", alignItems: "center", gap: 16 }}>
            <div style={{ display: "flex", alignItems: "flex-start", gap: 10 }}>
              <Icon name="clock" size={14} style={{ color: "var(--accent)", marginTop: 4 }}/>
              <div>
                <div style={{ fontSize: 10, letterSpacing: 1.4, textTransform: "uppercase", color: "var(--text-faint)" }}>
                  {t("latency_title")} <InfoTip text={t("tip_latency")}/>
                </div>
                <div className="num-mono" style={{ fontSize: 26, fontWeight: 700, color: "var(--text)", lineHeight: 1.1, marginTop: 2 }}>
                  {loadingLat ? "…" : fmtMs(lat.data?.p95_ms)}
                </div>
                <div style={{ fontSize: 11, color: "var(--text-dim)", marginTop: 2 }}>
                  p95 · {t("last_24h")}
                </div>
                <div style={{ marginTop: 6 }}>
                  <Chip tone={tone(lat.data?.current_ms)} dot>{t("latency_current")}: {fmtMs(lat.data?.current_ms)}</Chip>
                </div>
              </div>
            </div>
            <div style={{ flex: 1, minWidth: 120 }}>
              {latSeries.length > 1 && <Sparkline data={latSeries} width={220} height={44} color="var(--accent)"/>}
            </div>
          </div>
        </Card>
      )}

      {/* Traffic */}
      {!tr.error && (
        <Card>
          <div style={{ display: "flex", alignItems: "center", gap: 16 }}>
            <div style={{ display: "flex", alignItems: "flex-start", gap: 10 }}>
              <Icon name="analytics" size={14} style={{ color: "var(--accent-2)", marginTop: 4 }}/>
              <div>
                <div style={{ fontSize: 10, letterSpacing: 1.4, textTransform: "uppercase", color: "var(--text-faint)" }}>
                  {t("traffic_title")} <InfoTip text={t("tip_traffic")}/>
                </div>
                <div className="num-mono" style={{ fontSize: 26, fontWeight: 700, color: "var(--text)", lineHeight: 1.1, marginTop: 2 }}>
                  {loadingTr ? "…" : fmtRps(tr.data?.current_rps)}
                  <span style={{ fontSize: 13, color: "var(--text-dim)", fontWeight: 400, marginLeft: 4 }}>{t("rps_unit")}</span>
                </div>
                <div style={{ fontSize: 11, color: "var(--text-dim)", marginTop: 2 }}>
                  {t("traffic_now")} · {t("last_24h")}
                </div>
                <div style={{ marginTop: 6, display: "flex", gap: 6, flexWrap: "wrap" }}>
                  <Chip>{t("traffic_peak")}: {fmtRps(tr.data?.peak_rps)} {t("rps_unit")}</Chip>
                  {tr.data?.total_requests != null && (
                    <Chip>{tr.data.total_requests.toLocaleString()} {t("traffic_total")}</Chip>
                  )}
                </div>
              </div>
            </div>
            <div style={{ flex: 1, minWidth: 120 }}>
              {trSeries.length > 1 && <Sparkline data={trSeries} width={220} height={44} color="var(--accent-2)"/>}
            </div>
          </div>
        </Card>
      )}
    </div>
  );
};

Object.assign(window, { ViewOverview, MiniDag, LoadingBlock, EmptyBlock, ApiError, LbHealthKpi });
