package controller

import (
	"encoding/json"
	"fengkuangGameServerJob/dao"
	"fengkuangGameServerJob/model"
	"fengkuangGameServerJob/pkg/app"
	"fengkuangGameServerJob/pkg/errcode"
	"fengkuangGameServerJob/pkg/sdk"
	"fengkuangGameServerJob/service"
	"fengkuangGameServerJob/service/param"
	"fmt"
	"github.com/gin-gonic/gin"
	"sort"
	"strconv"
)

var (
	playerService = service.NewPlayerService()
)

type PlayerController struct {
}

func NewPlayerController() *PlayerController {
	return &PlayerController{}
}

// Login 处理登录
func (p *PlayerController) Login(c *gin.Context) {
	//1 参数
	//1.1 获取请求参数
	var loginParam param.LoginParam
	err := c.ShouldBind(&loginParam)
	if err != nil {
		app.Failed(c, errcode.InvalidParams)
		return
	}
	//1.2 请求参数详细校验
	eCode, err := loginParam.Validate()
	if eCode > 0 {
		app.Failed(c, eCode)
		return
	}
	if err != nil {
		app.Failed(c, errcode.InvalidParams)
		return
	}
	//1.3 版本判断,正式服还是灰度服务
	versionInfo := playerService.GetVersionInfo(loginParam.Version)
	if versionInfo.VersionId == 0 {
		app.Failed(c, errcode.InvalidVersionName)
		return
	}
	//2 获取登录服务器+playerId
	serverId := playerService.GetAppointedServer(loginParam.OpenId)
	tcpInfo := playerService.GetTcpWithPlayerId(loginParam.OpenId, serverId, versionInfo.VersionGrayscale)
	if serverId > 0 {
		playerService.DelAppointedServer(loginParam.OpenId)
	}
	if tcpInfo.TcpId == 0 {
		app.Failed(c, errcode.TcpNotFound)
		return
	}
	//跨服合并tcp了，判断是否有跨服合并tcp(新服一开始是不会开启跨服的)
	if tcpInfo.CrossId > 0 {
		//获取跨服对应的tcp信息,若当前跨服设置了tcp信息，则使用跨服的tcp信息
		crossTcp := playerService.GetTcpByCrossId(tcpInfo.CrossId)
		if crossTcp.TcpId > 0 && crossTcp.Ip != "" {
			tcpInfo.TcpId = crossTcp.TcpId
			tcpInfo.Ip = crossTcp.Ip
		}
	}
	//3 生成令牌
	token := playerService.CacheLoginToken(tcpInfo, loginParam.OpenId)
	//4 返回json信息(字段名称不能改动)
	respMap := gin.H{
		"token":  token,
		"openid": loginParam.OpenId,
		"appid":  loginParam.AppId,
		"tcp":    tcpInfo.Ip,
		"audit":  versionInfo.VersionAudit,
	}
	app.Success(c, respMap)
}

// ServerOnOpen 打开小游戏的时候加载
func (p *PlayerController) ServerOnOpen(c *gin.Context) {
	//1 获取参数+参数校验
	var param param.ServerCommonParam
	err := c.ShouldBind(&param)
	if err != nil {
		app.Failed(c, errcode.InvalidParams)
		return
	}
	wechatChecked := param.Validate(0)
	if wechatChecked.Code != errcode.SUCCESS {
		app.Failed(c, wechatChecked.Code)
		return
	}
	//2 获取区服信息
	//2.1 获取玩家对应的区服信息
	serverInfo := playerService.GetPlayerOwnershipServer(param.OpenId, wechatChecked.Grayscale)
	if serverInfo.ServerId == 0 {
		app.Failed(c, errcode.ServerNotFound)
		return
	}
	//2.2 获取区服一共有多少分组(即分页数量)
	groupNum := playerService.GetServerGroupNum(wechatChecked.Grayscale)
	//3 组装成前端想要的信息
	detail := service.ServerHomePageItem{
		ServerID:    serverInfo.ServerId,
		ServerName:  serverInfo.ServerName,
		RoleLevel:   0,
		RoleName:    "",
		ServerState: serverInfo.RunningStatus,
		IsNew:       playerService.ServerIsNew(serverInfo.OpenAt),
	}
	app.Success(c, gin.H{
		"serverZu":     groupNum,
		"serverDetail": detail,
	})
}

