/* MAZE GAME — guide the two characters together, randomized positions each game */
const { useState, useEffect, useRef, useCallback, useMemo } = React;

/* Maze layout: 0 = wall (cream paper), 1 = path (pink channel) */
const MAZE = [
  [0,0,1,1,1,0,0,1,0,1,1,0],
  [0,0,1,0,1,0,0,1,0,1,0,0],
  [0,1,1,0,1,0,0,1,0,1,1,1],
  [0,1,0,0,1,1,1,1,0,0,0,1],
  [0,1,0,0,0,0,0,0,0,1,1,1],
  [0,1,1,1,1,1,0,0,0,1,0,0],
  [0,0,0,0,0,1,0,1,1,1,0,0],
  [0,1,1,1,0,1,0,1,0,1,1,1],
  [0,1,0,1,0,1,1,1,0,0,0,1],
  [0,1,0,1,1,1,0,1,1,1,1,1],
  [0,1,0,0,0,0,0,0,0,0,0,0],
  [0,1,1,1,1,1,1,1,1,1,0,0],
  [0,0,0,0,0,0,0,0,0,1,0,0],
  [0,0,0,0,0,0,0,0,0,1,1,0],
];

const ROWS = MAZE.length;
const COLS = MAZE[0].length;

/* Collect path cells */
const PATH_CELLS = (() => {
  const cells = [];
  for (let r = 0; r < ROWS; r++)
    for (let c = 0; c < COLS; c++)
      if (MAZE[r][c] === 1) cells.push({ r, c });
  return cells;
})();

/* Pick a random pair of path cells that are far apart (Manhattan distance) */
function randomPair() {
  let best = { dist: 0, a: PATH_CELLS[0], b: PATH_CELLS[1] };
  for (let i = 0; i < 8; i++) {
    const a = PATH_CELLS[Math.floor(Math.random() * PATH_CELLS.length)];
    const b = PATH_CELLS[Math.floor(Math.random() * PATH_CELLS.length)];
    const d = Math.abs(a.r - b.r) + Math.abs(a.c - b.c);
    if (d > best.dist) best = { dist: d, a, b };
  }
  return { start: best.a, end: best.b };
}

