// Features grid, integrations marquee, metric bank browser

const { useState: uF, useEffect: eF, useMemo: mF } = React;

function FeatureGrid({ theme }) {
  const features = [
    {
      tag: "LOCAL-FIRST",
      title: "Your data never leaves your box.",
      body: "SQLite storage, no telemetry, no cloud. Run behind a firewall, on a plane, in a SCIF. Evalyn is a library and a CLI — not a service.",
      stat: "0 packets", statSub: "sent to anyone",
    },
    {
      tag: "136 METRICS",
      title: "A stocked pantry. Not an empty one.",
      body: "76 objective metrics (regex, JSON, cost, latency, URL-counting, schema) + 60 LLM-judge metrics across safety, grounding, completeness, style, ethics — including audio, image, and video eval.",
      stat: "76 / 60", statSub: "objective / llm",
    },
    {
      tag: "9 OPTIMIZERS",
      title: "Judges that learn from you.",
      body: "Calibrate any LLM judge with GEPA, APE, OPRO, EvoPrompt, TextGrad, MIPROv2, PromptBreeder, active learning, and ensemble fusion — same interface, pick what fits.",
      stat: "Δ +27%", statSub: "avg alignment lift",
    },
    {
      tag: "14 INSTRUMENTORS",
      title: "Zero integration work.",
      body: "Drop @eval on any function. Auto-patches OpenAI, Anthropic, Gemini, xAI, LangChain, LangGraph, Google ADK, Claude Agent SDK, CrewAI, AutoGen, DSPy, Haystack, LlamaIndex, Semantic Kernel.",
      stat: "1 decorator", statSub: "14 frameworks",
    },
    {
      tag: "75+ ANALYSES",
      title: "More than pass/fail.",
      body: "Cohort analysis, confusion matrices, cost dashboards, trend forecasting, root-cause analysis, what-if simulation, regression detection, cluster-failures, cluster-misalignments.",
      stat: "7 HTML reports", statSub: "per run",
    },
    {
      tag: "ONE COMMAND",
      title: "evalyn one-click.",
      body: "Detect framework → build dataset → suggest metrics → run eval → generate report. End to end in a single invocation, or break into stages when you want surgical control.",
      stat: "≤ 90s", statSub: "typical full loop",
    },
  ];
  return (
    <Section theme={theme} id="features"
             eyebrow="what's in the box"
             title="Every piece of the evaluation stack, local."
             sub="Eval doesn't have to be a SaaS. Evalyn bundles tracing, metrics, calibration, and reporting into one Python package — and gives you every knob on day one.">
      <div style={{
        display: 'grid',
        gridTemplateColumns: 'repeat(3, 1fr)',
        gap: 1,
        background: theme.border,
        border: `1px solid ${theme.border}`,
      }}>
        {features.map((f, i) => (
          <div key={f.tag} style={{
            background: theme.panel,
            padding: 32,
            display: 'flex', flexDirection: 'column', gap: 16,
            minHeight: 280,
            position: 'relative',
            transition: 'background 0.2s',
          }}
            onMouseEnter={e => e.currentTarget.style.background = theme.panel2}
            onMouseLeave={e => e.currentTarget.style.background = theme.panel}
          >
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
              <span style={{
                fontFamily: 'var(--mono)', fontSize: 10,
                letterSpacing: '0.18em', color: theme.accent,
                padding: '3px 8px', border: `1px solid ${theme.accentHair}`,
              }}>{f.tag}</span>
              <span style={{
                fontFamily: 'var(--mono)', fontSize: 10,
                color: theme.textMute, letterSpacing: '0.1em',
              }}>{String(i+1).padStart(2, '0')}/06</span>
            </div>
            <h3 style={{
              fontFamily: 'var(--display)', fontSize: 26,
              fontWeight: 500, letterSpacing: '-0.015em',
              lineHeight: 1.15, color: theme.text, margin: 0,
              textWrap: 'balance',
            }}>{f.title}</h3>
            <p style={{
              fontFamily: 'var(--body)', fontSize: 14.5, lineHeight: 1.55,
              color: theme.textDim, margin: 0, flex: 1,
            }}>{f.body}</p>
            <div style={{
              borderTop: `1px dashed ${theme.border}`, paddingTop: 12,
              display: 'flex', justifyContent: 'space-between', alignItems: 'baseline',
            }}>
              <span style={{
                fontFamily: 'var(--display)', fontSize: 22, color: theme.accent,
                fontWeight: 500, letterSpacing: '-0.01em',
              }}>{f.stat}</span>
              <span style={{ fontFamily: 'var(--mono)', fontSize: 11, color: theme.textMute }}>{f.statSub}</span>
            </div>
          </div>
        ))}
      </div>
    </Section>
  );
}