// ServerList 区服列表
func (p *PlayerController) ServerList(c *gin.Context) {
	//1 参数校验
	var listParam param.ServerListParam
	err := c.ShouldBind(&listParam)
	if err != nil {
		app.Failed(c, errcode.InvalidParams)
		return
	}
	wechatChecked := listParam.Validate()
	if wechatChecked.Code != errcode.SUCCESS {
		app.Failed(c, wechatChecked.Code)
		return
	}
	//2 获取区服列表
	lists := make([]*model.PlayerWithServer, 0, 100)
	if listParam.ServerZuID == service.RecommendGroup {
		//推荐服
		recommend := dao.GetRecommendServer(wechatChecked.UserId, wechatChecked.Grayscale)
		lists = append(lists, recommend)
	} else if listParam.ServerZuID == service.MyRoleGroup {
		//我的角色
		myRole := dao.GetMyRoleServer(wechatChecked.UserId, wechatChecked.Grayscale)
		lists = append(lists, myRole...)
	} else {
		//分页服
		size := service.ServerListSize
		paging := dao.GetPagingServer(wechatChecked.UserId, wechatChecked.Grayscale, (listParam.ServerZuID-1)*size, size)
		//按区服倒序
		sort.Slice(paging, func(i, j int) bool {
			return paging[i].Player.ServerId > paging[j].Player.ServerId
		})
		lists = append(lists, paging...)
	}
	//3 组装数据返回
	totalNum := len(lists)
	items := make([]service.ServerHomePageItem, 0, totalNum)
	for i := 0; i < totalNum; i++ {
		tmpNickName := lists[i].NickName
		if tmpNickName == "" && lists[i].PlayerLevel > 0 {
			tmpNickName = fmt.Sprintf("%s%d", service.EmptyName, lists[i].PlayerId)
		}
		tmp := service.ServerHomePageItem{
			ServerID:    lists[i].Player.ServerId,
			ServerName:  lists[i].ServerName,
			RoleLevel:   int(lists[i].PlayerLevel),
			RoleName:    tmpNickName,
			ServerState: lists[i].RunningStatus,
			IsNew:       playerService.ServerIsNew(lists[i].OpenAt),
		}
		items = append(items, tmp)
	}
	app.Success(c, items)
}

// SetAppointedServer 设置进入指定的服
func (p *PlayerController) SetAppointedServer(c *gin.Context) {
	//1 获取参数+参数校验
	var param param.AppointedServerParam
	err := c.ShouldBind(&param)
	if err != nil {
		app.Failed(c, errcode.InvalidParams)
		return
	}
	wechatChecked := param.Validate()
	if wechatChecked.Code != errcode.SUCCESS {
		app.Failed(c, wechatChecked.Code)
		return
	}
	//2 将选服信息写入redis
	playerService.SetAppointedServer(param.OpenId, param.ServerId)
	//3 返回成功给前端
	app.Success(c, gin.H{})
}

// BlackList 禁言/封禁
func (p *PlayerController) BlackList(c *gin.Context) {
	//1 接收参数+参数校验
	flag, err := strconv.Atoi(c.Param("flag"))
	var param service.BlackListParam
	err = c.ShouldBind(&param)
	if err != nil {
		sdk.SYFailed(c, 4001, "invalid params")
		return
	}
	err = param.Validate(flag)
	if err != nil {
		sdk.SYFailed(c, 4001, err.Error())
		return
	}
	// 获取用户所在区服及tcp信息
	server, err := playerService.ValidateServer(param.ServerId)
	if err != nil {
		sdk.SYFailed(c, 4001, "invalid params")
		return
	}
	//2 操作禁言、封禁相关操作
	if flag == 1 {
		//禁言
		playerService.HandlerBlackList1(param, server.ServerGrayscale)
	} else {
		//封禁
		//任务的详细内容
		body := service.BlackListBody{
			PlayerId: param.RoleId,
			OpenId:   param.Openid,
			Type:     param.Type,
			Day:      param.Day,
			Hour:     param.Hour,
		}
		if param.Status == 0 {
			body.Recovery = 1
		}
		bodyBin, _ := json.Marshal(&body)
		tokenSign := playerService.GenTokenSign(param)
		err = playerService.CommonMsgNotify(param.RoleId, server.TcpId, tokenSign, "kick_out", string(bodyBin))
		if err != nil {
			sdk.SYFailed(c, 4001, "封禁操作失败")
			return
		}
	}
	sdk.SYSuccess(c)
}

// IsNew 判断是否是新用户
func (p *PlayerController) IsNew(c *gin.Context) {
	//1 参数校验
	var loginParam param.LoginParam
	err := c.ShouldBind(&loginParam)
	if err != nil {
		app.Failed(c, errcode.InvalidParams)
		return
	}
	eCode, err := loginParam.IsNewValidate()
	if eCode > 0 || err != nil {
		app.Failed(c, errcode.InvalidParams)
		return
	}
	//2 根据openid判断是否是新用户
	isNew := playerService.IsNewOpenid(loginParam.OpenId, loginParam.AppId, loginParam.PlatformType)
	app.Success(c, gin.H{
		"is_new": isNew,
	})
}
