import { useState, useEffect, useRef, useCallback } from 'react'
import styles from '../styles/game.module.css'

const WORD_POOL = [
  'the', 'and', 'for', 'are', 'but', 'not', 'you', 'all', 'can', 'her',
  'was', 'one', 'our', 'out', 'day', 'get', 'has', 'him', 'his', 'how',
  'its', 'may', 'new', 'now', 'old', 'see', 'way', 'who', 'did', 'got',
  'let', 'say', 'she', 'too', 'use', 'big', 'cat', 'dog', 'fun', 'hat',
  'jump', 'kick', 'love', 'make', 'nice', 'open', 'play', 'quiz', 'run',
  'star', 'time', 'up', 'very', 'walk', 'xray', 'year', 'zero', 'code',
  'type', 'fast', 'hero', 'epic', 'cool', 'fire', 'bolt', 'zoom', 'dash',
  'pixel', 'blaze', 'storm', 'power', 'quest', 'magic', 'super', 'turbo',
  'cyber', 'ultra', 'royal', 'brave', 'swift', 'light', 'dream', 'shine',
]

type FallingWord = {
  id: number
  text: string
  x: number
  y: number
  speed: number
  matched: number // how many chars matched
}

type Explosion = {
  id: number
  text: string
  x: number
  y: number
  points: number
}

type Particle = {
  id: number
  x: number
  y: number
  tx: number
  ty: number
  color: string
  duration: number
}

const PARTICLE_COLORS = ['#2ecc71', '#27ae60', '#7c6ff7', '#f1c40f', '#e84393', '#3498db', '#00d2d3']

function spawnParticles(x: number, y: number, count: number): Particle[] {
  return Array.from({ length: count }, (_, i) => {
    const angle = (Math.PI * 2 * i) / count + (Math.random() - 0.5) * 0.5
    const dist = 40 + Math.random() * 80
    return {
      id: Date.now() + i,
      x,
      y,
      tx: Math.cos(angle) * dist,
      ty: Math.sin(angle) * dist,
      color: PARTICLE_COLORS[Math.floor(Math.random() * PARTICLE_COLORS.length)],
      duration: 0.4 + Math.random() * 0.3,
    }
  })
}

type Props = {
  highScore: number
  onGameOver: (score: number) => void
}

