package service

import (
	"encoding/json"
	"gadmin/config"
	"gadmin/internal/admin/forms"
	"gadmin/internal/gorm/model"
	"gadmin/internal/gorm/query"
	"gadmin/utility/serializer"
	"strconv"
	"strings"

	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cast"
	clientv3 "go.etcd.io/etcd/client/v3"
)

var DrainageServer = &sDrainageServer{
	key:                 "sparkteam/servers/loginparams/defaultGates",      // 引流服务器key
	newerServersKey:     "sparkteam/servers/loginparams/newerServers",      // 新服务器key
	maxOpendServerIdKey: "sparkteam/servers/loginparams/maxOpendServerId",  // 最大开放服务器ID
	whiteListKey:        "sparkteam/servers/loginparams/serverWhiteList",   // 登录白名单
	maxDeployServerId:   "sparkteam/servers/loginparams/maxDeployServerId", // 最大部署服务器
}

type sDrainageServer struct {
	key                 string
	newerServersKey     string
	maxOpendServerIdKey string
	whiteListKey        string
	maxDeployServerId   string
}

func (s *sDrainageServer) Get(ctx *gin.Context, req forms.GetDrainageServerReq) serializer.Response {
	logrus.Warnf("sDrainageServer Get")

	kv := clientv3.NewKV(config.Etcd)
	getResp, err := kv.Get(ctx, s.key)
	if err != nil {
		return serializer.DBErr(err.Error(), err)
	}

	if len(getResp.Kvs) == 0 {
		return serializer.Suc([]int32{})
	}

	var serverIds []int32
	if err = json.Unmarshal(getResp.Kvs[0].Value, &serverIds); err != nil {
		return serializer.DBErr(err.Error(), err)
	}

	return serializer.Suc(serverIds)
}

func (s *sDrainageServer) Edit(ctx *gin.Context, req forms.EditDrainageServerReq) serializer.Response {
	marshal, err := json.Marshal(req.ServerIds)
	if err != nil {
		return serializer.DBErr(err.Error(), err)
	}

	logrus.Warnf("sDrainageServer ServerIds:%v", string(marshal))

	kv := clientv3.NewKV(config.Etcd)
	putResp, err := kv.Put(ctx, s.key, string(marshal), clientv3.WithPrevKV())
	if err != nil {
		return serializer.DBErr(err.Error(), err)
	}

	logrus.Warnf("Revision:%v", putResp.Header.Revision)
	if putResp.PrevKv != nil {
		logrus.Warnf("key:%v", string(putResp.PrevKv.Key))
		logrus.Warnf("Value:%v", string(putResp.PrevKv.Value))
		logrus.Warnf("Version:%v", strconv.FormatInt(putResp.PrevKv.Version, 10))
	}

	return serializer.Suc(nil)
}

// 服务器显示控制参数设置
func (s *sDrainageServer) EditDisplay(ctx *gin.Context, req forms.EditDisplayServerReq) serializer.Response {
	marshal, err := json.Marshal(req.ServerIds)
	if err != nil {
		return serializer.DBErr(err.Error(), err)
	}

	if string(marshal) == `[""]` || string(marshal) == "null" {
		marshal = []byte("[]")
	}

	logrus.Warnf("sDrainageServer EditDisplay ServerIds:%v", string(marshal))

	// 新服务器
	kv := clientv3.NewKV(config.Etcd)
	putResp, err := kv.Put(ctx, s.newerServersKey, string(marshal), clientv3.WithPrevKV())
	if err != nil {
		return serializer.DBErr(err.Error(), err)
	}

	logrus.Warnf("Revision newerServersKey:%v", putResp.Header.Revision)
	if putResp.PrevKv != nil {
		logrus.Warnf("key:%v", string(putResp.PrevKv.Key))
		logrus.Warnf("Value:%v", string(putResp.PrevKv.Value))
		logrus.Warnf("Version:%v", strconv.FormatInt(putResp.PrevKv.Version, 10))
	}

	// 最大开放服务器ID
	putResp, err = kv.Put(ctx, s.maxOpendServerIdKey, cast.ToString(req.MaxOpendServerId), clientv3.WithPrevKV())
	if err != nil {
		return serializer.DBErr(err.Error(), err)
	}

	logrus.Warnf("Revision maxOpendServerIdKey:%v, MaxOpendServerId:%v", putResp.Header.Revision, cast.ToString(req.MaxOpendServerId))
	if putResp.PrevKv != nil {
		logrus.Warnf("key:%v", string(putResp.PrevKv.Key))
		logrus.Warnf("Value:%v", string(putResp.PrevKv.Value))
		logrus.Warnf("Version:%v", strconv.FormatInt(putResp.PrevKv.Version, 10))
	}

	// 最大部署服务器ID
	putResp, err = kv.Put(ctx, s.maxDeployServerId, cast.ToString(req.MaxDeployServerId), clientv3.WithPrevKV())
	if err != nil {
		return serializer.DBErr(err.Error(), err)
	}

	logrus.Warnf("Revision maxDeployServerId:%v, MaxDeployServerId:%v", putResp.Header.Revision, cast.ToString(req.MaxDeployServerId))
	if putResp.PrevKv != nil {
		logrus.Warnf("key:%v", string(putResp.PrevKv.Key))
		logrus.Warnf("Value:%v", string(putResp.PrevKv.Value))
		logrus.Warnf("Version:%v", strconv.FormatInt(putResp.PrevKv.Version, 10))
	}
	return serializer.Suc(nil)
}

