package main

import (
	"flag"
	"fmt"
	jsoniter "github.com/json-iterator/go"
	mhayaHttp "github.com/mhaya/extend/http"
	"github.com/mhaya/game/game_cluster/internal/code"
	"github.com/mhaya/game/game_cluster/internal/param"
	mhayaLogger "github.com/mhaya/logger"
	"math/rand"
	"strconv"
	"sync"
	"time"
)

func main() {

	// 定义命令行标志
	userOffset := flag.Int("userOffset", 500000, "用户偏移量")
	count := flag.Int("count", 100000, "请求总数")
	qps := flag.Int("qps", 500, "最大并发数")
	url := flag.String("url", "http://127.0.0.1:20000", "请求url")
	url1 := flag.String("url1", "http://127.0.0.1:20001", "请求url")
	url2 := flag.String("url2", "http://127.0.0.1:20002", "请求url")
	url3 := flag.String("url3", "http://127.0.0.1:20003", "请求url")
	duration := flag.Int("duration", 120, "测试持续时间")
	flag.Parse()

	startTime := time.Now()
	var wg sync.WaitGroup
	wg.Add(*count)
	// 创建一个 channel 来控制请求的速率
	reqCh := make(chan struct{}, *qps)

	// 控制请求速率的 goroutine
	go func() {
		ticker := time.NewTicker(time.Second / time.Duration(*qps))
		defer ticker.Stop()
		for range ticker.C {
			reqCh <- struct{}{}
		}
	}()

	// 发送请求的 goroutine
	go func() {
		for i := *userOffset; i < *count+*userOffset; i++ {
			<-reqCh
			go func() {
				defer wg.Done()
				str := strconv.Itoa(i)
				account := &param.LoginReq{
					Pid:      2,
					OpenID:   str,
					Platform: "ios",
					Channel:  "tg",
				}
				n := rand.Intn(1)
				switch n {
				case 0:
					RunRobot(*url, account, i)
				case 1:
					RunRobot(*url1, account, i)
				case 2:
					RunRobot(*url2, account, i)
				case 3:
					RunRobot(*url3, account, i)
				}

			}()
		}
	}()

	// 等待所有请求完成
	wg.Wait()
	fmt.Println("All goroutines have finished.")
	qpsAchieved := float64(*count) / time.Since(startTime).Seconds()
	fmt.Printf("Sent %d requests in %v, achieved QPS: %.2f\n", *count, duration, qpsAchieved)
}

func RunRobot(url string, val *param.LoginReq, num int) {
	fmt.Println("start goroutines i:%v", num)
	token := RegisterDevAccount(url, val)
	if token == "" {
		return
	}
	params := map[string]interface{}{
		"nickName": "guest" + val.OpenID,
	}
	rs := Login(url, params, token)
	if !code.IsFail(rs) {
		start(val, token, url)
	}

	//singInList(val, token, url)
	//singIn(val, token,url)
}

func RegisterDevAccount(url string, val *param.LoginReq) string {
	requestURL := fmt.Sprintf("%s/auth", url)

	params := map[string]interface{}{
		"pid":      val.Pid,
		"openid":   val.OpenID,
		"platform": val.Platform,
		"channel":  val.Channel,
	}
	jsonBytes, _, err := mhayaHttp.PostJSON(requestURL, params)
	if err != nil {
		mhayaLogger.Warn(err)
		return ""
	}

	rsp := &code.Result{}
	err = jsoniter.Unmarshal(jsonBytes, rsp)
	if err != nil {
		mhayaLogger.Warn(err)
		return ""
	}
	if rsp.Code == 0 {
		mhayaLogger.Debugf("register account = %v, result = %v", val.OpenID, rsp)
		return rsp.Data.(string)
	}
	return ""
}

func start(val *param.LoginReq, token string, url string) {
	requestURL := fmt.Sprintf("%s/start", url)

	params := map[string]interface{}{
		"pid":    val.Pid,
		"openId": val.OpenID,
	}
	execute("start", requestURL, params, token)
}

func singInList(val *param.LoginReq, token string, url string) {
	requestURL := fmt.Sprintf("%s/signInList", url)
	params := map[string]interface{}{}

	execute("signInList", requestURL, params, token)
}

func singIn(val *param.LoginReq, token string, url string) {
	requestURL := fmt.Sprintf("%s/signIn", url)
	params := map[string]interface{}{}

	execute("signIn", requestURL, params, token)
}

func rank(val *param.LoginReq, token string, url string) {
	requestURL := fmt.Sprintf("%s/rank", url)

	params := map[string]interface{}{
		"id": 1,
		"tp": 1,
	}
	execute("rank", requestURL, params, token)
}

func inviteRewardRatio(val *param.LoginReq, token string, url string) {
	requestURL := fmt.Sprintf("%s/inviteRewardRatio", url)

	params := map[string]interface{}{}
	execute("inviteRewardRatio", requestURL, params, token)
}

func inviteNodeReward(val *param.LoginReq, token string, url string) {
	requestURL := fmt.Sprintf("%s/inviteNodeReward", url)

	params := map[string]interface{}{}
	execute("inviteNodeReward", requestURL, params, token)
}