export function GameMode({ highScore, onGameOver }: Props) {
  const [words, setWords] = useState<FallingWord[]>([])
  const [input, setInput] = useState('')
  const inputRef = useRef('')
  const [score, setScore] = useState(0)
  const [lives, setLives] = useState(3)
  const [gameOver, setGameOver] = useState(false)
  const [started, setStarted] = useState(false)
  const [focused, setFocused] = useState(false)
  const [explosions, setExplosions] = useState<Explosion[]>([])
  const [particles, setParticles] = useState<Particle[]>([])
  const [flash, setFlash] = useState(0)
  const [combo, setCombo] = useState(0)
  const [showCombo, setShowCombo] = useState(0)
  const comboTimerRef = useRef<ReturnType<typeof setTimeout>>(undefined)
  const containerRef = useRef<HTMLDivElement>(null)
  const nextIdRef = useRef(0)
  const frameRef = useRef<number>(0)
  const lastSpawnRef = useRef(0)
  const difficultyRef = useRef(1)
  const livesRef = useRef(3)
  const gameOverRef = useRef(false)

  livesRef.current = lives
  gameOverRef.current = gameOver

  const spawnWord = useCallback(() => {
    const difficulty = difficultyRef.current
    const maxLen = Math.min(3 + Math.floor(difficulty / 3), 7)
    const pool = WORD_POOL.filter(w => w.length <= maxLen)
    const text = pool[Math.floor(Math.random() * pool.length)]
    const word: FallingWord = {
      id: nextIdRef.current++,
      text,
      x: Math.random() * 70 + 5, // 5%-75% from left
      y: -5,
      speed: 0.3 + difficulty * 0.08,
      matched: 0,
    }
    setWords(prev => [...prev, word])
  }, [])

  const startGame = () => {
    setWords([])
    updateInput('')
    setScore(0)
    setLives(3)
    setGameOver(false)
    setStarted(true)
    setExplosions([])
    setParticles([])
    setCombo(0)
    difficultyRef.current = 1
    lastSpawnRef.current = 0
    nextIdRef.current = 0
    containerRef.current?.focus()
  }

  // Game loop
  useEffect(() => {
    if (!started || gameOver) return

    let lastTime = performance.now()

    const tick = (now: number) => {
      if (gameOverRef.current) return
      const dt = (now - lastTime) / 16.67 // normalize to ~60fps
      lastTime = now

      // Spawn
      const spawnInterval = Math.max(1500 - difficultyRef.current * 80, 600)
      if (now - lastSpawnRef.current > spawnInterval) {
        spawnWord()
        lastSpawnRef.current = now
      }

      // Move words
      setWords(prev => {
        const next: FallingWord[] = []
        let lostLife = false
        for (const w of prev) {
          const ny = w.y + w.speed * dt
          if (ny > 100) {
            lostLife = true
          } else {
            next.push({ ...w, y: ny })
          }
        }
        if (lostLife) {
          setLives(l => {
            const nl = l - 1
            if (nl <= 0) {
              setGameOver(true)
            }
            return nl
          })
        }
        return next
      })

      // Increase difficulty
      difficultyRef.current = 1 + score / 50

      frameRef.current = requestAnimationFrame(tick)
    }

    frameRef.current = requestAnimationFrame(tick)
    return () => cancelAnimationFrame(frameRef.current)
  }, [started, gameOver, spawnWord, score])

  // Fire onGameOver
  useEffect(() => {
    if (gameOver && started) {
      onGameOver(score)
    }
  }, [gameOver, started, score, onGameOver])

  const updateInput = (val: string) => {
    inputRef.current = val
    setInput(val)
  }

  const handleKeyDown = (e: React.KeyboardEvent) => {
    if (gameOver) return
    if (!started) {
      startGame()
      return
    }

    if (e.key === 'Backspace') {
      const newInput = inputRef.current.slice(0, -1)
      updateInput(newInput)
      setWords(prev => prev.map(w => ({
        ...w,
        matched: w.text.startsWith(newInput) && newInput.length > 0 ? newInput.length : 0,
      })))
      return
    }

    if (e.key.length !== 1) return
    e.preventDefault()

    const newInput = inputRef.current + e.key

    // Do matching + removal in one atomic setWords call
    setWords(prev => {
      const completed = prev.find(w => w.text === newInput)
      if (completed) {
        const points = completed.text.length * 10
        setScore(s => s + points)
        updateInput('')

        // Spawn explosion at word position
        const now = Date.now()
        setExplosions(ex => [...ex, {
          id: now,
          text: completed.text,
          x: completed.x,
          y: completed.y,
          points,
        }])
        // Spawn particles
        setParticles(p => [...p, ...spawnParticles(completed.x, completed.y, 12)])
        // Screen flash
        setFlash(now)
        // Combo tracking
        setCombo(c => {
          const next = c + 1
          if (next >= 3) setShowCombo(now)
          return next
        })
        clearTimeout(comboTimerRef.current)
        comboTimerRef.current = setTimeout(() => setCombo(0), 2000)

        // Auto-clean effects after animation
        setTimeout(() => {
          setExplosions(ex => ex.filter(e => e.id !== now))
        }, 500)
        setTimeout(() => {
          setParticles(p => p.slice(-24))
        }, 800)

        return prev.filter(w => w.id !== completed.id)
      }
      // No completion — update partial matches
      updateInput(newInput)
      return prev.map(w => ({
        ...w,
        matched: w.text.startsWith(newInput) ? newInput.length : 0,
      }))
    })
  }

  return (
    <div className="fade-in">
      <div style={{ marginBottom: 16, display: 'flex', alignItems: 'center', gap: 16 }}>
        <h2 style={{ fontSize: 20, fontWeight: 700 }}>Falling Words</h2>
        <span style={{ color: 'var(--text-dim)', fontSize: 14 }}>
          High Score: {highScore}
        </span>
        {started && !gameOver && (
          <button onClick={startGame} style={{ marginLeft: 'auto' }}>Restart</button>
        )}
      </div>

      <div
        ref={containerRef}
        className={`${styles.gameContainer} ${!focused ? styles.blurred : ''}`}
        tabIndex={0}
        onKeyDown={handleKeyDown}
        onFocus={() => setFocused(true)}
        onBlur={() => setFocused(false)}
      >
        <div className={styles.gameHud}>
          <div className={styles.hudItem}>
            <span className={styles.hudLabel}>Score</span>
            <span className={styles.hudValue}>{score}</span>
          </div>
          <div className={styles.hudItem}>
            <span className={styles.hudLabel}>Lives</span>
            <span className={`${styles.hudValue} ${styles.lives}`}>
              {'❤️'.repeat(Math.max(0, lives))}{'🖤'.repeat(Math.max(0, 3 - lives))}
            </span>
          </div>
        </div>

        {words.map(w => (
          <div
            key={w.id}
            className={`${styles.word} ${w.matched > 0 ? styles.wordMatched : ''}`}
            style={{ left: `${w.x}%`, top: `${w.y}%` }}
          >
            {w.text.split('').map((ch, i) => (
              <span key={i} className={i < w.matched ? styles.wordMatchedChar : ''}>
                {ch}
              </span>
            ))}
          </div>
        ))}

        {/* Exploding words */}
        {explosions.map(ex => (
          <div
            key={ex.id}
            className={`${styles.word} ${styles.wordExploding}`}
            style={{ left: `${ex.x}%`, top: `${ex.y}%` }}
          >
            {ex.text}
          </div>
        ))}

        {/* Particles */}
        {particles.map(p => (
          <div
            key={p.id}
            className={styles.particle}
            style={{
              left: `${p.x}%`,
              top: `${p.y}%`,
              background: p.color,
              boxShadow: `0 0 6px ${p.color}, 0 0 12px ${p.color}`,
              '--tx': `${p.tx}px`,
              '--ty': `${p.ty}px`,
              '--duration': `${p.duration}s`,
            } as React.CSSProperties}
          />
        ))}

        {/* Score popups */}
        {explosions.map(ex => (
          <div
            key={`score-${ex.id}`}
            className={styles.scorePopup}
            style={{ left: `${ex.x + 3}%`, top: `${ex.y - 2}%` }}
          >
            +{ex.points}
          </div>
        ))}

        {/* Screen flash */}
        {flash > 0 && <div key={flash} className={styles.screenFlash} />}

        {/* Combo text */}
        {showCombo > 0 && combo >= 3 && (
          <div key={showCombo} className={styles.comboText}>
            {combo}x COMBO!
          </div>
        )}

        <div className={styles.dangerZone} />

        {started && !gameOver && (
          <div className={styles.inputDisplay}>
            {input || <span style={{ opacity: 0.3 }}>type a word...</span>}
          </div>
        )}

        {!started && (
          <div className={styles.gameOver}>
            <div className={styles.gameOverTitle}>Falling Words</div>
            <div className={styles.gameOverScore}>
              Type the words before they fall!
            </div>
            <button className={styles.gameOverButtons} onClick={startGame}
              style={{ background: 'var(--accent)', color: '#fff', fontWeight: 600, fontSize: 18, padding: '14px 36px' }}>
              Start Game
            </button>
          </div>
        )}

        {gameOver && (
          <div className={styles.gameOver}>
            <div className={styles.gameOverTitle}>Game Over!</div>
            <div className={styles.gameOverScore}>Score: {score}</div>
            {score > highScore && score > 0 && (
              <div className={styles.highScore}>New High Score!</div>
            )}
            <div className={styles.gameOverButtons}>
              <button
                onClick={startGame}
                style={{ background: 'var(--accent)', color: '#fff', fontWeight: 600, fontSize: 16, padding: '12px 28px' }}
              >
                Play Again
              </button>
            </div>
          </div>
        )}
      </div>
    </div>
  )
}