const INTEGRATIONS = [
  ['OpenAI', 'llm'], ['Anthropic', 'llm'], ['Gemini', 'llm'], ['xAI', 'llm'],
  ['LangChain', 'fw'], ['LangGraph', 'fw'], ['Google ADK', 'fw'], ['Claude Agent SDK', 'fw'],
  ['CrewAI', 'fw'], ['AutoGen', 'fw'], ['DSPy', 'fw'], ['Haystack', 'fw'],
  ['LlamaIndex', 'fw'], ['Semantic Kernel', 'fw'], ['SQLite', 'store'], ['OpenTelemetry', 'std'],
];

function IntegrationsMarquee({ theme }) {
  const row = INTEGRATIONS;
  return (
    <Section theme={theme} id="integrations"
             eyebrow="auto-instrumented"
             title="@eval works with the agents you already have."
             sub="If your stack is in this list, you don't change a line. Evalyn monkey-patches the right entrypoints and captures every call underneath.">
      <div style={{
        borderTop: `1px solid ${theme.border}`,
        borderBottom: `1px solid ${theme.border}`,
        overflow: 'hidden',
        position: 'relative',
        padding: '28px 0',
        background: theme.scheme === 'dark' ? 'rgba(0,0,0,0.2)' : 'rgba(255,255,255,0.3)',
      }}>
        <div style={{
          display: 'flex', gap: 60,
          whiteSpace: 'nowrap',
          animation: 'marquee 40s linear infinite',
          willChange: 'transform',
          width: 'max-content',
        }}>
          {[...row, ...row, ...row].map((it, i) => (
            <div key={i} style={{
              display: 'flex', alignItems: 'center', gap: 12,
              fontFamily: 'var(--display)', fontSize: 28,
              color: theme.textDim, letterSpacing: '-0.01em', fontWeight: 400,
            }}>
              <span style={{
                width: 10, height: 10,
                background: it[1] === 'llm' ? theme.accent : 'transparent',
                border: `1px solid ${it[1] === 'llm' ? theme.accent : theme.borderStrong}`,
                display: 'inline-block',
              }} />
              <span>{it[0]}</span>
              <span style={{
                fontFamily: 'var(--mono)', fontSize: 10, color: theme.textMute,
                letterSpacing: '0.15em', textTransform: 'uppercase',
              }}>{it[1]}</span>
            </div>
          ))}
        </div>
        {/* fade masks */}
        <div style={{
          position: 'absolute', inset: 0, pointerEvents: 'none',
          background: `linear-gradient(90deg, ${theme.bg}, transparent 10%, transparent 90%, ${theme.bg})`,
        }} />
      </div>
      <div style={{
        marginTop: 20, fontFamily: 'var(--mono)', fontSize: 12, color: theme.textDim,
        display: 'flex', gap: 24, flexWrap: 'wrap',
      }}>
        <span><span style={{ width: 8, height: 8, background: theme.accent, display: 'inline-block', marginRight: 8 }} /> LLM provider</span>
        <span><span style={{ width: 8, height: 8, border: `1px solid ${theme.borderStrong}`, display: 'inline-block', marginRight: 8 }} /> Agent framework</span>
        <span style={{ color: theme.textMute }}>→ don't see yours? open an issue.</span>
      </div>
    </Section>
  );
}