func itemWeekRecord(val *param.LoginReq, token string, url string) {
	requestURL := fmt.Sprintf("%s/itemWeekRecord", url)

	params := map[string]interface{}{}
	execute("itemWeekRecord", requestURL, params, token)
}

func inviteRewardRatioHistory(val *param.LoginReq, token string, url string) {
	requestURL := fmt.Sprintf("%s/inviteRewardRatioHistory", url)

	params := map[string]interface{}{}
	execute("inviteRewardRatioHistory", requestURL, params, token)
}

func countryRank(val *param.LoginReq, token string, url string) {
	requestURL := fmt.Sprintf("%s/countryRank", url)

	params := map[string]interface{}{}
	execute("countryRank", requestURL, params, token)
}

func claim(val *param.LoginReq, token string, url string) {
	requestURL := fmt.Sprintf("%s/claim", url)

	params := map[string]interface{}{}
	execute("claim", requestURL, params, token)
}

func Login(url string, params map[string]interface{}, token string) int32 {
	requestURL := fmt.Sprintf("%s/login", url)
	jsonBytes, err := mhayaHttp.PostJSONWithHeader(requestURL, params, token)
	if err != nil {
		mhayaLogger.Warnf("login err: %v", err)
		return 1
	}

	rsp := &code.Result{}
	err = jsoniter.Unmarshal(jsonBytes, rsp)
	if err != nil {
		mhayaLogger.Warnf("login Unmarshal err :%v ", err)
		return 1
	}
	if rsp.Code == 0 {
		mhayaLogger.Debugf("Login OK : %v", rsp.Code)
		return 0
	} else {
		mhayaLogger.Debugf("Login Fail : %v", rsp.Code)
	}
	return 1
}

func execute(handler string, url string, params map[string]interface{}, token string) {
	//requestURL := fmt.Sprintf("%s/start", url)
	jsonBytes, err := mhayaHttp.PostJSONWithHeader(url, params, token)
	if err != nil {
		mhayaLogger.Warn(err)
		return
	}

	rsp := &code.Result{}
	err = jsoniter.Unmarshal(jsonBytes, rsp)
	if err != nil {
		mhayaLogger.Warn(err)
		return
	}

	mhayaLogger.Debugf("%s  parms =%v", handler, params)
	mhayaLogger.Debugf("%s  rsp =%v", handler, rsp)
}

func Invite(url string, params map[string]interface{}, token string) {
	requestURL := fmt.Sprintf("%s/invite", url)
	jsonBytes, err := mhayaHttp.PostJSONWithHeader(requestURL, params, token)
	if err != nil {
		mhayaLogger.Warn(err)
		return
	}

	rsp := &code.Result{}
	err = jsoniter.Unmarshal(jsonBytes, rsp)
	if err != nil {
		mhayaLogger.Warn(err)
		return
	}
	mhayaLogger.Debugf("Invite %v", params)
}

//func RunRobot1(url, pid, userName, password, addr string, serverId int32, printLog bool) *Robot {
//	// 创建客户端
//	cli := New(
//		pomeloClient.New(
//			pomeloClient.WithRequestTimeout(10*time.Second),
//			pomeloClient.WithErrorBreak(true),
//		),
//	)
//	cli.PrintLog = printLog
//
//	// 登录获取token
//	if err := cli.GetToken(url, pid, userName, password); err != nil {
//		mhayaLogger.Error(err)
//		return nil
//	}
//
//	// 根据地址连接网关
//	if err := cli.ConnectToTCP(addr); err != nil {
//		mhayaLogger.Error(err)
//		return nil
//	}
//
//	if cli.PrintLog {
//		mhayaLogger.Infof("tcp connect %s is ok", addr)
//	}
//
//	// 随机休眠
//	cli.RandSleep()
//
//	// 用户登录到游戏节点
//	err := cli.UserLogin(serverId)
//	if err != nil {
//		mhayaLogger.Warn(err)
//		return nil
//	}
//
//	if cli.PrintLog {
//		mhayaLogger.Infof("user login is ok. [user = %s, serverId = %d]", userName, serverId)
//	}
//
//	//cli.RandSleep()
//
//	// 查看是否有角色
//	err = cli.PlayerSelect()
//	if err != nil {
//		mhayaLogger.Warn(err)
//		return nil
//	}
//
//	//cli.RandSleep()
//
//	// 创建角色
//	err = cli.ActorCreate()
//	if err != nil {
//		mhayaLogger.Warn(err)
//		return nil
//	}
//
//	//cli.RandSleep()
//
//	// 角色进入游戏
//	err = cli.ActorEnter()
//	if err != nil {
//		mhayaLogger.Warn(err)
//		return nil
//	}
//
//	elapsedTime := cli.StartTime.DiffInMillisecond(mhayaTime.Now())
//	mhayaLogger.Debugf("[%s] is enter to database. elapsed time:%dms", cli.TagName, elapsedTime)
//
//	//cli.Disconnect()
//
//	return cli
//}
