// LineageLens Interactive Playground
const { useState, useEffect, useRef, useCallback } = React;

// ========== CONFIG ==========
const API_BASE = 'http://localhost:8787';
const DEMO_TOKEN = 'demo-token-placeholder';

// ========== UTILITY: unique ID ==========
let _uid = 0;
const uid = () => `node-${++_uid}-${Date.now()}`;

// ========== CODE INPUT PANEL ==========
function CodeInput({ onTrack, loading }) {
  const [code, setCode] = useState(`async function chargeCard(amount) {
  const key = "sk_live_4f...";
  const res = await fetch(url, {
    headers: { Authorization: key },
    body: JSON.stringify({ amount })
  });
  return res.json();
}`);
  const [filePath, setFilePath] = useState('demo.py');

  return (
    <div className="card" style={{ padding: 0, overflow: 'hidden' }}>
      <div style={{ padding: '16px 20px', borderBottom: '1px solid var(--border-muted)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <div style={{ width: 8, height: 8, borderRadius: '50%', background: 'var(--solo)' }} />
          <span style={{ fontSize: 13, fontFamily: 'var(--mono)', color: 'var(--text-muted)' }}>CODE INPUT</span>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <span style={{ fontSize: 12, color: 'var(--text-dim)' }}>File:</span>
          <input
            value={filePath}
            onChange={e => setFilePath(e.target.value)}
            style={{
              background: 'var(--bg-3)', border: '1px solid var(--border)', borderRadius: 6,
              padding: '6px 10px', fontSize: 12, fontFamily: 'var(--mono)', color: 'var(--text)',
              width: 140, outline: 'none'
            }}
          />
        </div>
      </div>
      <textarea
        value={code}
        onChange={e => setCode(e.target.value)}
        spellCheck={false}
        style={{
          width: '100%', minHeight: 220, padding: '16px 20px', resize: 'vertical',
          background: 'var(--bg-1)', border: 'none', outline: 'none',
          fontFamily: 'var(--mono)', fontSize: 13, lineHeight: 1.7,
          color: 'var(--text)', caretColor: 'var(--solo)',
        }}
        placeholder="Paste your AI-generated code here..."
      />
      <div style={{ padding: '14px 20px', borderTop: '1px solid var(--border-muted)', display: 'flex', gap: 10, background: 'var(--bg-2)' }}>
        <button
          onClick={() => onTrack(code, filePath)}
          disabled={loading || !code.trim()}
          className="btn btn-lg"
          style={{
            background: loading ? 'var(--bg-3)' : 'var(--solo)', color: '#0B1020', fontWeight: 600,
            opacity: loading || !code.trim() ? 0.5 : 1, transition: 'all 0.2s ease',
            position: 'relative', overflow: 'hidden'
          }}
        >
          {loading && <span className="demo-spinner" />}
          {loading ? 'Tracking...' : '⚡ Track Code'}
        </button>
        <button
          onClick={() => onTrack('// Simulated AI event\nconsole.log("hello from AI");', 'simulated.js')}
          disabled={loading}
          className="btn btn-lg btn-ghost"
          style={{ opacity: loading ? 0.5 : 1 }}
        >
          🎲 Simulate AI Event
        </button>
      </div>
    </div>
  );
}

// ========== API RESPONSE PANEL ==========
function ApiResponse({ response, error }) {
  if (!response && !error) {
    return (
      <div className="card" style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: 120, color: 'var(--text-dim)', fontFamily: 'var(--mono)', fontSize: 12 }}>
        Waiting for API response...
      </div>
    );
  }
  const isError = !!error;
  return (
    <div className="card" style={{ padding: 0, overflow: 'hidden', borderColor: isError ? 'color-mix(in oklab, var(--red) 40%, var(--border))' : 'color-mix(in oklab, var(--green) 40%, var(--border))' }}>
      <div style={{ padding: '12px 20px', borderBottom: '1px solid var(--border-muted)', display: 'flex', alignItems: 'center', gap: 8, background: isError ? 'rgba(248,81,73,0.06)' : 'rgba(63,185,80,0.06)' }}>
        <span style={{ color: isError ? 'var(--red)' : 'var(--green)', fontSize: 14 }}>{isError ? '✕' : '✓'}</span>
        <span style={{ fontSize: 13, fontFamily: 'var(--mono)', color: isError ? 'var(--red)' : 'var(--green)' }}>
          {isError ? 'ERROR' : 'SUCCESS'} · POST /ingest
        </span>
      </div>
      <pre style={{
        padding: '16px 20px', margin: 0, background: 'var(--bg-1)',
        fontFamily: 'var(--mono)', fontSize: 12, lineHeight: 1.6,
        color: 'var(--text-muted)', overflow: 'auto', maxHeight: 200
      }}>
        {isError ? error : JSON.stringify(response, null, 2)}
      </pre>
    </div>
  );
}