// ---------- Metric bank browser ----------

const METRICS_DATA = [
  // objective
  { id: 'output_nonempty', type: 'obj', cat: 'structure', desc: 'PASS if output is not empty/None.' },
  { id: 'latency_ms', type: 'obj', cat: 'efficiency', desc: 'Measure execution latency in milliseconds.' },
  { id: 'url_count', type: 'obj', cat: 'grounding', desc: 'Counts URLs in output (proxy for citations).' },
  { id: 'json_valid', type: 'obj', cat: 'structure', desc: 'PASS if output is parseable JSON.' },
  { id: 'json_schema_match', type: 'obj', cat: 'structure', desc: 'PASS if output matches a given JSON schema.' },
  { id: 'regex_match', type: 'obj', cat: 'structure', desc: 'PASS if output matches a regex pattern.' },
  { id: 'token_cost_usd', type: 'obj', cat: 'efficiency', desc: 'Total USD cost derived from token counts.' },
  { id: 'token_count_output', type: 'obj', cat: 'efficiency', desc: 'Number of output tokens.' },
  { id: 'profanity_count', type: 'obj', cat: 'robustness', desc: 'Count of profane terms in output.' },
  { id: 'pii_count', type: 'obj', cat: 'robustness', desc: 'Count of PII matches (regex + NER).' },
  { id: 'language_match', type: 'obj', cat: 'style', desc: 'Output language matches input language.' },
  { id: 'readability_flesch', type: 'obj', cat: 'style', desc: 'Flesch reading ease score.' },
  { id: 'citation_present', type: 'obj', cat: 'grounding', desc: 'At least one citation/URL present.' },
  { id: 'distinct_n', type: 'obj', cat: 'diversity', desc: 'Distinct-N lexical diversity score.' },
  { id: 'rouge_l', type: 'obj', cat: 'correctness', desc: 'ROUGE-L overlap vs reference.' },
  { id: 'bleu', type: 'obj', cat: 'correctness', desc: 'BLEU-4 vs reference.' },
  { id: 'bertscore', type: 'obj', cat: 'correctness', desc: 'BERTScore F1 vs reference.' },
  { id: 'audio_duration', type: 'obj', cat: 'structure', desc: 'Duration of output audio (seconds).' },
  { id: 'image_is_valid', type: 'obj', cat: 'structure', desc: 'Output decodes as a valid image.' },
  { id: 'video_frame_count', type: 'obj', cat: 'structure', desc: 'Number of frames in output video.' },
  // subjective
  { id: 'helpfulness_accuracy', type: 'llm', cat: 'correctness', desc: 'Answers the user question accurately and helpfully.' },
  { id: 'factual_accuracy', type: 'llm', cat: 'correctness', desc: 'Factual claims are accurate and verifiable.' },
  { id: 'clarity_and_readability', type: 'llm', cat: 'style', desc: 'Response is clear and easy to follow.' },
  { id: 'completeness', type: 'llm', cat: 'completeness', desc: 'Addresses all parts of the question.' },
  { id: 'conciseness', type: 'llm', cat: 'style', desc: 'Avoids unnecessary verbosity.' },
  { id: 'instruction_following', type: 'llm', cat: 'instruction', desc: 'Follows explicit user constraints.' },
  { id: 'tone_appropriateness', type: 'llm', cat: 'style', desc: 'Tone fits the context and audience.' },
  { id: 'refusal_appropriateness', type: 'llm', cat: 'safety', desc: 'Refuses only when it should.' },
  { id: 'groundedness_in_context', type: 'llm', cat: 'grounding', desc: 'Claims are supported by provided context.' },
  { id: 'citation_faithfulness', type: 'llm', cat: 'grounding', desc: 'Citations actually support the claim.' },
  { id: 'hallucination', type: 'llm', cat: 'grounding', desc: 'Detects unsupported fabrication.' },
  { id: 'bias_detection', type: 'llm', cat: 'ethics', desc: 'Flags demographic or ideological bias.' },
  { id: 'toxicity', type: 'llm', cat: 'safety', desc: 'Flags harmful, abusive, or toxic content.' },
  { id: 'agent_plan_quality', type: 'llm', cat: 'agent', desc: 'Plan is coherent and leads to the goal.' },
  { id: 'tool_use_appropriateness', type: 'llm', cat: 'agent', desc: 'Uses the right tool at the right time.' },
  { id: 'persona_consistency', type: 'llm', cat: 'persona', desc: 'Stays in-character across the turn.' },
  { id: 'summary_fidelity', type: 'llm', cat: 'summarization', desc: 'Summary is faithful to source.' },
  { id: 'argumentation_quality', type: 'llm', cat: 'argumentation', desc: 'Arguments are well-structured and sound.' },
  { id: 'creativity', type: 'llm', cat: 'creativity', desc: 'Novel and imaginative response.' },
  { id: 'accessibility_clarity', type: 'llm', cat: 'accessibility', desc: 'Understandable to a broad audience.' },
];

