import React, { useState, useEffect, useRef } from 'react'
import { motion, AnimatePresence } from 'framer-motion'

interface Ship {
  x: number
  y: number
  angle: number
  velocity: { x: number; y: number }
  rotationSpeed: number
  score: number
  thrust: boolean
  shieldActive: boolean
  shieldEnergy: number
  invulnerable: boolean
  shooting: boolean
}

interface Bullet {
  x: number
  y: number
  angle: number
  velocity: { x: number; y: number }
  life: number
}

interface Particle {
  x: number
  y: number
  velocity: { x: number; y: number }
  life: number
  color: string
  size: number
}

const CANVAS_WIDTH = 800
const CANVAS_HEIGHT = 600
const STAR_RADIUS = 25
const GRAVITY_CONSTANT = 70
const THRUST_POWER = 0.2
const ROTATION_SPEED = 0.1
const BULLET_SPEED = 7
const BULLET_LIFE = 60
const BULLET_LENGTH = 20
const RESPAWN_TIME = 180
const MAX_PARTICLES = 200
const SHIELD_RECHARGE_RATE = 0.2
const SHIELD_DRAIN_RATE = 1
const MAX_SHIELD_ENERGY = 100
const MAX_SHIP_SPEED = 5
const INVULNERABILITY_TIME = 180 // 3 seconds at 60 FPS

