// POC visual cube panel. Uses cubing.js TwistyPlayer when the CDN module is ready.
function CubeDisplay({ scramble, cubeState, connected, liveMoves, cubeEvents, eventCounts }) {
  const hostRef = React.useRef(null);
  const playerRef = React.useRef(null);
  const [ready, setReady] = React.useState(!!window.TwistyPlayer);
  const liveAlg = liveMoves.map(m => m.move).filter(Boolean).join(' ');
  const displayedAlg = [scramble, liveAlg].filter(Boolean).join(' ');

  React.useEffect(() => {
    if (window.TwistyPlayer) {
      setReady(true);
      return;
    }

    const timer = setInterval(() => {
      if (window.TwistyPlayer) {
        setReady(true);
        clearInterval(timer);
      }
    }, 100);

    return () => clearInterval(timer);
  }, []);

  React.useEffect(() => {
    if (!ready || !hostRef.current) return;

    if (playerRef.current) {
      playerRef.current.remove();
      playerRef.current = null;
    }

    const player = new window.TwistyPlayer({
      puzzle: '3x3x3',
      alg: displayedAlg,
      background: 'none',
      controlPanel: 'none',
      hintFacelets: 'none',
      visualization: '3D',
    });
    player.style.width = '100%';
    player.style.height = '220px';
    hostRef.current.appendChild(player);
    playerRef.current = player;

    return () => {
      player.remove();
      playerRef.current = null;
    };
  }, [ready, displayedAlg]);

  const status = connected
    ? (cubeEvents.length ? `${cubeEvents.length} cube event${cubeEvents.length === 1 ? '' : 's'}` : cubeState ? 'Receiving cube state' : 'Connected; waiting for cube events')
    : 'Connect a GAN cube to verify the physical state';
  const recentMoves = liveMoves.slice(-30).reverse();
  const recentEvents = cubeEvents.slice(-30).reverse();

  return (
    <div style={cubeDisplayStyles.wrap}>
      <div style={cubeDisplayStyles.header}>
        <span style={cubeDisplayStyles.title}>Cube</span>
        <span style={cubeDisplayStyles.status}>{status}</span>
      </div>
      <div style={cubeDisplayStyles.playerShell}>
        {ready ? (
          <div ref={hostRef} style={cubeDisplayStyles.playerHost} />
        ) : (
          <div style={cubeDisplayStyles.fallback}>Loading cube display...</div>
        )}
      </div>
      <div style={cubeDisplayStyles.diagnostics}>
        <div style={cubeDisplayStyles.diagHeader}>
          <span style={cubeDisplayStyles.movesLabel}>Move stream</span>
          <span style={cubeDisplayStyles.counts}>
            T {eventCounts?.total || 0} / M {eventCounts?.moves || 0} / F {eventCounts?.facelets || 0} / G {eventCounts?.gyro || 0}
          </span>
        </div>
        <div style={cubeDisplayStyles.moveList}>
          {recentMoves.length ? recentMoves.map((m, i) => (
            <span key={`${m.timestamp}-${i}`} style={cubeDisplayStyles.moveChip}>{m.move}</span>
          )) : (
            <span style={cubeDisplayStyles.emptyMoves}>No MOVE events yet. Turn a face after connecting.</span>
          )}
        </div>
        <div style={cubeDisplayStyles.eventLog}>
          {recentEvents.length ? recentEvents.map((event, i) => (
            <div key={`${event.timestamp}-${event.type}-${i}`} style={cubeDisplayStyles.eventRow}>
              <span style={cubeDisplayStyles.eventType}>{event.type}</span>
              <span style={cubeDisplayStyles.eventLabel}>{event.label}</span>
              <span style={cubeDisplayStyles.eventDetail}>{event.detail}</span>
            </div>
          )) : (
            <div style={cubeDisplayStyles.emptyMoves}>No cube events received yet.</div>
          )}
        </div>
      </div>
      <div style={cubeDisplayStyles.note}>
        The event log is the source of truth for this POC. If it stays empty after connecting, the app is connected but no GAN events are reaching JavaScript.
      </div>
    </div>
  );
}

const cubeDisplayStyles = {
  wrap: {
    background: 'oklch(14% 0.01 250)',
    border: '1px solid oklch(20% 0.01 250)',
    borderRadius: '8px',
    padding: '14px 16px',
    display: 'flex',
    flexDirection: 'column',
    gap: '10px',
  },
  header: { display: 'flex', alignItems: 'center', gap: '10px' },
  title: {
    fontSize: '12px',
    fontWeight: '700',
    letterSpacing: '0.08em',
    textTransform: 'uppercase',
    color: 'oklch(60% 0.01 250)',
  },
  status: {
    marginLeft: 'auto',
    fontSize: '12px',
    color: 'oklch(42% 0.01 250)',
  },
  playerShell: {
    minHeight: '220px',
    borderRadius: '8px',
    background: 'oklch(10% 0.01 250)',
    overflow: 'hidden',
  },
  playerHost: { width: '100%', height: '220px' },
  diagnostics: {
    display: 'flex',
    flexDirection: 'column',
    gap: '8px',
  },
  diagHeader: {
    display: 'flex',
    alignItems: 'center',
    gap: '10px',
  },
  counts: {
    marginLeft: 'auto',
    fontFamily: "'JetBrains Mono', monospace",
    fontSize: '11px',
    color: 'oklch(50% 0.01 250)',
  },
  moveList: {
    display: 'flex',
    gap: '6px',
    flexWrap: 'wrap',
    minHeight: '28px',
    padding: '8px',
    borderRadius: '6px',
    background: 'oklch(10% 0.01 250)',
  },
  movesLabel: {
    fontFamily: "'JetBrains Mono', monospace",
    fontSize: '10px',
    letterSpacing: '0.10em',
    color: 'oklch(42% 0.01 250)',
    textTransform: 'uppercase',
    marginRight: '4px',
  },
  moveChip: {
    fontFamily: "'JetBrains Mono', monospace",
    fontSize: '12px',
    padding: '2px 7px',
    borderRadius: '4px',
    background: 'oklch(18% 0.06 165)',
    color: 'oklch(65% 0.14 165)',
  },
  emptyMoves: {
    fontSize: '12px',
    color: 'oklch(38% 0.01 250)',
  },
  eventLog: {
    display: 'flex',
    flexDirection: 'column',
    gap: '4px',
    maxHeight: '150px',
    overflowY: 'auto',
    padding: '8px',
    borderRadius: '6px',
    background: 'oklch(10% 0.01 250)',
    border: '1px solid oklch(18% 0.01 250)',
  },
  eventRow: {
    display: 'grid',
    gridTemplateColumns: '72px minmax(80px, 1fr) 1.6fr',
    gap: '8px',
    alignItems: 'baseline',
    fontSize: '11px',
  },
  eventType: {
    fontFamily: "'JetBrains Mono', monospace",
    color: 'oklch(65% 0.14 165)',
    fontWeight: '700',
  },
  eventLabel: {
    color: 'oklch(70% 0.01 250)',
  },
  eventDetail: {
    color: 'oklch(42% 0.01 250)',
    overflow: 'hidden',
    textOverflow: 'ellipsis',
    whiteSpace: 'nowrap',
  },
  fallback: {
    height: '220px',
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    color: 'oklch(42% 0.01 250)',
    fontSize: '13px',
  },
  note: {
    fontSize: '11px',
    lineHeight: 1.4,
    color: 'oklch(38% 0.01 250)',
  },
};

Object.assign(window, { CubeDisplay });
