import { useState, useCallback, useEffect, useRef } from 'react';
import { getMessages } from '../messages/index.js';
import { Keyboard } from './Keyboard.js';

const COLOR_MAP: Record<string, string> = {
  g: '#6aaa64',
  y: '#c9b458',
  x: '#787c7e',
};

const CURSOR_COLOR = '#6aaa64';
const COLOR_CYCLE: Array<'x' | 'y' | 'g'> = ['x', 'y', 'g'];

type CellColor = 'x' | 'y' | 'g';

interface CellState {
  letter: string;
  color: CellColor;
}

interface SolverBoardProps {
  onUpdate: (rows: Array<{ guess: string; result: string }>) => void;
  loading?: boolean;
}

function emptyBoard(): CellState[][] {
  return Array.from({ length: 6 }, () =>
    Array.from({ length: 5 }, () => ({ letter: '', color: 'x' as CellColor })),
  );
}

function buildRows(board: CellState[][]): Array<{ guess: string; result: string }> {
  const rows: Array<{ guess: string; result: string }> = [];
  for (const row of board) {
    if (row.every((c) => c.letter !== '')) {
      rows.push({
        guess: row.map((c) => c.letter).join(''),
        result: row.map((c) => c.color).join(''),
      });
    }
  }
  return rows;
}

function hasPartialRow(board: CellState[][]): boolean {
  for (const row of board) {
    const filled = row.filter((c) => c.letter !== '').length;
    if (filled > 0 && filled < 5) return true;
  }
  return false;
}

export function SolverBoard({ onUpdate, loading }: SolverBoardProps) {
  const [board, setBoard] = useState<CellState[][]>(emptyBoard);
  const [cursor, setCursor] = useState<{ row: number; col: number }>({ row: 0, col: 0 });

  // Refs for latest values used in keyboard handler (stable closure)
  const cursorRef = useRef(cursor);
  cursorRef.current = cursor;
  const boardRef = useRef(board);
  boardRef.current = board;
  const loadingRef = useRef(loading);
  loadingRef.current = loading;

  const partial = hasPartialRow(board);
  const updateDisabled = loading || partial;

  const triggerUpdate = useCallback(() => {
    const b = boardRef.current;
    const r = buildRows(b);
    if (hasPartialRow(b) || loadingRef.current) return;
    onUpdate(r);
  }, [onUpdate]);

  // ── Cell mutation helpers ──

  const setCell = useCallback((row: number, col: number, update: Partial<CellState>) => {
    setBoard((prev) => {
      const next = prev.map((r) => r.map((c) => ({ ...c })));
      if (update.letter !== undefined) next[row][col].letter = update.letter;
      if (update.color !== undefined) next[row][col].color = update.color;
      return next;
    });
  }, []);

  const cycleColor = useCallback((row: number, col: number) => {
    setBoard((prev) => {
      const next = prev.map((r) => r.map((c) => ({ ...c })));
      const current = next[row][col].color;
      const idx = COLOR_CYCLE.indexOf(current);
      next[row][col].color = COLOR_CYCLE[(idx + 1) % COLOR_CYCLE.length];
      return next;
    });
  }, []);

  const moveCursor = useCallback((row: number, col: number) => {
    setCursor({ row: Math.max(0, Math.min(5, row)), col: Math.max(0, Math.min(4, col)) });
  }, []);

  // ── Shared key handler (on-screen keyboard + physical keyboard) ──

  const handleKey = useCallback(
    (key: string) => {
      const { row, col } = cursorRef.current;

      if (key === 'Enter') {
        triggerUpdate();
        return;
      }

      if (key === 'Backspace') {
        setCell(row, col, { letter: '', color: 'x' });
        if (col > 0) {
          moveCursor(row, col - 1);
        } else if (row > 0) {
          moveCursor(row - 1, 4);
        }
        return;
      }

      if (key === 'ArrowLeft') {
        moveCursor(row, col - 1);
        return;
      }
      if (key === 'ArrowRight') {
        moveCursor(row, col + 1);
        return;
      }
      if (key === 'ArrowUp') {
        moveCursor(row - 1, col);
        return;
      }
      if (key === 'ArrowDown') {
        moveCursor(row + 1, col);
        return;
      }

      // Letter key (EN + RU, no ё)
      if (key.length === 1 && /^[a-zA-Zа-яА-Я]$/.test(key) && key.toLowerCase() !== 'ё') {
        const letter = key.toLowerCase();
        setCell(row, col, { letter, color: 'x' });
        if (col < 4) {
          moveCursor(row, col + 1);
        }
      }
    },
    [triggerUpdate, setCell, moveCursor],
  );

  // ── Physical keyboard ──

  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      // Ignore if user is typing in an input field
      if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) return;

      const key = e.key;
      // Only handle single letters and special keys
      if (
        key === 'Enter' ||
        key === 'Backspace' ||
        key.startsWith('Arrow') ||
        (key.length === 1 && /^[a-zA-Zа-яА-Я]$/.test(key) && key.toLowerCase() !== 'ё')
      ) {
        e.preventDefault();
        handleKey(key);
      }
    };

    document.addEventListener('keydown', handleKeyDown);
    return () => document.removeEventListener('keydown', handleKeyDown);
  }, [handleKey]);

  // ── Render ──

  const m = getMessages();

  return (
    <div>
      <style>{`
        @keyframes wl-solver-blink {
          0%, 100% { opacity: 1; }
          50% { opacity: 0; }
        }
      `}</style>

      {/* Grid */}
      <div style={{ display: 'flex', flexDirection: 'column', gap: '4px', alignItems: 'center' }}>
        {board.map((row, rowIdx) => (
          <div key={rowIdx} style={{ display: 'flex', gap: '4px' }}>
            {row.map((cell, colIdx) => {
              const hasLetter = cell.letter !== '';
              const bg = hasLetter ? COLOR_MAP[cell.color] : 'transparent';
              const isFocused = cursor.row === rowIdx && cursor.col === colIdx;

              return (
                <div
                  key={colIdx}
                  onClick={() => {
                    if (isFocused && hasLetter) {
                      cycleColor(rowIdx, colIdx);
                    } else {
                      moveCursor(rowIdx, colIdx);
                    }
                  }}
                  style={{
                    width: '52px',
                    height: '52px',
                    border: `2px solid ${hasLetter ? 'transparent' : '#d3d6da'}`,
                    backgroundColor: bg,
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'center',
                    fontSize: '1.5rem',
                    fontWeight: 'bold',
                    color: hasLetter ? '#fff' : '#000',
                    textTransform: 'uppercase',
                    fontFamily: 'monospace',
                    position: 'relative',
                    cursor: 'pointer',
                    userSelect: 'none',
                  }}
                >
                  {cell.letter}
                  {isFocused && (
                    <div
                      style={{
                        position: 'absolute',
                        bottom: '4px',
                        left: '8px',
                        right: '8px',
                        height: '3px',
                        backgroundColor: CURSOR_COLOR,
                        borderRadius: '1px',
                        animation: 'wl-solver-blink 1s step-end infinite',
                      }}
                    />
                  )}
                </div>
              );
            })}
          </div>
        ))}
      </div>

      {/* Hint */}
      <div
        style={{
          textAlign: 'center',
          marginTop: '10px',
          fontSize: '0.75rem',
          color: '#787c7e',
          fontFamily: 'sans-serif',
        }}
      >
        {m.solver.tapHint}
      </div>

      {/* On-screen keyboard */}
      <Keyboard
        letterColors={{}}
        onKeyPress={handleKey}
        enterDisabled={updateDisabled}
      />
    </div>
  );
}
