package models

import (
	"math/rand"
	"sync"
	"time"
)

type ServerInfo struct {
	ID         string  `json:"id"`
	Name       string  `json:"name"`
	Region     string  `json:"region"`
	Version    string  `json:"version"`
	MaxPlayers int     `json:"max_players"`
	Online     int     `json:"online"`
	TPS        float64 `json:"tps"`
	MSPT       float64 `json:"mspt"`
	Status     string  `json:"status"`
}

var (
	serversMu sync.RWMutex
	servers   = []ServerInfo{
		{ID: "SP4", Name: "SP4", Region: "EU-West", Version: "1.20.4", MaxPlayers: 120, Online: 42, TPS: 19.8, MSPT: 38.2, Status: "online"},
		{ID: "SPk", Name: "SPk", Region: "US-East", Version: "1.20.4", MaxPlayers: 80, Online: 17, TPS: 19.6, MSPT: 41.9, Status: "online"},
		{ID: "SPm", Name: "SPm", Region: "Asia", Version: "1.20.4", MaxPlayers: 64, Online: 9, TPS: 19.9, MSPT: 35.6, Status: "online"},
	}
	rng = rand.New(rand.NewSource(time.Now().UnixNano()))
)

func GetServers() []ServerInfo {
	serversMu.RLock()
	defer serversMu.RUnlock()
	copyList := make([]ServerInfo, len(servers))
	copy(copyList, servers)
	return copyList
}

func UpdateServers() []ServerInfo {
	serversMu.Lock()
	defer serversMu.Unlock()

	for i := range servers {
		base := servers[i]
		if base.Status != "online" {
			servers[i].Online = 0
			servers[i].TPS = 0
			servers[i].MSPT = 0
			continue
		}
		delta := rng.Intn(3) - 1
		online := base.Online + delta
		if online < 0 {
			online = 0
		}
		if online > base.MaxPlayers {
			online = base.MaxPlayers
		}
		servers[i].Online = online

		tpsJitter := (rng.Float64() * 0.4) - 0.2
		msptJitter := (rng.Float64() * 4.0) - 2.0

		servers[i].TPS = clampFloat(base.TPS+tpsJitter, 17.5, 20.0)
		servers[i].MSPT = clampFloat(base.MSPT+msptJitter, 20.0, 60.0)
	}

	copyList := make([]ServerInfo, len(servers))
	copy(copyList, servers)
	return copyList
}

func ServerExists(id string) bool {
	serversMu.RLock()
	defer serversMu.RUnlock()
	for _, srv := range servers {
		if srv.ID == id {
			return true
		}
	}
	return false
}

func GetServerByID(id string) (ServerInfo, bool) {
	serversMu.RLock()
	defer serversMu.RUnlock()
	for _, srv := range servers {
		if srv.ID == id {
			return srv, true
		}
	}
	return ServerInfo{}, false
}

func SetServerStatus(id, status string) bool {
	serversMu.Lock()
	defer serversMu.Unlock()
	for i, srv := range servers {
		if srv.ID == id {
			servers[i].Status = status
			if status != "online" {
				servers[i].Online = 0
				servers[i].TPS = 0
				servers[i].MSPT = 0
			}
			return true
		}
	}
	return false
}

func ScheduleServerOnline(id string, delaySeconds int) {
	time.AfterFunc(time.Duration(delaySeconds)*time.Second, func() {
		SetServerStatus(id, "online")
	})
}

func clampFloat(value, min, max float64) float64 {
	if value < min {
		return min
	}
	if value > max {
		return max
	}
	return value
}