function MazeGame({ onWin }) {
  const initial = useMemo(() => randomPair(), []);
  const [start, setStart] = useState(initial.start);
  const [end, setEnd] = useState(initial.end);
  const [pos, setPos] = useState(initial.start);
  const [trail, setTrail] = useState([`${initial.start.r},${initial.start.c}`]);
  const [moves, setMoves] = useState(0);
  const [won, setWon] = useState(false);
  const boardRef = useRef(null);
  const [cell, setCell] = useState(38);

  useEffect(() => {
    const update = () => {
      if (!boardRef.current) return;
      const w = boardRef.current.clientWidth;
      setCell(w / COLS);
    };
    update();
    window.addEventListener("resize", update);
    return () => window.removeEventListener("resize", update);
  }, []);

  const tryMove = useCallback((dr, dc) => {
    if (won) return;
    setPos((cur) => {
      const nr = cur.r + dr, nc = cur.c + dc;
      if (nr < 0 || nr >= ROWS || nc < 0 || nc >= COLS) return cur;
      if (MAZE[nr][nc] === 0) return cur;
      const key = `${nr},${nc}`;
      setTrail((t) => (t.includes(key) ? t : [...t, key]));
      setMoves((m) => m + 1);
      if (nr === end.r && nc === end.c) {
        setWon(true);
        setTimeout(() => onWin && onWin(), 700);
      }
      return { r: nr, c: nc };
    });
  }, [won, onWin, end]);

  // keyboard
  useEffect(() => {
    const onKey = (e) => {
      if (["ArrowUp", "w", "W"].includes(e.key)) { e.preventDefault(); tryMove(-1, 0); }
      else if (["ArrowDown", "s", "S"].includes(e.key)) { e.preventDefault(); tryMove(1, 0); }
      else if (["ArrowLeft", "a", "A"].includes(e.key)) { e.preventDefault(); tryMove(0, -1); }
      else if (["ArrowRight", "d", "D"].includes(e.key)) { e.preventDefault(); tryMove(0, 1); }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [tryMove]);

  // touch swipe
  useEffect(() => {
    const el = boardRef.current;
    if (!el) return;
    let sx = 0, sy = 0, active = false;
    const onStart = (e) => {
      const t = e.touches ? e.touches[0] : e;
      sx = t.clientX; sy = t.clientY; active = true;
    };
    const onEnd = (e) => {
      if (!active) return;
      active = false;
      const t = e.changedTouches ? e.changedTouches[0] : e;
      const dx = t.clientX - sx, dy = t.clientY - sy;
      const TH = 22;
      if (Math.abs(dx) < TH && Math.abs(dy) < TH) return;
      if (Math.abs(dx) > Math.abs(dy)) tryMove(0, dx > 0 ? 1 : -1);
      else tryMove(dy > 0 ? 1 : -1, 0);
    };
    el.addEventListener("touchstart", onStart, { passive: true });
    el.addEventListener("touchend", onEnd);
    return () => {
      el.removeEventListener("touchstart", onStart);
      el.removeEventListener("touchend", onEnd);
    };
  }, [tryMove]);

  /* New randomized game */
  const reset = () => {
    const { start: s, end: e } = randomPair();
    setStart(s);
    setEnd(e);
    setPos(s);
    setTrail([`${s.r},${s.c}`]);
    setMoves(0);
    setWon(false);
  };

  const boardStyle = {
    gridTemplateColumns: `repeat(${COLS}, 1fr)`,
    gridTemplateRows: `repeat(${ROWS}, 1fr)`,
  };

  const charSize = Math.min(60, Math.max(30, cell * 1.55));

  return (
    <div className="game-area">
      <div className="maze-card">
        <div className="maze-board" ref={boardRef} style={boardStyle}>
          {MAZE.flatMap((row, r) =>
            row.map((v, c) => {
              const key = `${r},${c}`;
              const isPath = v === 1;
              const isTrail = trail.includes(key);
              return (
                <div key={key} className={`maze-cell ${isPath ? "path" : ""}`}>
                  {isTrail && isPath && (
                    <span className="trail-heart" />
                  )}
                </div>
              );
            })
          )}
          {/* End character (the one being reached) */}
          <div className="target" style={{
            width: charSize, height: charSize,
            left: end.c * cell + cell / 2 - charSize / 2,
            top:  end.r * cell + cell / 2 - charSize / 2,
          }}>
            <YouChar size={charSize} />
          </div>
          {/* Player character */}
          <div className="runner" style={{
            width: charSize, height: charSize,
            left: pos.c * cell + cell / 2 - charSize / 2,
            top:  pos.r * cell + cell / 2 - charSize / 2,
          }}>
            <MeChar size={charSize} />
          </div>
          {won && (
            <div className="win-veil">
              <div>
                <div className="win-heart">♥</div>
                <div className="win-title">Together at last</div>
                <div className="win-sub">Unlocking the personal notes…</div>
              </div>
            </div>
          )}
        </div>
      </div>

      <div className="maze-side">
        <div className="maze-stat">
          <div className="l">Moves</div>
          <div className="v">{moves}</div>
        </div>
        <div className="maze-stat">
          <div className="l">How to play</div>
          <div className="hint-text">
            Tap the arrows or swipe over the maze. Bring the two together — start and end change every game.
          </div>
        </div>
        <div className="controls-pad">
          <button className="pad-up"    onClick={() => tryMove(-1, 0)} aria-label="up">↑</button>
          <button className="pad-left"  onClick={() => tryMove(0, -1)} aria-label="left">←</button>
          <button className="pad-mid"   onClick={reset}>NEW</button>
          <button className="pad-right" onClick={() => tryMove(0, 1)} aria-label="right">→</button>
          <button className="pad-down"  onClick={() => tryMove(1, 0)} aria-label="down">↓</button>
        </div>
      </div>
    </div>
  );
}

window.MazeGame = MazeGame;
