import { useEffect, useMemo, useState } from 'react';
import { RotateCcw } from 'lucide-react';

import type { DemoModule } from '@/lib/demo-kit';
import { cn } from '@/lib/utils';

import * as st from '@/content/styles';

/**
 * The visitor's own attempt, on the same seed as the run beside it.
 *
 * Generic over the demo: it knows only `interactive.init`, `interactive.Controls`
 * and `Surface` from the contract, so a demo that ships an interactive mode gets
 * this for free and one that does not renders nothing rather than a broken pane.
 *
 * The seed is the shared coordinate. Both boards derive from it, which is what
 * makes "you and the model got the same word" a fact about the page rather than
 * a sentence on it.
 */
export function PlayYourself<TState>({
  demo,
  seed,
  className,
}: {
  demo: DemoModule<TState>;
  seed: number;
  className?: string;
}) {
  const interactive = demo.interactive;
  const Surface = demo.Surface;

  // `init` is pure and seeded, so remounting on a seed change is the whole of
  // "start a new game" — there is no other state to reset.
  const initial = useMemo(
    () => (interactive ? interactive.init(seed) : null),
    [interactive, seed],
  );
  const [state, setState] = useState<TState | null>(initial);
  const [generation, setGeneration] = useState(0);

  useEffect(() => setState(initial), [initial]);

  if (!interactive || state === null) return null;
  const Controls = interactive.Controls;

  return (
    // Capped, not full-bleed. The keyboard is a grid of flex rows, so an
    // unconstrained parent stretches it to the page width and the keys drift
    // far from the board they belong to.
    <div className={cn('w-full max-w-md space-y-3', className)}>
      <div className="flex items-baseline justify-between gap-3">
        <h3 className={st.h3}>Your attempt</h3>
        <button
          type="button"
          onClick={() => {
            setState(interactive.init(seed));
            setGeneration((g) => g + 1);
          }}
          className="inline-flex items-center gap-1.5 rounded-md px-2 py-1 text-xs text-muted transition-colors duration-1 hover:bg-surface-2 hover:text-fg"
        >
          <RotateCcw aria-hidden="true" className="size-3.5" />
          Start over
        </button>
      </div>

      <div className="card w-fit p-4">
        <Surface state={state} />
      </div>

      {/* Remounting on `generation` clears any state the controls hold of their
          own — a half-typed word survives a reset otherwise, and the board and
          the keyboard then disagree about what is on the current row. */}
      <Controls key={generation} state={state} onChange={setState} seed={seed} />
    </div>
  );
}

export default PlayYourself;
