// ValidateScreen.jsx — pre-deploy validation against Hyperliquid.
//
// Receives the OKRs the user picked from the deck, POSTs them to
// /api/validate-opportunities, and shows a per-pick verdict (still valid vs
// stale — based on whether the current HL orderflow contradicts the cell's
// directional thesis). User can drop invalid picks and send the rest to
// the trading desk backlog.

const { useState: useStateVS, useEffect: useEffectVS } = React;

function ValidateScreen({ picks, onBack, onSendToBacklog }) {
  const [status, setStatus] = useStateVS("loading"); // loading | ready | error
  const [results, setResults] = useStateVS([]);
  const [error, setError] = useStateVS(null);

  useEffectVS(() => {
    let cancelled = false;
    const payload = {
      picks: picks.map((p) => ({
        okrId: p.id,
        coin: extractCoin(p),
        pair: p.tag || (p._source && p._source.pair) || "",
        timeframe: p._source && p._source.timeframe,
        archetype: p._source && p._source.archetype,
        direction: p.direction || (p._source && p._source.direction) || null,
        orderflow_signal: p.orderflow_signal || (p._source && p._source.orderflow_signal) || null,
      })),
    };
    fetch("/api/validate-opportunities", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify(payload),
    })
      .then((r) => r.json().then((b) => ({ ok: r.ok, body: b })))
      .then(({ ok, body }) => {
        if (cancelled) return;
        if (!ok) {
          setError(body.error || "validation_failed");
          setStatus("error");
          return;
        }
        setResults(body.results || []);
        setStatus("ready");
      })
      .catch((e) => {
        if (cancelled) return;
        setError(String(e.message || e));
        setStatus("error");
      });
    return () => { cancelled = true; };
  }, []);

  const validIds = new Set(results.filter((r) => r.valid).map((r) => r.okrId));
  const validPicks = picks.filter((p) => validIds.has(p.id));
  const allValid = results.length > 0 && results.every((r) => r.valid);
  const someValid = validPicks.length > 0;

  return (
    <div style={{
      display: "flex",
      flexDirection: "column",
      height: "100%",
      padding: "0 20px 20px",
      gap: 14,
      boxSizing: "border-box",
      overflowY: "auto",
    }}>
      <header style={{ paddingTop: 6 }}>
        <button
          onClick={onBack}
          style={{
            background: "none",
            border: "none",
            padding: 0,
            color: "var(--color-text-link)",
            fontFamily: "var(--font-family-sans)",
            fontSize: 14,
            fontWeight: 500,
            cursor: "pointer",
            display: "inline-flex",
            alignItems: "center",
            gap: 4,
            marginBottom: 8,
          }}
        >
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
            <polyline points="15 18 9 12 15 6" />
          </svg>
          Back to picks
        </button>
        <div className="ds-overline" style={{ color: "var(--color-brand-primary)" }}>
          Validate against Hyperliquid
        </div>
        <h1 style={{
          margin: "4px 0 0",
          fontFamily: "var(--font-family-sans)",
          fontWeight: 600,
          fontSize: 22,
          lineHeight: "28px",
          letterSpacing: "-0.005em",
          color: "var(--color-text-primary)",
          textWrap: "balance",
        }}>
          {status === "loading" && "Checking the book…"}
          {status === "ready" && `${validPicks.length} of ${picks.length} still valid`}
          {status === "error" && "Validation failed"}
        </h1>
      </header>

      {status === "loading" && (
        <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
          {picks.map((p) => (
            <ValidatingSkeleton key={p.id} pick={p} />
          ))}
        </div>
      )}

      {status === "error" && (
        <div style={{
          background: "var(--color-surface-promo)",
          borderLeft: "4px solid var(--color-danger, #b03a2e)",
          borderRadius: "var(--radius-sm)",
          padding: "12px 14px",
        }}>
          <div className="ds-body-sm" style={{ color: "var(--color-text-primary)" }}>
            {error || "Could not reach Hyperliquid."}
          </div>
        </div>
      )}

      {status === "ready" && (
        <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
          {results.map((r) => (
            <VerdictRow key={r.okrId} result={r} pickLookup={pickById(picks, r.okrId)} />
          ))}
        </div>
      )}

      {status === "ready" && (
        <div style={{ marginTop: "auto", display: "flex", gap: 10 }}>
          <button
            onClick={onBack}
            style={{
              flex: 1,
              height: 48,
              background: "var(--color-surface-default)",
              color: "var(--color-text-primary)",
              border: "1px solid var(--color-border-subtle)",
              borderRadius: "var(--radius-sm)",
              fontFamily: "var(--font-family-sans)",
              fontWeight: 600,
              fontSize: 15,
              cursor: "pointer",
            }}
          >
            Back to picks
          </button>
          <button
            onClick={() => onSendToBacklog?.(validPicks, results)}
            disabled={!someValid}
            style={{
              flex: 1.4,
              height: 48,
              background: someValid ? "var(--color-brand-primary)" : "var(--color-surface-subtle)",
              color: someValid ? "var(--color-text-on-brand)" : "var(--color-text-muted)",
              border: "none",
              borderRadius: "var(--radius-sm)",
              fontFamily: "var(--font-family-sans)",
              fontWeight: 600,
              fontSize: 15,
              cursor: someValid ? "pointer" : "not-allowed",
              display: "inline-flex",
              alignItems: "center",
              justifyContent: "center",
              gap: 8,
            }}
          >
            {allValid ? `Send all ${validPicks.length} to desk` : `Send ${validPicks.length} cleared to desk`}
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
              <polyline points="9 18 15 12 9 6" />
            </svg>
          </button>
        </div>
      )}
    </div>
  );
}

