package server

import (
	"fmt"
	"log"

	"git.zb-server.de/ZB-Server/EscapeFromTeacher/pkg/game"
)

// CheckCoinCollision prüft ob Spieler Coins einsammelt
func (r *Room) CheckCoinCollision(p *ServerPlayer) {
	if !p.IsAlive || p.IsSpectator {
		return
	}

	playerHitbox := game.Rect{
		OffsetX: p.X + r.pDrawOffX + r.pHitboxOffX,
		OffsetY: p.Y + r.pDrawOffY + r.pHitboxOffY,
		W:       r.pW,
		H:       r.pH,
	}

	// Durch alle aktiven Chunks iterieren
	for _, activeChunk := range r.ActiveChunks {
		chunkDef, exists := r.World.ChunkLibrary[activeChunk.ChunkID]
		if !exists {
			continue
		}

		// Durch alle Objekte im Chunk
		for objIdx, obj := range chunkDef.Objects {
			assetDef, ok := r.World.Manifest.Assets[obj.AssetID]
			if !ok {
				continue
			}

			// Nur Coins prüfen
			if assetDef.Type != "coin" {
				continue
			}

			// Eindeutiger Key für diesen Coin
			coinKey := fmt.Sprintf("%s_%d", activeChunk.ChunkID, objIdx)

			// Wurde bereits eingesammelt?
			if r.CollectedCoins[coinKey] {
				continue
			}

			// Coin-Hitbox
			coinHitbox := game.Rect{
				OffsetX: activeChunk.X + obj.X + assetDef.Hitbox.OffsetX,
				OffsetY: obj.Y + assetDef.Hitbox.OffsetY,
				W:       assetDef.Hitbox.W,
				H:       assetDef.Hitbox.H,
			}

			// Kollision?
			if game.CheckRectCollision(playerHitbox, coinHitbox) {
				// Coin einsammeln!
				r.CollectedCoins[coinKey] = true
				p.Score += 200
				log.Printf("💰 %s hat Coin eingesammelt! Score: %d", p.Name, p.Score)
			}
		}
	}
}

// UpdateDistanceScore aktualisiert Distanz-basierte Punkte
func (r *Room) UpdateDistanceScore() {
	if r.Status != "RUNNING" {
		return
	}

	// Anzahl lebender Spieler zählen
	aliveCount := 0
	for _, p := range r.Players {
		if p.IsAlive && !p.IsSpectator {
			aliveCount++
		}
	}

	if aliveCount == 0 {
		return
	}

	// Multiplier = Anzahl lebender Spieler
	multiplier := float64(aliveCount)

	// Akkumulator erhöhen: multiplier Punkte pro Sekunde
	// Bei 60 FPS: multiplier / 60.0 Punkte pro Tick
	r.ScoreAccum += multiplier / 60.0

	// Wenn Akkumulator >= 1.0, Punkte vergeben
	if r.ScoreAccum >= 1.0 {
		pointsToAdd := int(r.ScoreAccum)
		r.ScoreAccum -= float64(pointsToAdd)

		for _, p := range r.Players {
			if p.IsAlive && !p.IsSpectator {
				p.Score += pointsToAdd
			}
		}
	}
}

// KillPlayer markiert Spieler als tot
func (r *Room) KillPlayer(p *ServerPlayer) {
	if !p.IsAlive {
		return
	}

	p.IsAlive = false
	p.IsSpectator = true
	log.Printf("💀 %s ist gestorben! Final Score: %d", p.Name, p.Score)

	// Prüfen ob alle tot sind
	aliveCount := 0
	for _, pl := range r.Players {
		if pl.IsAlive && !pl.IsSpectator {
			aliveCount++
		}
	}

	if aliveCount == 0 && r.Status == "RUNNING" {
		log.Printf("🏁 Alle Spieler tot - Game Over!")
		r.Status = "GAMEOVER"
	}
}
