package game

import (
	"fmt"
	"sync"

	"a301_game_server/config"
	"a301_game_server/pkg/logger"
)

// World manages all zones.
type World struct {
	mu    sync.RWMutex
	zones map[uint32]*Zone
	cfg   *config.Config
}

// NewWorld creates a new world.
func NewWorld(cfg *config.Config) *World {
	return &World{
		zones: make(map[uint32]*Zone),
		cfg:   cfg,
	}
}

// CreateZone creates and registers a new zone.
func (w *World) CreateZone(id uint32) *Zone {
	zone := NewZone(id, w.cfg)

	w.mu.Lock()
	w.zones[id] = zone
	w.mu.Unlock()

	logger.Info("zone created", "zoneID", id)
	return zone
}

// GetZone returns a zone by ID.
func (w *World) GetZone(id uint32) (*Zone, error) {
	w.mu.RLock()
	defer w.mu.RUnlock()

	zone, ok := w.zones[id]
	if !ok {
		return nil, fmt.Errorf("zone %d not found", id)
	}
	return zone, nil
}

// StartAll launches all zone game loops.
func (w *World) StartAll() {
	w.mu.RLock()
	defer w.mu.RUnlock()

	for _, zone := range w.zones {
		go zone.Run()
	}
	logger.Info("all zones started", "count", len(w.zones))
}

// StopAll stops all zone game loops.
func (w *World) StopAll() {
	w.mu.RLock()
	defer w.mu.RUnlock()

	for _, zone := range w.zones {
		zone.Stop()
	}
	logger.Info("all zones stopped")
}

// TotalPlayers returns the total number of online players across all zones.
func (w *World) TotalPlayers() int {
	w.mu.RLock()
	defer w.mu.RUnlock()

	total := 0
	for _, zone := range w.zones {
		total += zone.PlayerCount()
	}
	return total
}

// TotalEntities returns the total number of entities across all zones.
func (w *World) TotalEntities() int {
	w.mu.RLock()
	defer w.mu.RUnlock()

	total := 0
	for _, zone := range w.zones {
		total += zone.EntityCount()
	}
	return total
}
