<template>
  <div class="interactive-bg">
    <canvas ref="canvas"></canvas>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from 'vue'

const canvas = ref<HTMLCanvasElement | null>(null)
let ctx: CanvasRenderingContext2D | null = null
let animationId: number
let particles: Particle[] = []
let airflowParticles: AirflowParticle[] = []
let explosions: ExplosionParticle[] = []
let nebulas: Nebula[] = []
let shootingStars: ShootingStar[] = []
let mouse = { x: -1000, y: -1000 }
let lastMouse = { x: -1000, y: -1000 }

// Configuration
const PARTICLE_COUNT = 50
const NEBULA_COUNT = 4
const SHOOTING_STAR_CHANCE = 0.005

class Nebula {
  x: number
  y: number
  radius: number
  color: string
  vx: number
  vy: number

  constructor(w: number, h: number) {
    this.x = Math.random() * w
    this.y = Math.random() * h
    this.radius = Math.random() * 200 + 150 
    this.vx = (Math.random() - 0.5) * 0.2 
    this.vy = (Math.random() - 0.5) * 0.2
    
    const colors = [
      'rgba(76, 29, 149, 0.15)', 
      'rgba(30, 58, 138, 0.15)', 
      'rgba(88, 28, 135, 0.1)'   
    ]
    this.color = colors[Math.floor(Math.random() * colors.length)]
  }

  update(w: number, h: number) {
    this.x += this.vx
    this.y += this.vy

    if (this.x < -this.radius) this.x = w + this.radius
    if (this.x > w + this.radius) this.x = -this.radius
    if (this.y < -this.radius) this.y = h + this.radius
    if (this.y > h + this.radius) this.y = -this.radius
  }

  draw() {
    if (!ctx) return
    ctx.beginPath()
    const gradient = ctx.createRadialGradient(this.x, this.y, 0, this.x, this.y, this.radius)
    gradient.addColorStop(0, this.color)
    gradient.addColorStop(1, 'rgba(0,0,0,0)')
    
    ctx.fillStyle = gradient
    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2)
    ctx.fill()
  }
}

class Particle {
  x: number
  y: number
  vx: number
  vy: number
  baseSize: number
  size: number
  color: string
  glowColor: string
  isGold: boolean
  pulseAngle: number
  pulseSpeed: number

  constructor(w: number, h: number, startBottom: boolean = true) {
    this.x = Math.random() * w
    this.y = startBottom ? h + Math.random() * 100 : Math.random() * h
    this.vx = (Math.random() - 0.5) * 0.3
    this.vy = -Math.random() * 0.6 - 0.2 
    
    this.isGold = Math.random() < 0.1
    this.pulseAngle = Math.random() * Math.PI * 2
    this.pulseSpeed = 0.05

    if (this.isGold) {
      this.baseSize = Math.random() * 8 + 6 
      this.color = '#FDB813' 
      this.glowColor = 'rgba(253, 184, 19, 0.6)'
    } else {
      this.baseSize = Math.random() * 4 + 2 
      const colors = [
        { c: '#ffffff', g: 'rgba(255, 255, 255, 0.4)' }, 
        { c: '#6366f1', g: 'rgba(99, 102, 241, 0.4)' },  
        { c: '#06b6d4', g: 'rgba(6, 182, 212, 0.4)' },   
      ]
      const type = colors[Math.floor(Math.random() * colors.length)]
      this.color = type.c
      this.glowColor = type.g
    }
    this.size = this.baseSize
  }

  update(w: number, h: number) {
    this.x += this.vx
    this.y += this.vy

    if (this.isGold) {
      this.pulseAngle += this.pulseSpeed
      this.size = this.baseSize + Math.sin(this.pulseAngle) * 1.5
    }

    if (this.y < -50) {
      this.y = h + 50
      this.x = Math.random() * w
    }
    if (this.x < -50) this.x = w + 50
    if (this.x > w + 50) this.x = -50
  }

  draw() {
    if (!ctx) return
    ctx.beginPath()
    ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2)
    ctx.fillStyle = this.color
    
    ctx.shadowBlur = this.isGold ? 25 + Math.sin(this.pulseAngle) * 5 : 10
    ctx.shadowColor = this.glowColor
    ctx.fill()
    ctx.shadowBlur = 0 
  }
}

class ShootingStar {
  x: number
  y: number
  vx: number
  vy: number
  length: number
  life: number
  
