<template>
  <Scene name="effects" @preload="preloadScene" @create="createScene" @update="updateScene" />
</template>

<script setup lang="ts">
import { Scene } from 'phavuer'
import { useZoneStore } from '@/stores/zoneStore'
import { useGameStore } from '@/stores/gameStore'
import { onBeforeUnmount, ref, watch } from 'vue'
import type { WeatherState } from '@/types'

// Constants
const SUNRISE_HOUR = 6
const SUNSET_HOUR = 20
const DAY_STRENGTH = 100
const NIGHT_STRENGTH = 30

// Stores
const gameStore = useGameStore()
const zoneStore = useZoneStore()

// Scene ref
const sceneRef = ref<Phaser.Scene | null>(null)

// Effect refs
const lightEffect = ref<Phaser.GameObjects.Graphics | null>(null)
const rainEmitter = ref<Phaser.GameObjects.Particles.ParticleEmitter | null>(null)
const fogSprite = ref<Phaser.GameObjects.Sprite | null>(null)

// State refs
const weatherState = ref<WeatherState>({
  isRainEnabled: false,
  rainPercentage: 0,
  isFogEnabled: false,
  fogDensity: 0
})

// Scene lifecycle methods
const preloadScene = async (scene: Phaser.Scene) => {
  scene.load.image('raindrop', 'assets/raindrop.png')
  scene.load.image('fog', 'assets/fog.png')
}

const createScene = async (scene: Phaser.Scene) => {
  sceneRef.value = scene
  setupEffects(scene)
  setupSocketListeners()
}

const updateScene = () => {
  updateEffects()
}

// Effect setup
const setupEffects = (scene: Phaser.Scene) => {
  createLightEffect(scene)
  createRainEffect(scene)
  createFogEffect(scene)
}

const createLightEffect = (scene: Phaser.Scene) => {
  lightEffect.value = scene.add.graphics()
  lightEffect.value.setDepth(1000)
}

const createRainEffect = (scene: Phaser.Scene) => {
  rainEmitter.value = scene.add.particles(0, 0, 'raindrop', {
    x: { min: 0, max: window.innerWidth },
    y: -50,
    quantity: 5,
    lifespan: 2000,
    speedY: { min: 300, max: 500 },
    scale: { start: 0.005, end: 0.005 },
    alpha: { start: 0.5, end: 0 },
    blendMode: 'ADD'
  })
  rainEmitter.value.setDepth(900)
  rainEmitter.value.stop()
}

const createFogEffect = (scene: Phaser.Scene) => {
  fogSprite.value = scene.add.sprite(window.innerWidth / 2, window.innerHeight / 2, 'fog')
  fogSprite.value.setScale(2)
  fogSprite.value.setAlpha(0)
  fogSprite.value.setDepth(950)
}

// Lighting calculations
const calculateLightStrength = (time: Date): number => {
  const hour = time.getHours()
  const minute = time.getMinutes()

  let strength = DAY_STRENGTH

  // Night time (10 PM - 6 AM)
  if (hour >= SUNSET_HOUR || hour < SUNRISE_HOUR) {
    strength = NIGHT_STRENGTH
  }
  // Full daylight (7 AM - 7 PM)
  else if (hour > SUNRISE_HOUR && hour < SUNSET_HOUR - 2) {
    strength = DAY_STRENGTH
  }
  // Sunrise transition (6 AM - 7 AM)
  else if (hour === SUNRISE_HOUR) {
    strength = NIGHT_STRENGTH + ((DAY_STRENGTH - NIGHT_STRENGTH) * minute) / 60
  }
  // Sunset transition (8 PM - 10 PM)
  else if (hour >= SUNSET_HOUR - 2 && hour < SUNSET_HOUR) {
    const totalMinutes = (hour - (SUNSET_HOUR - 2)) * 60 + minute
    const transitionProgress = totalMinutes / 120 // 2 hours = 120 minutes
    strength = DAY_STRENGTH - (DAY_STRENGTH - NIGHT_STRENGTH) * transitionProgress
  }

  return strength
}

// Effect updates
const updateEffects = () => {
  const effects = zoneStore.zone?.zoneEffects || []

  if (effects.length > 0) {
    updateZoneEffects(effects)
  } else {
    // Make sure we're getting the current time
    const lightStrength = calculateLightStrength(gameStore.world.date)
    updateLightEffect(lightStrength)
    updateWeatherEffects()
  }
}

const updateZoneEffects = (effects: any[]) => {
  // Always update light based on time when zone effects are present
  updateLightEffect(calculateLightStrength(gameStore.world.date))

  effects.forEach((effect) => {
    switch (effect.effect) {
      case 'rain':
        updateRainEffect(effect.strength)
        break
      case 'fog':
        updateFogEffect(effect.strength)
        break
    }
  })
}

const updateWeatherEffects = () => {
  updateRainEffect(weatherState.value.isRainEnabled ? weatherState.value.rainPercentage : 0)
  updateFogEffect(weatherState.value.isFogEnabled ? weatherState.value.fogDensity * 100 : 0)
}

const updateLightEffect = (strength: number) => {
  if (!lightEffect.value) return
  const darkness = 1 - strength / 100
  lightEffect.value.clear()
  lightEffect.value.fillStyle(0x000000, darkness)
  lightEffect.value.fillRect(0, 0, window.innerWidth, window.innerHeight)
}

const updateRainEffect = (strength: number) => {
  if (!rainEmitter.value) return
  if (strength > 0) {
    rainEmitter.value.start()
    rainEmitter.value.setQuantity(Math.floor((strength / 100) * 10))
  } else {
    rainEmitter.value.stop()
  }
}

const updateFogEffect = (strength: number) => {
  if (!fogSprite.value) return
  fogSprite.value.setAlpha(strength / 100)
}

// Socket handlers
const setupSocketListeners = () => {
  // Initial weather state
  gameStore.connection?.emit('weather', (response: WeatherState) => {
    if (zoneStore.zone?.zoneEffects) return
    weatherState.value = response
    updateEffects()
  })

  // Weather updates
  gameStore.connection?.on('weather', (data: WeatherState) => {
    weatherState.value = data
    updateEffects()
  })

  // Time updates
  gameStore.connection?.on('date', () => {
    if (zoneStore.zone?.zoneEffects) return
    updateEffects()
  })
}

// Watchers
watch(() => zoneStore.zone?.zoneEffects, updateEffects, { deep: true })

// Cleanup
onBeforeUnmount(() => {
  if (sceneRef.value) sceneRef.value.scene.remove('effects')
  gameStore.connection?.off('weather')
})
</script>
