package game

import (
	"encoding/json"
	"fmt"
	"runtime"
	"server/GoUtil"
	Msg "server/game/mod/msg"
	"server/gamedata"
	"server/msg"
	"server/pkg/github.com/name5566/leaf/gate"
	"server/pkg/github.com/name5566/leaf/log"
	"time"

	"github.com/shirou/gopsutil/cpu"
	"github.com/shirou/gopsutil/mem"
	"google.golang.org/protobuf/proto"
)

var AdminFuncMap = map[string]func([]interface{}) error{
	"ReqAdminInfo":        AdminPlayerInfo,
	"ReqServerInfo":       ReqServerInfo,
	"ReqReloadServerMail": ReqReloadServerMail,
	"ReqReload":           ReqReload,
	"ReqAdminGm":          ReqAdminGm,
}

func AdminProcess(Func string, args []interface{}) {
	if f, ok := AdminFuncMap[Func]; ok {
		err := f(args)
		if err != nil {
			log.Debug("AdminProcess error: %v", err)
		}
		return
	}
	log.Debug("AdminProcess error: %v", "Func not found")
}

func AdminPlayerInfo(args []interface{}) error {
	a, buf := ParseAdminArgs(args)
	req := &msg.ReqAdminInfo{}
	proto.Unmarshal(buf, req)
	player := G_GameLogicPtr.GetPlayer(req.Uid)
	if player == nil {
		player = new(Player)
		player.M_DwUin = req.Uid
		player.InitPlayerOnly()
		player.ZeroUpdate(nil)
	}
	res := make(map[string]interface{})
	res["Name"] = player.PlayMod.getBaseMod().NickName
	res["Uid"] = player.M_DwUin
	res["AreaId"] = player.PlayMod.getDecorateMod().GetAreaId()
	res["Charge"] = player.PlayMod.getChargeMod().Charge
	res["Level"] = player.GetPlayerBaseMod().GetLevel()
	res["Diamond"] = player.GetPlayerBaseMod().GetDiamond()
	res["Star"] = player.GetPlayerBaseMod().GetStar()
	res["Energy"] = player.GetPlayerBaseMod().GetEnergy()
	res["Diamond"] = player.GetPlayerBaseMod().GetDiamond()
	res["Mac"] = player.GetPlayerBaseMod().GetName()
	res["Login"] = player.GetPlayerBaseMod().Data.LoginTime
	res["Cumulative"] = player.PlayMod.getBaseMod().Cumulative
	res["TodayCumulative"] = player.PlayMod.getBaseMod().TodayCumulative
	res["Bonus"] = player.PlayMod.getLimitedTimeEventMod().Progress
	OrderMap := make(map[int]interface{})
	Index := 0
	for k, v := range player.PlayMod.getOrderMod().OrderList {
		OrderMap[Index] = map[string]interface{}{
			"Id":      k,
			"Type":    v.Type,
			"Time":    v.Timestamp,
			"ChessId": GoUtil.IntSliceToString(v.MergeId),
			"Diff":    v.Diff,
		}
		Index++
	}
	res["Order"] = OrderMap
	AdminPlayerBack(a, res)
	return nil
}

func AdminPlayerBack(a gate.Agent, res map[string]interface{}) {
	JsonBuff, _ := json.Marshal(res)
	response := &msg.AdminRes{}
	response.Func = "admin"
	response.Info = JsonBuff
	a.WriteMsg(response)
}

func ReqServerInfo(args []interface{}) error {
	a, _ := ParseAdminArgs(args)
	res := make(map[string]interface{})
	res["PlayerNum"] = G_GameLogicPtr.GetPlayerNum()
	res["StartTime"] = G_GameLogicPtr.GetStartTime()
	var m runtime.MemStats
	runtime.ReadMemStats(&m)
	res["TotalAlloc"] = fmt.Sprintf("%dM", m.TotalAlloc/(1024*1024))
	// 2. 获取系统内存使用信息
	vmStat, err := mem.VirtualMemory()
	if err == nil {
		res["Sys"] = fmt.Sprintf("%.2f%%", vmStat.UsedPercent)
	}
	// 3. 获取 CPU 使用率（一秒内采样）
	cpuPercent, err := cpu.Percent(time.Second, false)
	if err == nil && len(cpuPercent) > 0 {
		res["CPU"] = fmt.Sprintf("%.2f%%", cpuPercent[0])
	}
	AdminPlayerBack(a, res)
	return nil
}

func ReqReloadServerMail(args []interface{}) error {
	G_GameLogicPtr.MailMgrCall(&Msg.Msg{Type: Msg.HANDLE_TYPE_MAIL_RELOAD})
	G_GameLogicPtr.NotifyAll(&Msg.Msg{Type: Msg.HANDLE_TYPE_MAIL})
	return nil
}

func ReqReload(args []interface{}) error {
	a, _ := ParseAdminArgs(args)
	gamedata.Reload()
	res := make(map[string]interface{})
	res["Code"] = 0
	AdminPlayerBack(a, res)
	return nil
}

func ReqAdminGm(args []interface{}) error {
	a, buf := ParseAdminArgs(args)
	req := &msg.ReqAdminGm{}
	proto.Unmarshal(buf, req)
	res := make(map[string]interface{})
	res["Code"] = 0
	res["Msg"] = "ok"
	player := G_GameLogicPtr.GetPlayer(req.Uid)
	if player == nil {
		res["Code"] = 1
		res["Msg"] = "player not found"
		AdminPlayerBack(a, res)
		return nil
	}
	player.lock.Lock()
	defer player.lock.Unlock()
	err := ReqGmCommand_(player, req.Command)

	if err != nil {
		res["Code"] = 1
		res["Msg"] = err.Error()
	}
	if err != nil {
		res["Code"] = 1
		res["Msg"] = err.Error()
		AdminPlayerBack(a, res)
		return err
	}
	AdminPlayerBack(a, res)
	return nil
}