  constructor(w: number, h: number) {
    this.x = Math.random() * w
    this.y = Math.random() * (h * 0.5) 
    this.vx = (Math.random() * 10 + 10) * (Math.random() < 0.5 ? 1 : -1) 
    this.vy = Math.random() * 5 + 2 
    this.length = Math.random() * 80 + 50
    this.life = 1.0
  }

  update() {
    this.x += this.vx
    this.y += this.vy
    this.life -= 0.02
  }

  draw() {
    if (!ctx || this.life <= 0) return
    
    const tailX = this.x - this.vx * 3 
    const tailY = this.y - this.vy * 3

    const gradient = ctx.createLinearGradient(this.x, this.y, tailX, tailY)
    gradient.addColorStop(0, `rgba(255, 255, 255, ${this.life})`)
    gradient.addColorStop(1, `rgba(255, 255, 255, 0)`)

    ctx.beginPath()
    ctx.moveTo(this.x, this.y)
    ctx.lineTo(tailX, tailY)
    ctx.strokeStyle = gradient
    ctx.lineWidth = 2
    ctx.lineCap = 'round'
    ctx.stroke()
    
    ctx.beginPath()
    ctx.arc(this.x, this.y, 2, 0, Math.PI * 2)
    ctx.fillStyle = `rgba(255, 255, 255, ${this.life})`
    ctx.shadowBlur = 10
    ctx.shadowColor = 'white'
    ctx.fill()
    ctx.shadowBlur = 0
  }
}

class AirflowParticle {
  x: number
  y: number
  vx: number
  vy: number
  size: number
  life: number
  decay: number
  color: string

  constructor(x: number, y: number, mouseVx: number, mouseVy: number) {
    this.x = x
    this.y = y
    
    const speed = Math.sqrt(mouseVx * mouseVx + mouseVy * mouseVy)
    const dirX = speed > 0 ? mouseVx / speed : 0
    const dirY = speed > 0 ? mouseVy / speed : 0

    const spread = 0.6 
    const angle = Math.atan2(-dirY, -dirX) + (Math.random() - 0.5) * spread
    
    const ejectSpeed = Math.random() * 3 + 1
    
    this.vx = Math.cos(angle) * ejectSpeed
    this.vy = Math.sin(angle) * ejectSpeed
    
    this.size = Math.random() * 3 + 2
    this.life = 1.0
    this.decay = Math.random() * 0.02 + 0.015
    
    this.color = `255, 255, 255` 
  }

  update() {
    this.x += this.vx
    this.y += this.vy
    this.life -= this.decay
    this.size += 0.3 
    this.vx *= 0.94 
    this.vy *= 0.94
  }

  draw() {
    if (!ctx || this.life <= 0) return
    ctx.beginPath()
    ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2)
    const gradient = ctx.createRadialGradient(this.x, this.y, 0, this.x, this.y, this.size)
    gradient.addColorStop(0, `rgba(${this.color}, ${this.life * 0.8})`)
    gradient.addColorStop(1, `rgba(${this.color}, 0)`)
    
    ctx.fillStyle = gradient
    ctx.fill()
  }
}

class ExplosionParticle {
  x: number
  y: number
  vx: number
  vy: number
  life: number
  color: string
  size: number

  constructor(x: number, y: number, color: string) {
    this.x = x
    this.y = y
    const angle = Math.random() * Math.PI * 2
    const speed = Math.random() * 6 + 2 
    this.vx = Math.cos(angle) * speed
    this.vy = Math.sin(angle) * speed
    this.life = 1.0
    this.color = color
    this.size = Math.random() * 3 + 1
  }

  update() {
    this.x += this.vx
    this.y += this.vy
    this.life -= Math.random() * 0.02 + 0.01 
    this.vx *= 0.95 
    this.vy *= 0.95
  }

  draw() {
    if (!ctx || this.life <= 0) return
    ctx.globalAlpha = this.life
    ctx.fillStyle = this.color
    ctx.beginPath()
    ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2)
    ctx.fill()
    ctx.globalAlpha = 1.0
  }
}