// ========== LIVE EVENT LOGS ==========
function EventLogs({ logs }) {
  const ref = useRef(null);
  useEffect(() => { if (ref.current) ref.current.scrollTop = ref.current.scrollHeight; }, [logs]);

  return (
    <div className="card" style={{ padding: 0, overflow: 'hidden' }}>
      <div style={{ padding: '12px 20px', borderBottom: '1px solid var(--border-muted)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <span style={{ width: 6, height: 6, borderRadius: '50%', background: 'var(--green)', boxShadow: '0 0 8px var(--green)', animation: 'blink 2s infinite' }} />
          <span style={{ fontSize: 13, fontFamily: 'var(--mono)', color: 'var(--text-muted)' }}>LIVE EVENT LOG</span>
        </div>
        <span style={{ fontSize: 11, fontFamily: 'var(--mono)', color: 'var(--text-dim)' }}>{logs.length} events</span>
      </div>
      <div ref={ref} style={{ maxHeight: 280, overflow: 'auto', background: 'var(--bg-1)' }}>
        {logs.length === 0 && (
          <div style={{ padding: 24, textAlign: 'center', color: 'var(--text-dim)', fontSize: 12, fontFamily: 'var(--mono)' }}>
            No events yet. Track some code to begin.
          </div>
        )}
        {logs.map((log, i) => (
          <div key={i} style={{
            padding: '10px 20px', borderBottom: '1px solid var(--border-muted)',
            fontFamily: 'var(--mono)', fontSize: 12, display: 'flex', gap: 12, alignItems: 'flex-start',
            animation: 'fadeSlideIn 0.3s ease'
          }}>
            <span style={{ color: 'var(--text-dim)', flexShrink: 0, width: 70 }}>{log.time}</span>
            <span style={{ color: log.color || 'var(--text-muted)' }}>{log.icon} {log.message}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

// ========== GRAPH VISUALIZATION ==========
function LineageGraphVis({ nodes, edges }) {
  const canvasRef = useRef(null);
  const [hoveredNode, setHoveredNode] = useState(null);
  const [positions, setPositions] = useState({});

  // Layout nodes in a force-directed-like grid
  useEffect(() => {
    if (nodes.length === 0) return;
    const pos = {};
    const cx = 350, cy = 200;
    nodes.forEach((n, i) => {
      const angle = (i / nodes.length) * Math.PI * 2 - Math.PI / 2;
      const radius = 130 + (i % 2) * 40;
      pos[n.id] = {
        x: cx + Math.cos(angle) * radius,
        y: cy + Math.sin(angle) * radius,
      };
    });
    setPositions(pos);
  }, [nodes]);

  const nodeColors = { 'ai-code': 'var(--solo)', 'version': 'var(--team)', 'file': 'var(--ent)', 'prompt': 'var(--yellow)', 'risk': 'var(--red)' };

  if (nodes.length === 0) {
    return (
      <div className="card" style={{ minHeight: 300, display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column', gap: 12 }}>
        <div style={{ fontSize: 40, opacity: 0.3 }}>🔗</div>
        <div style={{ color: 'var(--text-dim)', fontFamily: 'var(--mono)', fontSize: 12 }}>
          Track code to see the lineage graph
        </div>
      </div>
    );
  }

  return (
    <div className="card" style={{ padding: 0, overflow: 'hidden' }}>
      <div style={{ padding: '12px 20px', borderBottom: '1px solid var(--border-muted)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <span style={{ fontSize: 13, fontFamily: 'var(--mono)', color: 'var(--text-muted)' }}>LINEAGE GRAPH</span>
        </div>
        <span style={{ fontSize: 11, fontFamily: 'var(--mono)', color: 'var(--text-dim)' }}>{nodes.length} nodes · {edges.length} edges</span>
      </div>
      <div style={{ background: 'var(--bg-1)', position: 'relative', height: 400 }}>
        <svg viewBox="0 0 700 400" style={{ width: '100%', height: '100%' }}>
          <defs>
            <marker id="graph-arrow" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto">
              <path d="M0,0 L8,4 L0,8 Z" fill="var(--text-dim)" />
            </marker>
          </defs>
          {/* Edges */}
          {edges.map((e, i) => {
            const from = positions[e.from];
            const to = positions[e.to];
            if (!from || !to) return null;
            const active = hoveredNode === e.from || hoveredNode === e.to;
            return (
              <line key={i} x1={from.x} y1={from.y} x2={to.x} y2={to.y}
                stroke={active ? 'var(--solo)' : 'var(--border)'}
                strokeWidth={active ? 2 : 1}
                strokeDasharray={active ? 'none' : '4 4'}
                markerEnd="url(#graph-arrow)"
                style={{ transition: 'all 0.3s ease' }}
              />
            );
          })}
          {/* Nodes */}
          {nodes.map(n => {
            const p = positions[n.id];
            if (!p) return null;
            const color = nodeColors[n.type] || 'var(--text-muted)';
            const hovered = hoveredNode === n.id;
            return (
              <g key={n.id}
                onMouseEnter={() => setHoveredNode(n.id)}
                onMouseLeave={() => setHoveredNode(null)}
                style={{ cursor: 'pointer' }}
              >
                <rect x={p.x - 65} y={p.y - 20} width={130} height={40} rx={8}
                  fill={hovered ? 'var(--bg-3)' : 'var(--bg-2)'}
                  stroke={color}
                  strokeOpacity={hovered ? 1 : 0.5}
                  strokeWidth={hovered ? 2 : 1}
                  style={{ transition: 'all 0.2s ease', filter: hovered ? `drop-shadow(0 0 8px ${color})` : 'none' }}
                />
                <circle cx={p.x - 50} cy={p.y} r={4} fill={color} />
                <text x={p.x - 40} y={p.y - 4} fontSize={11} fontFamily="var(--mono)" fill="var(--text)">{n.label}</text>
                <text x={p.x - 40} y={p.y + 10} fontSize={9} fontFamily="var(--mono)" fill="var(--text-muted)">{n.sub}</text>
              </g>
            );
          })}
        </svg>
      </div>
    </div>
  );
}

// ========== STATS BAR ==========
function StatsBar({ stats }) {
  return (
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 12 }}>
      {stats.map(s => (
        <div key={s.label} className="card" style={{ padding: '16px 20px', textAlign: 'center', transition: 'all 0.3s ease' }}>
          <div style={{ fontSize: 28, fontWeight: 600, letterSpacing: '-0.02em', color: s.color || 'var(--text)' }}>{s.value}</div>
          <div style={{ fontSize: 11, fontFamily: 'var(--mono)', color: 'var(--text-dim)', marginTop: 6, letterSpacing: '0.04em' }}>{s.label}</div>
        </div>
      ))}
    </div>
  );
}

// ========== MAIN PLAYGROUND APP ==========
function DemoPlayground() {
  const [loading, setLoading] = useState(false);
  const [response, setResponse] = useState(null);
  const [error, setError] = useState(null);
  const [logs, setLogs] = useState([]);
  const [nodes, setNodes] = useState([]);
  const [edges, setEdges] = useState([]);
  const [trackCount, setTrackCount] = useState(0);
  const [apiEndpoint, setApiEndpoint] = useState(API_BASE);

  const addLog = useCallback((message, icon = '→', color = 'var(--text-muted)') => {
    const now = new Date();
    const time = now.toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' });
    setLogs(prev => [...prev, { time, message, icon, color }]);
  }, []);

  const addGraphNode = useCallback((type, label, sub) => {
    const id = uid();
    setNodes(prev => [...prev, { id, type, label, sub }]);
    return id;
  }, []);

  const addGraphEdge = useCallback((from, to) => {
    setEdges(prev => [...prev, { from, to }]);
  }, []);

  const handleTrack = useCallback(async (code, filePath) => {
    setLoading(true);
    setError(null);
    setResponse(null);
    addLog(`Sending POST ${apiEndpoint}/ingest`, '📡', 'var(--solo)');
    addLog(`File: ${filePath} · ${code.split('\n').length} lines`, '📄', 'var(--text-muted)');

    try {
      const res = await fetch(`${apiEndpoint}/ingest`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${DEMO_TOKEN}`,
        },
        body: JSON.stringify({ event: 'ai_code', filePath, content: code }),
      });

      if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`);
      const data = await res.json();
      setResponse(data);
      setTrackCount(prev => prev + 1);
      addLog('Code tracked successfully!', '✓', 'var(--green)');
      addLog(`Response: ${JSON.stringify(data).substring(0, 80)}...`, '←', 'var(--team)');

      // Add to graph
      const codeId = addGraphNode('ai-code', filePath, `${code.split('\n').length} lines`);
      const verId = addGraphNode('version', `v${trackCount + 1}`, new Date().toLocaleTimeString());
      addGraphEdge(codeId, verId);
      if (nodes.length > 0) {
        addGraphEdge(nodes[nodes.length - 1].id, codeId);
      }
      addLog('Lineage graph updated', '🔗', 'var(--ent)');
    } catch (err) {
      // Simulate success for demo when API is unreachable
      const simulated = {
        status: 'ok',
        id: uid(),
        message: 'AI code event ingested (demo mode)',
        filePath,
        lines: code.split('\n').length,
        riskScore: Math.random() > 0.5 ? 'HIGH' : 'LOW',
        agent: ['Cursor', 'ChatGPT', 'Claude', 'Aider'][Math.floor(Math.random() * 4)],
        timestamp: new Date().toISOString(),
      };
      setResponse(simulated);
      setTrackCount(prev => prev + 1);
      addLog(`API unreachable — using demo mode`, '⚠', 'var(--yellow)');
      addLog('Code tracked (simulated)', '✓', 'var(--green)');

      const codeId = addGraphNode('ai-code', filePath, `${code.split('\n').length} lines`);
      const verId = addGraphNode('version', `v${trackCount + 1}`, simulated.agent);
      const riskId = addGraphNode(simulated.riskScore === 'HIGH' ? 'risk' : 'file', simulated.riskScore === 'HIGH' ? 'risk: HIGH' : 'risk: LOW', simulated.riskScore === 'HIGH' ? 'needs review' : 'clean');
      addGraphEdge(codeId, verId);
      addGraphEdge(verId, riskId);
      if (nodes.length > 0) addGraphEdge(nodes[nodes.length - 1].id, codeId);
      addLog('Lineage graph updated', '🔗', 'var(--ent)');
    }
    setLoading(false);
  }, [apiEndpoint, addLog, addGraphNode, addGraphEdge, nodes, trackCount]);

  const stats = [
    { label: 'TRACKED', value: trackCount, color: 'var(--solo)' },
    { label: 'GRAPH NODES', value: nodes.length, color: 'var(--team)' },
    { label: 'EDGES', value: edges.length, color: 'var(--ent)' },
    { label: 'EVENTS', value: logs.length, color: 'var(--yellow)' },
  ];

  return (
    <>
      {/* Hero */}
      <section style={{ paddingTop: 80, paddingBottom: 48, borderTop: 'none', position: 'relative', overflow: 'hidden' }}>
        <div className="grid-bg" />
        <div className="container" style={{ position: 'relative' }}>
          <div className="eyebrow"><span className="dot" style={{ background: 'var(--solo)' }} />INTERACTIVE PLAYGROUND</div>
          <h1 style={{ marginTop: 22, marginBottom: 18, fontSize: 48 }}>
            Track AI code. <span style={{ color: 'var(--solo)' }}>Live.</span>
          </h1>
          <p className="lead" style={{ marginBottom: 24 }}>
            Paste code, hit track, and watch LineageLens ingest, analyze, and graph the lineage in real time.
          </p>
          {/* Endpoint config */}
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 8 }}>
            <span style={{ fontSize: 12, fontFamily: 'var(--mono)', color: 'var(--text-dim)' }}>API Endpoint:</span>
            <input
              value={apiEndpoint}
              onChange={e => setApiEndpoint(e.target.value)}
              style={{
                background: 'var(--bg-2)', border: '1px solid var(--border)', borderRadius: 6,
                padding: '8px 14px', fontSize: 13, fontFamily: 'var(--mono)', color: 'var(--text)',
                width: 340, outline: 'none'
              }}
              placeholder="http://your-vm-ip:8787"
            />
          </div>
        </div>
      </section>

      {/* Stats */}
      <section style={{ paddingTop: 0, paddingBottom: 32, borderTop: 'none' }}>
        <div className="container">
          <StatsBar stats={stats} />
        </div>
      </section>

      {/* Main Grid */}
      <section style={{ paddingTop: 0, paddingBottom: 48, borderTop: 'none' }}>
        <div className="container">
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 20 }}>
            {/* Left: Input + Response */}
            <div style={{ display: 'flex', flexDirection: 'column', gap: 20 }}>
              <CodeInput onTrack={handleTrack} loading={loading} />
              <ApiResponse response={response} error={error} />
            </div>
            {/* Right: Logs + Graph */}
            <div style={{ display: 'flex', flexDirection: 'column', gap: 20 }}>
              <EventLogs logs={logs} />
            </div>
          </div>
        </div>
      </section>

      {/* Graph - full width */}
      <section style={{ paddingTop: 0, paddingBottom: 96, borderTop: 'none' }}>
        <div className="container">
          <LineageGraphVis nodes={nodes} edges={edges} />
        </div>
      </section>
    </>
  );
}

Object.assign(window, { DemoPlayground });