function pickById(picks, id) {
  return picks.find((p) => p.id === id) || {};
}

// Best-effort coin extraction from the OKR. The worker emits _source.pair
// as "BTC/USDC:USDC"; OKR.tag is "Trending · BTC/USDC". Fall back to tag if
// _source is absent (e.g. mock data).
function extractCoin(okr) {
  const pair = (okr._source && okr._source.pair) || "";
  if (pair.includes("/")) return pair.split("/")[0];
  const tag = okr.tag || "";
  const m = tag.match(/·\s*([A-Z0-9]+)\s*\//);
  return m ? m[1] : "";
}

function ValidatingSkeleton({ pick }) {
  return (
    <div style={{
      background: "var(--color-surface-default)",
      border: "1px solid var(--color-border-subtle)",
      borderRadius: "var(--radius-sm)",
      padding: "12px 14px",
      display: "flex",
      alignItems: "center",
      gap: 12,
    }}>
      <div style={{
        width: 14, height: 14, borderRadius: "50%",
        border: "2px solid var(--color-border-subtle)",
        borderTopColor: "var(--color-brand-primary)",
        animation: "tw-spin 1.1s linear infinite",
      }} />
      <div style={{ display: "flex", flexDirection: "column", gap: 2 }}>
        <span className="ds-overline" style={{ color: "var(--color-text-muted)", fontSize: 10 }}>
          {pick.tag}
        </span>
        <span className="ds-body-sm" style={{ color: "var(--color-text-primary)", fontSize: 13 }}>
          {pick.objective}
        </span>
      </div>
    </div>
  );
}

function VerdictRow({ result, pickLookup }) {
  const valid = !!result.valid;
  const accent = valid ? "var(--color-success, #0b6b3a)" : "var(--color-danger, #b03a2e)";
  const bg = valid ? "rgba(11,107,58,0.05)" : "rgba(176,58,46,0.05)";
  return (
    <div style={{
      background: bg,
      border: `1px solid ${accent}`,
      borderRadius: "var(--radius-sm)",
      padding: "12px 14px",
      display: "flex",
      flexDirection: "column",
      gap: 6,
    }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8 }}>
        <div style={{ display: "flex", flexDirection: "column", gap: 1, minWidth: 0 }}>
          <span className="ds-overline" style={{ color: "var(--color-text-muted)", fontSize: 10 }}>
            {pickLookup.tag} · {result.timeframe || ""}
          </span>
          <span style={{
            fontFamily: "var(--font-family-sans)",
            fontWeight: 600,
            fontSize: 14,
            color: "var(--color-text-primary)",
            overflow: "hidden",
            textOverflow: "ellipsis",
            whiteSpace: "nowrap",
          }}>
            {pickLookup.objective}
          </span>
        </div>
        <span style={{
          padding: "3px 10px",
          borderRadius: "var(--radius-pill)",
          background: accent,
          color: "#fff",
          fontFamily: "var(--font-family-sans)",
          fontWeight: 700,
          fontSize: 10,
          letterSpacing: "0.06em",
          flexShrink: 0,
        }}>
          {valid ? "STILL VALID" : "STALE"}
        </span>
      </div>
      <div className="ds-caption" style={{
        color: "var(--color-text-secondary)",
        fontSize: 11,
        lineHeight: "15px",
      }}>
        {result.reason}
      </div>
      {result.current && (
        <div className="ds-caption" style={{
          color: "var(--color-text-muted)",
          fontSize: 10,
          fontFamily: "var(--font-family-mono, monospace)",
        }}>
          original {result.original?.direction || "—"} · {result.original?.flow_signal || "—"}
          {"  →  "}
          live {result.current.flow_signal} (conv {result.current.flow_conviction}, imb {Number(result.current.book_imbalance_50bps || 0).toFixed(3)})
        </div>
      )}
    </div>
  );
}

Object.assign(window, { ValidateScreen });