const init = () => {
  if (!canvas.value) return
  ctx = canvas.value.getContext('2d')
  if (!ctx) return

  const resize = () => {
    if (!canvas.value) return
    canvas.value.width = canvas.value.offsetWidth
    canvas.value.height = canvas.value.offsetHeight
    
    particles = []
    nebulas = []
    shootingStars = []
    
    for (let i = 0; i < PARTICLE_COUNT; i++) {
      particles.push(new Particle(canvas.value.width, canvas.value.height, false))
    }
    for (let i = 0; i < NEBULA_COUNT; i++) {
      nebulas.push(new Nebula(canvas.value.width, canvas.value.height))
    }
  }
  
  window.addEventListener('resize', resize)
  resize()

  const onMouseMove = (e: MouseEvent) => {
    if (!canvas.value) return
    const rect = canvas.value.getBoundingClientRect()
    lastMouse.x = mouse.x
    lastMouse.y = mouse.y
    mouse.x = e.clientX - rect.left
    mouse.y = e.clientY - rect.top
    
    const dx = mouse.x - lastMouse.x
    const dy = mouse.y - lastMouse.y
    const speed = Math.sqrt(dx * dx + dy * dy)

    if (lastMouse.x !== -1000 && speed > 1) {
        const count = Math.min(Math.floor(speed / 1.5), 12) 
        
        for (let i = 0; i < count; i++) {
            const t = Math.random()
            const ix = lastMouse.x + dx * t
            const iy = lastMouse.y + dy * t
            airflowParticles.push(new AirflowParticle(ix, iy, dx, dy))
        }
    }

    checkCollisions()
  }
  
  const onMouseLeave = () => {
    mouse.x = -1000
    mouse.y = -1000
    lastMouse.x = -1000
    lastMouse.y = -1000
  }

  canvas.value.addEventListener('mousemove', onMouseMove)
  canvas.value.addEventListener('mouseleave', onMouseLeave)

  const checkCollisions = () => {
    const hitRadius = 40 
    
    for (let i = particles.length - 1; i >= 0; i--) {
      const p = particles[i]
      const dx = mouse.x - p.x
      const dy = mouse.y - p.y
      const dist = Math.sqrt(dx * dx + dy * dy)
      
      if (dist < hitRadius) {
        createExplosion(p.x, p.y, p.color)
        particles.splice(i, 1)
        if (canvas.value) {
           particles.push(new Particle(canvas.value.width, canvas.value.height, true))
        }
      }
    }
  }

  const createExplosion = (x: number, y: number, color: string) => {
    for (let i = 0; i < 50; i++) {
      explosions.push(new ExplosionParticle(x, y, color))
    }
  }

  const animate = () => {
    if (!ctx || !canvas.value) return
    ctx.clearRect(0, 0, canvas.value.width, canvas.value.height)

    // 1. Background Nebula
    nebulas.forEach(n => {
      n.update(canvas.value!.width, canvas.value!.height)
      n.draw()
    })

    // 2. Shooting Stars
    if (Math.random() < SHOOTING_STAR_CHANCE) {
      shootingStars.push(new ShootingStar(canvas.value.width, canvas.value.height))
    }
    for (let i = shootingStars.length - 1; i >= 0; i--) {
      shootingStars[i].update()
      shootingStars[i].draw()
      if (shootingStars[i].life <= 0 || 
          shootingStars[i].x < -100 || shootingStars[i].x > canvas.value.width + 100 ||
          shootingStars[i].y > canvas.value.height + 100) {
        shootingStars.splice(i, 1)
      }
    }

    // 3. Airflow
    ctx.globalCompositeOperation = 'lighter'
    for (let i = airflowParticles.length - 1; i >= 0; i--) {
      airflowParticles[i].update()
      airflowParticles[i].draw()
      if (airflowParticles[i].life <= 0) {
        airflowParticles.splice(i, 1)
      }
    }
    ctx.globalCompositeOperation = 'source-over'

    // 4. Particles
    particles.forEach(p => {
      p.update(canvas.value!.width, canvas.value!.height)
      p.draw()
    })

    // 5. Explosions
    for (let i = explosions.length - 1; i >= 0; i--) {
      explosions[i].update()
      explosions[i].draw()
      if (explosions[i].life <= 0) {
        explosions.splice(i, 1)
      }
    }

    // 6. Vignette
    const w = canvas.value.width
    const h = canvas.value.height
    const radius = Math.max(w, h) * 0.8
    const gradient = ctx.createRadialGradient(w/2, h/2, radius * 0.5, w/2, h/2, radius)
    gradient.addColorStop(0, 'rgba(0,0,0,0)')
    gradient.addColorStop(1, 'rgba(0,0,0,0.4)') 
    ctx.fillStyle = gradient
    ctx.fillRect(0, 0, w, h)

    animationId = requestAnimationFrame(animate)
  }

  animate()
}

onMounted(() => {
  init()
})

onBeforeUnmount(() => {
  cancelAnimationFrame(animationId)
  window.removeEventListener('resize', () => {})
})
</script>

<style scoped>
.interactive-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: auto;
  z-index: 0;
}
canvas {
  display: block;
  width: 100%;
  height: 100%;
}
</style>
