"use client";

import type { MouseEvent } from "react";
import { useEffect, useMemo, useRef, useState } from "react";

import { Button } from "@/components/ui/button";

function createGrid(cols: number, rows: number) {
  return Array.from({ length: rows }, () => Array.from({ length: cols }, () => 0));
}

function seedRandom(grid: number[][], density: number) {
  for (let y = 0; y < grid.length; y += 1) {
    for (let x = 0; x < grid[0].length; x += 1) {
      grid[y][x] = Math.random() < density ? 1 : 0;
    }
  }
}

function stepGrid(grid: number[][]) {
  const rows = grid.length;
  const cols = grid[0]?.length ?? 0;
  const next = createGrid(cols, rows);

  for (let y = 0; y < rows; y += 1) {
    const yPrev = (y - 1 + rows) % rows;
    const yNext = (y + 1) % rows;
    for (let x = 0; x < cols; x += 1) {
      const xPrev = (x - 1 + cols) % cols;
      const xNext = (x + 1) % cols;
      const neighbors =
        grid[yPrev][xPrev] +
        grid[yPrev][x] +
        grid[yPrev][xNext] +
        grid[y][xPrev] +
        grid[y][xNext] +
        grid[yNext][xPrev] +
        grid[yNext][x] +
        grid[yNext][xNext];

      if (grid[y][x]) {
        next[y][x] = neighbors === 2 || neighbors === 3 ? 1 : 0;
      } else {
        next[y][x] = neighbors === 3 ? 1 : 0;
      }
    }
  }

  return next;
}

export function GameOfLifeMini() {
  const canvasRef = useRef<HTMLCanvasElement | null>(null);
  const [running, setRunning] = useState(true);
  const [speed, setSpeed] = useState(6);
  const cellSize = 10;
  const width = 420;
  const height = 260;

  const { rows, cols } = useMemo(
    () => ({
      cols: Math.floor(width / cellSize),
      rows: Math.floor(height / cellSize),
    }),
    [],
  );

  const gridRef = useRef<number[][]>(createGrid(cols, rows));

  useEffect(() => {
    gridRef.current = createGrid(cols, rows);
    seedRandom(gridRef.current, 0.22);
  }, [cols, rows]);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    if (!ctx) return;

    let raf = 0;
    let last = performance.now();
    const tickMs = 1000 / speed;

    const draw = () => {
      ctx.clearRect(0, 0, width, height);
      ctx.fillStyle = "#141414";
      ctx.fillRect(0, 0, width, height);

      const grid = gridRef.current;
      ctx.fillStyle = "#f2f2f2";
      for (let y = 0; y < rows; y += 1) {
        for (let x = 0; x < cols; x += 1) {
          if (grid[y][x]) {
            ctx.fillRect(
              x * cellSize,
              y * cellSize,
              cellSize - 1,
              cellSize - 1,
            );
          }
        }
      }
    };

    const loop = (now: number) => {
      if (running && now - last >= tickMs) {
        gridRef.current = stepGrid(gridRef.current);
        last = now;
      }
      draw();
      raf = requestAnimationFrame(loop);
    };

    raf = requestAnimationFrame(loop);
    return () => cancelAnimationFrame(raf);
  }, [running, speed, cols, rows]);

  const handleToggleCell = (event: MouseEvent<HTMLCanvasElement>) => {
    const rect = event.currentTarget.getBoundingClientRect();
    const x = Math.floor((event.clientX - rect.left) / cellSize);
    const y = Math.floor((event.clientY - rect.top) / cellSize);
    if (x < 0 || y < 0 || y >= rows || x >= cols) return;
    gridRef.current[y][x] = gridRef.current[y][x] ? 0 : 1;
  };

  return (
    <div className="space-y-3">
      <div className="flex items-center justify-between">
        <div>
          <div className="text-sm font-semibold uppercase tracking-wide text-muted-foreground">
            Game of Life
          </div>
          <div className="text-xs text-muted-foreground">
            Click to toggle cells. Space-time improvisation.
          </div>
        </div>
        <div className="flex items-center gap-2">
          <Button
            size="sm"
            variant={running ? "secondary" : "default"}
            onClick={() => setRunning((prev) => !prev)}
          >
            {running ? "Pause" : "Play"}
          </Button>
          <Button
            size="sm"
            variant="outline"
            onClick={() => {
              gridRef.current = createGrid(cols, rows);
            }}
          >
            Clear
          </Button>
          <Button
            size="sm"
            variant="outline"
            onClick={() => {
              gridRef.current = createGrid(cols, rows);
              seedRandom(gridRef.current, 0.22);
            }}
          >
            Randomize
          </Button>
        </div>
      </div>

      <div className="rounded-2xl border border-border/60 bg-background/60 p-3 shadow-sm">
        <canvas
          ref={canvasRef}
          width={width}
          height={height}
          onClick={handleToggleCell}
          className="h-65 w-full rounded-xl border border-border/40 bg-black"
        />
      </div>

      <div className="flex items-center gap-2 text-xs text-muted-foreground">
        <span>Speed</span>
        <div className="flex items-center gap-2">
          <Button
            size="sm"
            variant="ghost"
            onClick={() => setSpeed((prev) => Math.max(2, prev - 1))}
          >
            -
          </Button>
          <span className="min-w-6 text-center tabular-nums">{speed}</span>
          <Button
            size="sm"
            variant="ghost"
            onClick={() => setSpeed((prev) => Math.min(12, prev + 1))}
          >
            +
          </Button>
        </div>
      </div>
    </div>
  );
}
