package sdk

import (
	"github.com/mhaya/game/game_cluster/internal/data"
	mhayaLogger "github.com/mhaya/logger"
	"math/rand"
)

// Service 结构体表示单个服务的信息。
type Service struct {
	NodeId string // 服务的节点地址
	Player int
	Weight float64 // 权重
}

// WeightedRoundRobin 是一个结构体，用于管理一组带权重的服务，并支持基于权重的选择逻辑。
type WeightedRoundRobin struct {
	services []*Service
	all      int
	total    float64 // 所有服务的总权重
}

// NewWeightedRoundRobin 创建一个新的 WeightedRoundRobin 实例。
func NewWeightedRoundRobin(maps map[string]int) *WeightedRoundRobin {
	serviceConfig, ok := data.ServerConfig.Get()
	if !ok {
		mhayaLogger.Warnf("[NewWeightedRoundRobin] weighted round robin service config is nil")
		return nil
	}
	wrr := &WeightedRoundRobin{
		services: nil,
	}
	var services []*Service
	for k, v := range maps {
		wrr.all += v
		services = append(services, &Service{
			NodeId: k,
			Player: v,
		})
	}
	wrr.services = services
	avg := wrr.all / len(wrr.services)

	for _, service := range services {
		if service.Player-avg <= 3*serviceConfig.Range {
			service.Weight = float64(serviceConfig.Weight.Max)
		} else if service.Player-avg < 2*serviceConfig.Range {
			service.Weight = float64(serviceConfig.Weight.Middle)
		} else {
			service.Weight = float64(serviceConfig.Weight.Min)
		}
		if service.Player >= serviceConfig.Expansion {
			service.Weight = float64(serviceConfig.Weight.Min)
		}
		if service.Player >= serviceConfig.Max {
			service.Weight = 0
		}
	}

	for _, s := range services {
		wrr.total += s.Weight
	}
	return wrr
}

// Pick 使用加权轮询的方式选取一个服务。
func (w *WeightedRoundRobin) Pick() *Service {
	if len(w.services) == 0 {
		return nil
	}

	// 随机选择一个介于[0, total)之间的数字
	target := rand.Float64() * w.total
	var current float64 = 0.0

	// 循环直到找到正确的服务
	for _, service := range w.services {
		current += service.Weight
		if current >= target {
			return service
		}
	}

	// 如果因浮点数精度问题未能命中，则返回最后一个服务
	return w.services[len(w.services)-1]
}