export default function Component() {
  const [input, setInput] = useState('')
  const [output, setOutput] = useState(['Welcome to the Retro Terminal', 'Type "help" for available commands.'])
  const [isLoggedIn, setIsLoggedIn] = useState(false)
  const [username, setUsername] = useState('')
  const [loginStep, setLoginStep] = useState('username')
  const [isOn, setIsOn] = useState(true)
  const [isGameRunning, setIsGameRunning] = useState(false)
  const terminalRef = useRef<HTMLDivElement>(null)
  const canvasRef = useRef<HTMLCanvasElement>(null)
  const [ship1, setShip1] = useState<Ship>({ 
    x: 200, y: 300, angle: Math.PI / 2, velocity: { x: 0, y: 0 }, 
    rotationSpeed: 0, score: 0, thrust: false, 
    shieldActive: false, shieldEnergy: MAX_SHIELD_ENERGY, invulnerable: false, shooting: false
  })
  const [ship2, setShip2] = useState<Ship>({ 
    x: 600, y: 300, angle: 3 * Math.PI / 2, velocity: { x: 0, y: 0 }, 
    rotationSpeed: 0, score: 0, thrust: false, 
    shieldActive: false, shieldEnergy: MAX_SHIELD_ENERGY, invulnerable: false, shooting: false
  })
  const [bullets1, setBullets1] = useState<Bullet[]>([])
  const [bullets2, setBullets2] = useState<Bullet[]>([])
  const [particles, setParticles] = useState<Particle[]>([])
  const [respawnTimer1, setRespawnTimer1] = useState(0)
  const [respawnTimer2, setRespawnTimer2] = useState(0)

  useEffect(() => {
    if (terminalRef.current) {
      terminalRef.current.scrollTop = terminalRef.current.scrollHeight
    }
  }, [output])

  useEffect(() => {
    if (isGameRunning) {
      const canvas = canvasRef.current
      const ctx = canvas?.getContext('2d')
      if (!ctx) return

      const gameLoop = setInterval(() => {
        updateGame()
        drawGame(ctx)
      }, 1000 / 60) // 60 FPS

      return () => clearInterval(gameLoop)
    }
  }, [isGameRunning, ship1, ship2, bullets1, bullets2, particles])

  const handleInput = (e: React.ChangeEvent<HTMLInputElement>) => {
    setInput(e.target.value)
  }

  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault()
    if (input.trim() === '') return

    const newOutput = [...output, `> ${input}`]
    
    if (loginStep === 'username') {
      newOutput.push(processLogin(input))
    } else if (loginStep === 'password') {
      newOutput.push(processPassword(input))
    } else if (loginStep === 'create') {
      newOutput.push(processCreateAccount(input))
    } else {
      newOutput.push(processCommand(input))
    }

    setOutput(newOutput)
    setInput('')
  }

  const processLogin = (username: string) => {
    setUsername(username)
    setLoginStep('password')
    return `Enter password for ${username}:`
  }

  const processPassword = (password: string) => {
    if (password === 'password') {
      setIsLoggedIn(true)
      setLoginStep('')
      return `Welcome, ${username}!`
    } else {
      setLoginStep('create')
      return 'Account not found. Create new account? (y/n)'
    }
  }

  const processCreateAccount = (response: string) => {
    if (response.toLowerCase() === 'y') {
      setIsLoggedIn(true)
      setLoginStep('')
      return `Account created for ${username}. Welcome!`
    } else {
      setLoginStep('username')
      setUsername('')
      return 'Account creation cancelled. Please login or create an account.'
    }
  }

  const processCommand = (cmd: string) => {
    const lowerCmd = cmd.toLowerCase().trim()
    switch (lowerCmd) {
      case 'help':
        return `Available commands:
  help - Show this help message
  clear - Clear the terminal
  echo [message] - Display a message
  date - Show current date and time
  login - Log into your account
  logout - Log out of your account
  whoami - Display current user
  exit - Turn off the terminal
  space wars - Launch Space Wars game
${isLoggedIn ? '  secret - Access secret information' : ''}`
      case 'clear':
        setOutput([])
        return ''
      case 'date':
        return new Date().toLocaleString()
      case 'login':
        if (isLoggedIn) {
          return 'You are already logged in.'
        }
        setLoginStep('username')
        return 'Enter username:'
      case 'logout':
        if (!isLoggedIn) {
          return 'You are not logged in.'
        }
        setIsLoggedIn(false)
        setUsername('')
        return 'You have been logged out.'
      case 'whoami':
        return isLoggedIn ? username : 'You are not logged in.'
      case 'secret':
        return isLoggedIn ? 'The secret is: 42' : 'You must be logged in to access secret information.'
      case 'exit':
        setIsOn(false)
        return 'Shutting down...'
      case 'space wars':
        setIsGameRunning(true)
        return 'Launching Space Wars...'
      default:
        if (lowerCmd.startsWith('echo ')) {
          return lowerCmd.slice(5)
        }
        return `Command not found: ${cmd}`
    }
  }

  const updateGame = () => {
    // Update ship positions and apply gravity
    const updateShip = (ship: Ship): Ship => {
      if (ship.x === -1 && ship.y === -1) return ship // Skip update if ship is destroyed

      // Apply gravity
      const dx = CANVAS_WIDTH / 2 - ship.x
      const dy = CANVAS_HEIGHT / 2 - ship.y
      const distanceSquared = dx * dx + dy * dy
      const gravityForce = GRAVITY_CONSTANT / distanceSquared

      ship.velocity.x += gravityForce * dx / Math.sqrt(distanceSquared)
      ship.velocity.y += gravityForce * dy / Math.sqrt(distanceSquared)

      // Apply thrust
      if (ship.thrust) {
        ship.velocity.x += Math.cos(ship.angle) * THRUST_POWER
        ship.velocity.y += Math.sin(ship.angle) * THRUST_POWER
      }

      // Update position
      ship.x = (ship.x + ship.velocity.x + CANVAS_WIDTH) % CANVAS_WIDTH
      ship.y = (ship.y + ship.velocity.y + CANVAS_HEIGHT) % CANVAS_HEIGHT

      // Apply rotation
      ship.angle += ship.rotationSpeed

      // Update shield energy
      if (ship.shieldActive && ship.shieldEnergy > 0 && !ship.shooting) {
        ship.shieldEnergy = Math.max(0, ship.shieldEnergy - SHIELD_DRAIN_RATE)
      } else if (!ship.shieldActive && ship.shieldEnergy < MAX_SHIELD_ENERGY) {
        ship.shieldEnergy = Math.min(MAX_SHIELD_ENERGY, ship.shieldEnergy + SHIELD_RECHARGE_RATE)
      }

      return ship
    }

    setShip1(prevShip => updateShip({ ...prevShip }))
    setShip2(prevShip => updateShip({ ...prevShip }))

    // Update bullets
    const updateBullets = (bullets: Bullet[]): Bullet[] => {
      return bullets
        .map(bullet => ({
          ...bullet,
          x: (bullet.x + bullet.velocity.x + CANVAS_WIDTH) % CANVAS_WIDTH,
          y: (bullet.y + bullet.velocity.y + CANVAS_HEIGHT) % CANVAS_HEIGHT,
          life: bullet.life - 1,
        }))
        .filter(bullet => bullet.life > 0)
    }

    setBullets1(prevBullets => updateBullets(prevBullets))
    setBullets2(prevBullets => updateBullets(prevBullets))

    // Update particles
    setParticles(prev => 
      prev
        .map(particle => ({
          ...particle,
          x: particle.x + particle.velocity.x,
          y: particle.y + particle.velocity.y,
          life: particle.life - 1,
        }))
        .filter(particle => particle.life > 0)
    )

    // Check collisions
    const checkCollisions = () => {
      // Ship-Star collisions
      const checkShipStarCollision = (ship: Ship) => {
        const dx = ship.x - CANVAS_WIDTH / 2
        const dy = ship.y - CANVAS_HEIGHT / 2
        return Math.sqrt(dx * dx + dy * dy) < STAR_RADIUS
      }

      if (checkShipStarCollision(ship1) && !ship1.shieldActive && !ship1.invulnerable) {
        setShip1(prev => ({ ...prev, x: -1, y: -1 }))
        setRespawnTimer1(RESPAWN_TIME)
        setShip2(prev => ({ ...prev, score: prev.score + 1 }))
        createExplosion(ship1.x, ship1.y)
      }

      if (checkShipStarCollision(ship2) && !ship2.shieldActive && !ship2.invulnerable) {
        setShip2(prev => ({ ...prev, x: -1, y: -1 }))
        setRespawnTimer2(RESPAWN_TIME)
        setShip1(prev => ({ ...prev, score: prev.score + 1 }))
        createExplosion(ship2.x, ship2.y)
      }

      // Bullet-Ship collisions
      const checkBulletShipCollision = (bullet: Bullet, ship: Ship) => {
        const dx = bullet.x - ship.x
        const dy = bullet.y - ship.y
        return Math.sqrt(dx * dx + dy * dy) < 10 // Reduced collision radius for smaller ships
      }

      bullets1.forEach(bullet => {
        if (checkBulletShipCollision(bullet, ship2) && !ship2.shieldActive && !ship2.invulnerable) {
          setShip2(prev => ({ ...prev, x: -1, y: -1 }))
          setRespawnTimer2(RESPAWN_TIME)
          setShip1(prev => ({ ...prev, score: prev.score + 1 }))
          createExplosion(ship2.x, ship2.y)
        }
      })

      bullets2.forEach(bullet => {
        if (checkBulletShipCollision(bullet, ship1) && !ship1.shieldActive && !ship1.invulnerable) {
          setShip1(prev => ({ ...prev, x: -1, y: -1 }))
          setRespawnTimer1(RESPAWN_TIME)
          setShip2(prev => ({ ...prev, score: prev.score + 1 }))
          createExplosion(ship1.x, ship1.y)
        }
      })
    }

    checkCollisions()

    // Handle respawning and invulnerability
    if (respawnTimer1 > 0) {
      setRespawnTimer1(prev => prev - 1)
      if (respawnTimer1 === 1) {
        setShip1(prev => ({ 
          ...prev, 
          x: 200, 
          y: 300, 
          angle: Math.PI / 2, 
          velocity: { x: 0, y: 0 },
          shieldEnergy: MAX_SHIELD_ENERGY,
          invulnerable: true
        }))
        setTimeout(() => setShip1(prev => ({ ...prev, invulnerable: false })), INVULNERABILITY_TIME * 1000 / 60)
      }
    }

    if (respawnTimer2 > 0) {
      setRespawnTimer2(prev => prev - 1)
      if (respawnTimer2 === 1) {
        setShip2(prev => ({ 
          ...prev, 
          x: 600, 
          y: 300, 
          angle: 3 * Math.PI / 2, 
          velocity: { x: 0, y: 0 },
          shieldEnergy: MAX_SHIELD_ENERGY,
          invulnerable: true
        }))
        setTimeout(() => setShip2(prev => ({ ...prev, invulnerable: false })), INVULNERABILITY_TIME * 1000 / 60)
      }
    }
  }

  const createExplosion = (x: number, y: number) => {
    const newParticles = Array.from({ length: 50 }, () => ({
      x,
      y,
      velocity: {
        x: (Math.random() - 0.5) * 5,
        y: (Math.random() - 0.5) * 5
      },
      life: 30 + Math.random() * 20,
      color: `rgba(255, ${Math.floor(Math.random() * 200) + 55}, 51, ${Math.random() * 0.5 + 0.5})`,
      size: Math.random() * 4 + 2
    }))
    setParticles(prev => [...prev, ...newParticles].slice(-MAX_PARTICLES))
  }

  const drawGame = (ctx: CanvasRenderingContext2D) => {
    ctx.fillStyle = '#0D0208'
    ctx.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT)

    // Draw star
    const gradient = ctx.createRadialGradient(CANVAS_WIDTH / 2, CANVAS_HEIGHT / 2, 0, CANVAS_WIDTH / 2, CANVAS_HEIGHT / 2, STAR_RADIUS)
    gradient.addColorStop(0, 'rgba(51, 255, 51, 1)')
    gradient.addColorStop(1, 'rgba(51, 255, 51, 0)')
    ctx.fillStyle = gradient
    ctx.beginPath()
    ctx.arc(CANVAS_WIDTH / 2, CANVAS_HEIGHT / 2, STAR_RADIUS, 0, Math.PI * 2)
    ctx.fill()

    // Draw ships
    const drawShip = (ship: Ship) => {
      if (ship.x === -1 && ship.y === -1) return // Don't draw if ship is destroyed

      ctx.save()
      ctx.translate(ship.x, ship.y)
      ctx.rotate(ship.angle)

      // Draw ship body (smaller)
      ctx.fillStyle = '#33FF33'
      ctx.beginPath()
      ctx.moveTo(10, 0)
      ctx.lineTo(-10, -7)
      ctx.lineTo(-10, 7)
      ctx.closePath()
      ctx.fill()

      // Draw wings (smaller)
      ctx.beginPath()
      ctx.moveTo(-10, -7)
      ctx.quadraticCurveTo(0, -14, 10, 0)
      ctx.moveTo(-10, 7)
      ctx.quadraticCurveTo(0, 14, 10, 0)
      ctx.strokeStyle = '#33FF33'
      ctx.lineWidth = 1.5
      ctx.stroke()

      // Draw engine
      if (ship.thrust) {
        const speed = Math.sqrt(ship.velocity.x ** 2 + ship.velocity.y ** 2)
        const normalizedSpeed = Math.min(speed / MAX_SHIP_SPEED, 1)
        ctx.fillStyle = `rgba(51, 255, 51, ${normalizedSpeed})`
        ctx.beginPath()
        ctx.moveTo(-10, -3)
        ctx.lineTo(-17 - normalizedSpeed * 7, 0)
        ctx.lineTo(-10, 3)
        ctx.closePath()
        ctx.fill()
      }

      // Draw shield (red)
      if (ship.shieldActive && ship.shieldEnergy > 0 && !ship.shooting) {
        ctx.beginPath()
        ctx.arc(0, 0, 15, 0, Math.PI * 2)
        ctx.strokeStyle = `rgba(255, 0, 0, ${ship.shieldEnergy / MAX_SHIELD_ENERGY})`
        ctx.lineWidth = 2
        ctx.stroke()
      }

      // Draw invulnerability effect
      if (ship.invulnerable) {
        ctx.beginPath()
        ctx.arc(0, 0, 17, 0, Math.PI * 2)
        ctx.strokeStyle = `rgba(255, 255, 255, ${0.5 + Math.sin(Date.now() / 100) * 0.5})`
        ctx.lineWidth = 1
        ctx.stroke()
      }

      ctx.restore()
    }

    drawShip(ship1)
    drawShip(ship2)

    // Draw bullets (longer and red)
    ctx.strokeStyle = '#FF0000'
    ctx.lineWidth = 2
    const drawBullets = (bullets: Bullet[]) => {
      bullets.forEach(bullet => {
        ctx.beginPath()
        ctx.moveTo(bullet.x, bullet.y)
        ctx.lineTo(
          bullet.x - Math.cos(bullet.angle) * BULLET_LENGTH,
          bullet.y - Math.sin(bullet.angle) * BULLET_LENGTH
        )
        ctx.stroke()
      })
    }

    drawBullets(bullets1)
    drawBullets(bullets2)

    // Draw particles
    particles.forEach(particle => {
      ctx.fillStyle = particle.color
      ctx.beginPath()
      ctx.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2)
      ctx.fill()
    })

    // Draw scores
    ctx.font = '20px monospace'
    ctx.fillStyle = '#33FF33'
    ctx.fillText(`Player 1: ${ship1.score}`, 10, 30)
    ctx.fillText(`Player 2: ${ship2.score}`, CANVAS_WIDTH - 120, 30)

    // Draw shield energy bars
    const drawShieldBar = (x: number, y: number, energy: number) => {
      ctx.fillStyle = `rgba(255, 0, 0, 0.5)`
      ctx.fillRect(x, y, energy / MAX_SHIELD_ENERGY * 100, 10)
      ctx.strokeStyle = '#FF0000'
      ctx.strokeRect(x, y, 100, 10)
    }

    drawShieldBar(10, 40, ship1.shieldEnergy)
    drawShieldBar(CANVAS_WIDTH - 110, 40, ship2.shieldEnergy)

    // Draw respawn timers
    if (respawnTimer1 > 0) {
      ctx.fillText(`Respawn: ${Math.ceil(respawnTimer1 / 60)}`, 10, 70)
    }
    if (respawnTimer2 > 0) {
      ctx.fillText(`Respawn: ${Math.ceil(respawnTimer2 / 60)}`, CANVAS_WIDTH - 120, 70)
    }
  }

  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (!isGameRunning) return

      switch (e.key) {
        case 'ArrowLeft':
          setShip1(prev => ({ ...prev, rotationSpeed: -ROTATION_SPEED }))
          break
        case 'ArrowRight':
          setShip1(prev => ({ ...prev, rotationSpeed: ROTATION_SPEED }))
          break
        case 'ArrowUp':
          setShip1(prev => ({ ...prev, thrust: true }))
          break
        case 'ArrowDown':
          setShip1(prev => ({ ...prev, shieldActive: true }))
          break
        case ' ':
          if (ship1.x !== -1 && ship1.y !== -1) {
            setShip1(prev => ({ ...prev, shooting: true }))
            setBullets1(prev => [...prev, {
              x: ship1.x + Math.cos(ship1.angle) * 15,
              y: ship1.y + Math.sin(ship1.angle) * 15,
              angle: ship1.angle,
              velocity: {
                x: Math.cos(ship1.angle) * BULLET_SPEED + ship1.velocity.x,
                y: Math.sin(ship1.angle) * BULLET_SPEED + ship1.velocity.y
              },
              life: BULLET_LIFE
            }])
          }
          break
        case 'a':
          setShip2(prev => ({ ...prev, rotationSpeed: -ROTATION_SPEED }))
          break
        case 'd':
          setShip2(prev => ({ ...prev, rotationSpeed: ROTATION_SPEED }))
          break
        case 'w':
          setShip2(prev => ({ ...prev, thrust: true }))
          break
        case 's':
          setShip2(prev => ({ ...prev, shieldActive: true }))
          break
        case 'q':
          if (ship2.x !== -1 && ship2.y !== -1) {
            setShip2(prev => ({ ...prev, shooting: true }))
            setBullets2(prev => [...prev, {
              x: ship2.x + Math.cos(ship2.angle) * 15,
              y: ship2.y + Math.sin(ship2.angle) * 15,
              angle: ship2.angle,
              velocity: {
                x: Math.cos(ship2.angle) * BULLET_SPEED + ship2.velocity.x,
                y: Math.sin(ship2.angle) * BULLET_SPEED + ship2.velocity.y
              },
              life: BULLET_LIFE
            }])
          }
          break
      }
    }

    const handleKeyUp = (e: KeyboardEvent) => {
      if (!isGameRunning) return

      switch (e.key) {
        case 'ArrowLeft':
        case 'ArrowRight':
          setShip1(prev => ({ ...prev, rotationSpeed: 0 }))
          break
        case 'ArrowUp':
          setShip1(prev => ({ ...prev, thrust: false }))
          break
        case 'ArrowDown':
          setShip1(prev => ({ ...prev, shieldActive: false }))
          break
        case ' ':
          setShip1(prev => ({ ...prev, shooting: false }))
          break
        case 'a':
        case 'd':
          setShip2(prev => ({ ...prev, rotationSpeed: 0 }))
          break
        case 'w':
          setShip2(prev => ({ ...prev, thrust: false }))
          break
        case 's':
          setShip2(prev => ({ ...prev, shieldActive: false }))
          break
        case 'q':
          setShip2(prev => ({ ...prev, shooting: false }))
          break
      }
    }

    window.addEventListener('keydown', handleKeyDown)
    window.addEventListener('keyup', handleKeyUp)

    return () => {
      window.removeEventListener('keydown', handleKeyDown)
      window.removeEventListener('keyup', handleKeyUp)
    }
  }, [isGameRunning, ship1, ship2])

  return (
    <div className="flex items-center justify-center min-h-screen bg-gray-900 p-4">
      <AnimatePresence>
        {isOn && (
          <motion.div
            initial={{ opacity: 0, scale: 0.8 }}
            animate={{ opacity: 1, scale: 1 }}
            exit={{ opacity: 0, scale: 0.8 }}
            transition={{ duration: 0.5 }}
            className="w-full max-w-2xl h-[80vh] bg-[#0D0208] rounded-lg overflow-hidden shadow-2xl border-4 border-[#3F3F3F] relative"
          >
            <div className="absolute inset-0 pointer-events-none">
              <div
                className="absolute inset-0 opacity-10"
                style={{
                  background: 'repeating-linear-gradient(0deg, #000 0px, #000 1px, transparent 1px, transparent 2px)',
                  backgroundSize: '100% 2px',
                }}
              />
              <div
                className="absolute inset-0 opacity-5"
                style={{
                  background: 'radial-gradient(circle, #ffffff 0%, transparent 100%)',
                }}
              />
            </div>
            {isGameRunning ? (
              <div className="relative h-full">
                <canvas ref={canvasRef} width={CANVAS_WIDTH} height={CANVAS_HEIGHT} className="w-full h-full" />
                <button
                  onClick={() => setIsGameRunning(false)}
                  className="absolute bottom-2 right-2 px-2 py-1 bg-transparent text-[#33FF33] border border-[#33FF33] rounded hover:bg-[#33FF33] hover:text-black transition-colors text-xs"
                >
                  Exit Game
                </button>
                <div className="absolute bottom-2 left-2 text-[#33FF33] text-xs">
                  Player 1: Arrow keys to move, Down for shield, Space to shoot<br />
                  Player 2: WASD to move, S for shield, Q to shoot
                </div>
              </div>
            ) : (
              <div
                ref={terminalRef}
                className="h-full overflow-y-auto p-6 font-mono text-[#33FF33] text-sm"
                style={{ textShadow: '0 0 5px #33FF33' }}
              >
                {output.map((line, index) => (
                  <motion.div
                    key={index}
                    initial={{ opacity: 0, y: 20 }}
                    animate={{ opacity: 1, y: 0 }}
                    transition={{ duration: 0.3, delay: index * 0.05 }}
                    className="mb-1"
                  >
                    {line}
                  </motion.div>
                ))}
                <form onSubmit={handleSubmit} className="flex items-center mt-2">
                  <span className="mr-2 text-[#33FF33]">{'>'}</span>
                  <input
                    type={loginStep === 'password' ? 'password' : 'text'}
                    value={input}
                    onChange={handleInput}
                    className="flex-grow bg-transparent outline-none text-[#33FF33]"
                    autoFocus
                  />
                </form>
              </div>
            )}
          </motion.div>
        )}
      </AnimatePresence>
      {!isOn && (
        <button
          onClick={() => {
            setIsOn(true)
            setOutput(['Terminal restarted. Welcome back!', 'Type "help" for available commands.'])
          }}
          className="px-4 py-2 bg-[#33FF33] text-black rounded hover:bg-[#2CD62C] transition-colors"
        >
          Restart Terminal
        </button>
      )}
    </div>
  )
}