function MetricBank({ theme }) {
  const [q, setQ] = useState('');
  const [type, setType] = useState('all');
  const [cat, setCat] = useState('all');

  const cats = useMemo(() => {
    const s = new Set(METRICS_DATA.map(m => m.cat));
    return ['all', ...Array.from(s).sort()];
  }, []);

  const filtered = useMemo(() => METRICS_DATA.filter(m => {
    if (type !== 'all' && m.type !== type) return false;
    if (cat !== 'all' && m.cat !== cat) return false;
    if (q && !(m.id.includes(q.toLowerCase()) || m.desc.toLowerCase().includes(q.toLowerCase()))) return false;
    return true;
  }), [q, type, cat]);

  return (
    <Section theme={theme} id="metrics"
             eyebrow="metric bank · sample of 136"
             title="136 metrics. Searchable. Swap-able. Yours to extend."
             sub="A representative slice of the built-in metric catalog. Every metric is a small Python file — contribute your own with a PR.">
      <div style={{
        border: `1px solid ${theme.border}`,
        background: theme.panel,
      }}>
        {/* Search + filters */}
        <div style={{
          display: 'flex', gap: 0, borderBottom: `1px solid ${theme.border}`,
          flexWrap: 'wrap',
        }}>
          <div style={{ flex: 1, minWidth: 260, display: 'flex', alignItems: 'center', gap: 10, padding: '14px 18px' }}>
            <span style={{ color: theme.accent, fontFamily: 'var(--mono)', fontSize: 14 }}>⌕</span>
            <input
              type="text" value={q}
              onChange={e => setQ(e.target.value)}
              placeholder="search e.g. 'grounding' or 'hallucination'..."
              style={{
                border: 'none', outline: 'none', background: 'transparent',
                color: theme.text, flex: 1,
                fontFamily: 'var(--mono)', fontSize: 13,
              }}
            />
            <span style={{ fontFamily: 'var(--mono)', fontSize: 11, color: theme.textMute }}>{filtered.length}/{METRICS_DATA.length}</span>
          </div>
          <div style={{ display: 'flex', borderLeft: `1px solid ${theme.border}` }}>
            {['all', 'obj', 'llm'].map(t => (
              <button key={t} onClick={() => setType(t)}
                style={{
                  background: type === t ? theme.panel2 : 'transparent',
                  border: 'none',
                  borderRight: `1px solid ${theme.border}`,
                  color: type === t ? theme.accent : theme.textDim,
                  padding: '14px 18px',
                  fontFamily: 'var(--mono)', fontSize: 11,
                  letterSpacing: '0.15em', textTransform: 'uppercase',
                  cursor: 'pointer',
                }}>{t === 'all' ? 'all' : t === 'obj' ? 'objective' : 'llm judge'}</button>
            ))}
          </div>
        </div>
        {/* Cat chips */}
        <div style={{
          display: 'flex', gap: 6, padding: '12px 18px', flexWrap: 'wrap',
          borderBottom: `1px solid ${theme.border}`,
        }}>
          {cats.map(c => (
            <button key={c} onClick={() => setCat(c)}
              style={{
                background: cat === c ? theme.accent : 'transparent',
                color: cat === c ? '#1a1108' : theme.textDim,
                border: `1px solid ${cat === c ? theme.accent : theme.border}`,
                padding: '5px 10px',
                fontFamily: 'var(--mono)', fontSize: 10,
                letterSpacing: '0.08em', cursor: 'pointer',
                textTransform: 'uppercase',
              }}>{c}</button>
          ))}
        </div>
        {/* List */}
        <div style={{ maxHeight: 420, overflow: 'auto' }}>
          {filtered.length === 0 && (
            <div style={{ padding: 40, textAlign: 'center', color: theme.textMute, fontFamily: 'var(--mono)' }}>no matches</div>
          )}
          {filtered.map((m, i) => (
            <div key={m.id} style={{
              display: 'grid',
              gridTemplateColumns: '60px 260px 110px 1fr 80px',
              alignItems: 'center', gap: 16,
              padding: '14px 18px',
              borderBottom: i < filtered.length - 1 ? `1px solid ${theme.border}` : 'none',
              transition: 'background 0.15s',
            }}
              onMouseEnter={e => e.currentTarget.style.background = theme.panel2}
              onMouseLeave={e => e.currentTarget.style.background = 'transparent'}
            >
              <span style={{ fontFamily: 'var(--mono)', fontSize: 10, color: theme.textMute }}>
                {String(i+1).padStart(3,'0')}
              </span>
              <code style={{ fontFamily: 'var(--mono)', fontSize: 12.5, color: theme.text }}>{m.id}</code>
              <span style={{
                fontFamily: 'var(--mono)', fontSize: 10,
                color: m.type === 'llm' ? theme.accent : theme.textDim,
                padding: '3px 8px', border: `1px solid ${m.type === 'llm' ? theme.accentHair : theme.border}`,
                textAlign: 'center', letterSpacing: '0.12em',
                textTransform: 'uppercase', width: 'fit-content',
              }}>{m.type === 'llm' ? 'llm judge' : 'objective'}</span>
              <span style={{ fontFamily: 'var(--body)', fontSize: 13.5, color: theme.textDim }}>{m.desc}</span>
              <span style={{
                fontFamily: 'var(--mono)', fontSize: 10, color: theme.textMute,
                letterSpacing: '0.1em', textTransform: 'uppercase', textAlign: 'right',
              }}>{m.cat}</span>
            </div>
          ))}
        </div>
        <div style={{
          borderTop: `1px solid ${theme.border}`,
          padding: '14px 18px',
          fontFamily: 'var(--mono)', fontSize: 11, color: theme.textMute,
          display: 'flex', justifyContent: 'space-between', alignItems: 'center',
          background: theme.scheme === 'dark' ? 'rgba(0,0,0,0.2)' : 'rgba(255,255,255,0.3)',
        }}>
          <span>showing {filtered.length} of {METRICS_DATA.length} example metrics · 136 built-in total</span>
          <a href="#" style={{ color: theme.accent, textDecoration: 'none' }}>
            contribute a metric <Icon.arrow />
          </a>
        </div>
      </div>
    </Section>
  );
}

Object.assign(window, { FeatureGrid, IntegrationsMarquee, MetricBank, INTEGRATIONS, METRICS_DATA });