// 服务器显示控制参数获取
func (s *sDrainageServer) GetDisplay(ctx *gin.Context, req forms.GetDisplayServerReq) serializer.Response {

	var (
		serverIds         []int32
		maxOpendServerId  int32
		maxDeployServerId int32
	)

	// 新服
	kv := clientv3.NewKV(config.Etcd)
	getResp, err := kv.Get(ctx, s.newerServersKey)
	if err != nil {
		return serializer.DBErr(err.Error(), err)
	}

	if len(getResp.Kvs) > 0 {
		if err = json.Unmarshal(getResp.Kvs[0].Value, &serverIds); err != nil {
			return serializer.DBErr(err.Error(), err)
		}
	}

	// 最大开放
	getResp, err = kv.Get(ctx, s.maxOpendServerIdKey)
	if err != nil {
		return serializer.DBErr(err.Error(), err)
	}

	if len(getResp.Kvs) > 0 {
		maxOpendServerId = cast.ToInt32(string(getResp.Kvs[0].Value))
	}

	// 最大部署
	getResp, err = kv.Get(ctx, s.maxDeployServerId)
	if err != nil {
		return serializer.DBErr(err.Error(), err)
	}

	if len(getResp.Kvs) > 0 {
		maxDeployServerId = cast.ToInt32(string(getResp.Kvs[0].Value))
	}

	return serializer.Suc(forms.GetDisplayServerRes{
		ServerIds:         serverIds,
		MaxOpendServerId:  maxOpendServerId,
		MaxDeployServerId: maxDeployServerId,
	})
}

func (s *sDrainageServer) GetWhiteList(ctx *gin.Context, req forms.GetWhiteListServerReq) serializer.Response {
	kv := clientv3.NewKV(config.Etcd)
	getResp, err := kv.Get(ctx, s.whiteListKey)
	if err != nil {
		return serializer.DBErr(err.Error(), err)
	}

	if len(getResp.Kvs) == 0 {
		return serializer.Suc([]int64{})
	}

	var params map[string][]int64

	if err = json.Unmarshal(getResp.Kvs[0].Value, &params); err != nil {
		return serializer.DBErr(err.Error(), err)
	}
	type result struct {
		ServerIds []int64 `json:"server_ids"`
		PlayerIds string  `json:"player_ids"`
	}
	resp := &result{}
	playerIdMap := make(map[int64]struct{})
	//服务器的值都一样 放外边
	var ids []string
	for svrId, playerIds := range params {
		if svrId == "all" {
			resp.ServerIds = append(resp.ServerIds, 0)
			for _, playerId := range playerIds {
				ids = append(ids, strconv.FormatInt(playerId, 10))
			}
			resp.PlayerIds = strings.Join(ids, ",")
			break
		}
		for _, playerId := range playerIds {
			if _, ok := playerIdMap[playerId]; ok {
				continue
			}
			playerIdMap[playerId] = struct{}{}
			ids = append(ids, strconv.FormatInt(playerId, 10))
		}
		parseInt, _ := strconv.ParseInt(svrId, 10, 64)
		resp.ServerIds = append(resp.ServerIds, parseInt)
	}
	resp.PlayerIds = strings.Join(ids, ",")
	logrus.Infof("resp:%+v", resp)
	return serializer.Suc(resp)
}

func (s *sDrainageServer) EditWhiteList(ctx *gin.Context, req forms.EditWhiteListServerReq) serializer.Response {

	orgPlayerIds := strings.Split(req.PlayerIds, `,`)
	var playerIds []int64
	if len(orgPlayerIds) > 0 {
		for _, id := range orgPlayerIds {
			if cast.ToInt64(id) > 0 {
				playerIds = append(playerIds, cast.ToInt64(id))
			}
		}
	}

	params := make(map[string][]int64)
	//是否全选游戏服
	for _, svrId := range req.ServerIds {
		if svrId == 0 {
			//清空并设置
			params = make(map[string][]int64)
			params["all"] = make([]int64, 0)
			break
		}
		params[strconv.Itoa(svrId)] = make([]int64, 0)
	}
	//获取server_option
	var lists []*model.ServerOption
	err := query.Use(config.DB).ServerOption.WithContext(ctx).Scan(&lists)
	if err != nil {
		return serializer.DBErr(err.Error(), err)
	}
	if len(req.ServerIds) == len(lists) {
		params = make(map[string][]int64)
		params["all"] = make([]int64, 0)
	}

	if len(playerIds) != 0 {
		for svrId, _ := range params {
			params[svrId] = playerIds
		}
	}

	marshal, err := json.Marshal(params)
	if err != nil {
		return serializer.DBErr(err.Error(), err)
	}

	logrus.Infof("marshal:%v", string(marshal))

	kv := clientv3.NewKV(config.Etcd)
	putResp, err := kv.Put(ctx, s.whiteListKey, string(marshal), clientv3.WithPrevKV())
	if err != nil {
		return serializer.DBErr(err.Error(), err)
	}

	logrus.Infof("Revision:%+v", putResp)
	if putResp.PrevKv != nil {
		logrus.Warnf("key:%v", string(putResp.PrevKv.Key))
		logrus.Warnf("Value:%v", string(putResp.PrevKv.Value))
		logrus.Warnf("Version:%v", strconv.FormatInt(putResp.PrevKv.Version, 10))
	}

	return serializer.Suc(nil)
}
