package gm_services

import (
	"encoding/json"
	"errors"
	"fmt"
	"gadmin/config"
	"gadmin/internal/admin/consts"
	"gadmin/internal/admin/forms"
	"gadmin/internal/admin/gm_rpc/rpc_share"
	"gadmin/internal/gorm/model"
	"gadmin/internal/gorm/query"
	"gadmin/utility"
	"gadmin/utility/character"
	"gadmin/utility/player"
	"gadmin/utility/serializer"
	"gadmin/utility/token"
	"leafstalk/covenant/msg"
	"os"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
)

func DeleteUserAccount(ctx *gin.Context, playerID int64) (err error) {
	if playerID == 0 {
		return errNoUser
	}

	attr, err := player.GetAttrByUserId(playerID)
	if err != nil {
		return
	}
	DB, err := player.GetDBByPlayerAttr(attr)
	if err != nil {
		return
	}

	msgs := msg.GmDelPlayer{
		MsgId:      character.GenerateMsgId(),
		PlayerID:   playerID,
		OperatorId: token.GetUID(ctx),
	}
	//err = gate.SendToWorld(0, &msgs)
	//if err == nil {
	//}
	rpc_share.MsgMap[msgs.MsgId] = fmt.Sprintf("%s,GM操作删除玩家[%d]", utility.FormatSecond(time.Now()), playerID)

	var resp *msg.ResponseGmDelPlayer
	res, err := config.GmNats.GmRequest(DB, "GmDelPlayer", msgs)
	if err != nil {
		return
	}

	if err = json.Unmarshal(res, &resp); err != nil {
		return
	}

	rpc_share.LogChan <- rpc_share.LogMsg{
		MsgID: msgs.MsgId,
		Data:  resp,
	}

	return
}

func DeleteAccount(ctx *gin.Context, accId int64) (err error) {
	if accId == 0 {
		return errNoUser
	}

	account, err := player.GetAccountByAccId(accId)
	if err != nil {
		return
	}

	msgs := msg.GmDelAccountId{
		MsgId: character.GenerateMsgId(),
		AccId: account.AccID,
	}

	res, err := config.GmNats.GmLoginServRequest("GmDelAccountId", msgs)
	if err != nil {
		return
	}

	var resp *msg.ResponseGmDelAccountId
	if err = json.Unmarshal(res, &resp); err != nil {
		return
	}
	//删除成功 记录日志
	logrus.Warnf("DeleteAccount account:%+v\n", account)

	rpc_share.MsgMap[msgs.MsgId] = fmt.Sprintf("%s,GM操作删除玩家账号[%d]", utility.FormatSecond(time.Now()), account.AccID)

	rpc_share.LogChan <- rpc_share.LogMsg{
		MsgID: msgs.MsgId,
		Data:  resp,
	}

	return
}

func OpenAccount(accId int64) (err error) {
	if os.Getenv("GIN_MODE") == "release" {
		err = errors.New("正式服环境不允许该操作，请将联系服务端将账号数据拷贝至测试服！")
		return err
	}

	getUserAccount := func() (*model.UserAccount, string) {
		var models *model.UserAccount
		config.LDB.Model("user_account_1").Where("accId = ?", accId).Scan(&models)
		if models != nil {
			return models, "user_account_1"
		}

		config.LDB.Model("user_account_2").Where("accId = ?", accId).Scan(&models)
		if models != nil {
			return models, "user_account_2"
		}
		return nil, ""
	}

	row, tab := getUserAccount()
	if row == nil {
		err = errors.New("账号不存在！")
		return err
	}

	if row.Account != "" {
		err = errors.New("该玩家已存在账号！")
		return err
	}

	tx := config.LDB.Model(tab).Where("accId = ?", accId).Updates(model.UserAccount{
		Openid:     fmt.Sprintf("account@u%v", accId),
		Account:    fmt.Sprintf("u%v", accId),
		Password:   "202cb962ac59075b964b07152d234b70", // 123
		Platopenid: fmt.Sprintf("u%v", accId),
	})

	if tx.Error != nil {
		logrus.WithField("OpenAccount ", accId).Errorln(err.Error())
		return
	}

	//info, err := dao.Where(dao.ID.Eq(playerID)).Updates(model.UserAccount{
	//	Openid:     fmt.Sprintf("account@u%v", playerID),
	//	Account:    fmt.Sprintf("u%v", playerID),
	//	Password:   "202cb962ac59075b964b07152d234b70", // 123
	//	Platopenid: fmt.Sprintf("u%v", playerID),
	//})
	//
	//if err != nil {
	//	logrus.WithField("OpenAccount", playerID).Errorln(err.Error())
	//	return
	//} else {
	//	data, _ := json.Marshal(row)
	//	logrus.WithField("OpenAccount", playerID).Infoln(info.RowsAffected, string(data))
	//}
	//if info.RowsAffected == 0 {
	//	err = errors.New("未找到该用户")
	//}
	return
}

// 获取玩家游戏数据异常列表
func AlarmGameDataList(ctx *gin.Context, req forms.AlarmGameDataListReq) serializer.Response {
	var result forms.AlarmGameDataListResp
	alarmModel := query.Use(config.DB).GameDataAlarm
	alarmQuery := alarmModel.WithContext(ctx)

	if req.UserID != 0 {
		alarmQuery = alarmQuery.Where(alarmModel.PlayerID.Eq(req.UserID))
	}
	if len(req.CreatedAt) == 2 {
		alarmQuery = alarmQuery.Where(alarmModel.CreatedAt.Between(time.Unix(req.CreatedAt[0], 0), time.Unix(req.CreatedAt[1], 0)))
	}

	//count
	count, err := alarmQuery.Count()
	if err != nil {
		return serializer.Err(consts.CodeParamErr, err.Error(), err)
	}
	if count == 0 {
		return serializer.Suc(result)
	}

	_, limit, offset := forms.CalculatePage(req.Page, req.PerPage)
	list, err := alarmQuery.
		Order(alarmModel.CreatedAt.Desc()).
		Limit(int(limit)).
		Offset(int(offset)).
		Find()
	if err != nil {
		return serializer.Err(consts.CodeParamErr, err.Error(), err)
	}

	//封禁状态
	uIdMap := make(map[int][]int64)
	for _, item := range list {
		uIdMap[req.ServerID] = append(uIdMap[req.ServerID], item.PlayerID)
	}
	uInfoMap := make(map[int64]*model.PlayerAttr)
	accIds := make([]int64, 0)
	for svrId, uIds := range uIdMap {
		playerAttrModel := query.Use(config.GDBGroup[svrId]).PlayerAttr
		userList, err := playerAttrModel.WithContext(ctx).Select(playerAttrModel.ID, playerAttrModel.ServerID, playerAttrModel.Playerid, playerAttrModel.AccID).Where(playerAttrModel.Playerid.In(uIds...)).Find()
		if err != nil {
			return serializer.Err(consts.CodeParamErr, err.Error(), err)
		}
		for _, item := range userList {
			uInfoMap[item.AccID] = item
			accIds = append(accIds, item.AccID)
		}
	}
	//根据accId获取表名字
	tableMap := make(map[string][]int64)
	for _, accId := range accIds {
		tableName := model.GetAccountTable(accId, "user_account")
		tableMap[tableName] = append(tableMap[tableName], accId)
	}
	//取account
	accMap := make(map[int64]int)
	for tableName, accIds := range tableMap {
		accounts := make([]*model.UserAccount, 0)
		err = config.LDB.Table(tableName).Select([]string{"id", "accId", "ban"}).Where("accId in ?", accIds).Find(&accounts).Error
		if err != nil {
			return serializer.Err(consts.CodeParamErr, err.Error(), err)
		}
		//处理account
		for _, item := range accounts {
			accMap[item.AccID] = int(item.Ban)
		}
	}
	//处理封禁信息
	uBanMap := make(map[int64]int)
	for accId, isBan := range accMap {
		uBanMap[uInfoMap[accId].Playerid] = isBan
	}

	res := make([]*forms.AlarmGameDataInfo, 0)
	for _, item := range list {
		res = append(res, &forms.AlarmGameDataInfo{
			ID:        item.ID,
			PlayerID:  item.PlayerID,
			Attrs:     item.Attrs,
			ServerID:  int32(req.ServerID),
			Msg:       item.Msg,
			Time:      item.Time,
			Module:    item.Module,
			CreatedAt: item.CreatedAt,
			Ban:       uBanMap[item.PlayerID],
		})
	}

	result.List = res
	result.Page = req.Page
	result.PerPage = req.PerPage
	result.PageCount = (count + req.PerPage - 1) / req.PerPage
	return serializer.Suc(result)
}

func AlarmAttrList(ctx *gin.Context, req forms.AlarmAttrReq) serializer.Response {
	var result forms.AlarmAttrResp
	/*alarmModel := query.Use(config.DB).GameCharacterDataAnomaly
	alarmQuery := alarmModel.WithContext(ctx)

	if len(req.Time) == 2 {
		alarmQuery = alarmQuery.Where(alarmModel.CreatedAt.Between(time.Unix(req.Time[0], 0), time.Unix(req.Time[1], 0)))
	}
	if req.ChapterID >= 0 {
		alarmQuery = alarmQuery.Where(alarmModel.ChapterID.Eq(int32(req.ChapterID)))
	}
	if req.RoomID >= 0 {
		alarmQuery = alarmQuery.Where(alarmModel.RoomID.Eq(int32(req.RoomID)))
	}
	if req.Level >= 0 {
		alarmQuery = alarmQuery.Where(alarmModel.Level.Eq(int32(req.Level)))
	}
	serverId := model2.ExtractLineId(req.UserID)
	alarmQuery = alarmQuery.Where(alarmModel.UserID.Eq(req.UserID)).Where(alarmModel.ServerID.Eq(int32(serverId)))
	//count
	count, err := alarmQuery.Count()
	if err != nil {
		return serializer.Err(consts.CodeParamErr, err.Error(), err)
	}
	if count == 0 {
		return serializer.Suc(result)
	}

	_, limit, offset := forms.CalculatePage(req.Page, req.PerPage)
	list, err := alarmQuery.
		Order(alarmModel.CreatedAt.Desc()).
		Limit(int(limit)).
		Offset(int(offset)).
		Find()
	if err != nil {
		return serializer.Err(consts.CodeParamErr, err.Error(), err)
	}

	result.List = list
	result.Page = req.Page
	result.PerPage = req.PerPage
	result.PageCount = (count + req.PerPage - 1) / req.PerPage*/
	return serializer.Suc(result)
}

func AlarmCheatingList(ctx *gin.Context, req forms.AlarmCheatingReq) serializer.Response {
	var result forms.AlarmGameDataListResp
	cheatingModel := query.Use(config.DB).GameAlarmCombatLog
	cheatingQuery := cheatingModel.WithContext(ctx)

	if req.ServerId != 0 {
		cheatingQuery = cheatingQuery.Where(cheatingModel.ServerID.Eq(int32(req.ServerId)))
	}
	if req.PlayerId != 0 {
		cheatingQuery = cheatingQuery.Where(cheatingModel.PlayerID.Eq(req.PlayerId))
	}
	if req.YearMonth != 0 {
		cheatingQuery = cheatingQuery.Where(cheatingModel.YearMonth.Eq(strconv.FormatInt(req.YearMonth, 10)))
	}
	if len(req.OriginTime) != 0 {
		cheatingQuery = cheatingQuery.Where(cheatingModel.OriginTime.Between(strconv.FormatInt(req.OriginTime[0], 10), strconv.FormatInt(req.OriginTime[1], 10)))
	}
	if req.Ratio != 0 {
		cheatingQuery = cheatingQuery.Where(cheatingModel.Ratio.Gte(req.Ratio))
	}
	//count
	count, err := cheatingQuery.Count()
	if err != nil {
		return serializer.Err(consts.CodeParamErr, err.Error(), err)
	}
	if count == 0 {
		return serializer.Suc(result)
	}
	_, limit, offset := forms.CalculatePage(req.Page, req.PerPage)
	list, err := cheatingQuery.
		Order(cheatingModel.OriginTime.Desc()).
		Limit(int(limit)).
		Offset(int(offset)).
		Find()
	if err != nil {
		return serializer.Err(consts.CodeParamErr, err.Error(), err)
	}
	//获取player_id,server_id
	find, err := cheatingModel.Select(cheatingModel.PlayerID, cheatingModel.ServerID).Group(cheatingModel.PlayerID).Find()
	if err != nil {
		return serializer.Err(consts.CodeParamErr, err.Error(), err)
	}
	//封禁状态
	uIdMap := make(map[int][]int64)
	for _, item := range find {
		uIdMap[int(item.ServerID)] = append(uIdMap[int(req.ServerId)], item.PlayerID)
	}
	uInfoMap := make(map[int64]*model.PlayerAttr)
	accIds := make([]int64, 0)
	for svrId, uIds := range uIdMap {
		playerAttrModel := query.Use(config.GDBGroup[svrId]).PlayerAttr
		userList, err := playerAttrModel.WithContext(ctx).Select(playerAttrModel.ID, playerAttrModel.ServerID, playerAttrModel.Playerid, playerAttrModel.AccID).Where(playerAttrModel.Playerid.In(uIds...)).Find()
		if err != nil {
			return serializer.Err(consts.CodeParamErr, err.Error(), err)
		}
		for _, item := range userList {
			uInfoMap[item.AccID] = item
			accIds = append(accIds, item.AccID)
		}
	}
	//根据accId获取表名字
	tableMap := make(map[string][]int64)
	for _, accId := range accIds {
		tableName := model.GetAccountTable(accId, "user_account")
		tableMap[tableName] = append(tableMap[tableName], accId)
	}
	//取account
	accMap := make(map[int64]int)
	for tableName, accIds := range tableMap {
		accounts := make([]*model.UserAccount, 0)
		err = config.LDB.Table(tableName).Select([]string{"id", "accId", "ban"}).Where("accId in ?", accIds).Find(&accounts).Error
		if err != nil {
			return serializer.Err(consts.CodeParamErr, err.Error(), err)
		}
		//处理account
		for _, item := range accounts {
			accMap[item.AccID] = int(item.Ban)
		}
	}
	//处理封禁信息
	uBanMap := make(map[int64]int)
	for accId, isBan := range accMap {
		uBanMap[uInfoMap[accId].Playerid] = isBan
	}

	res := make([]*forms.AlarmCheatingInfo, 0)
	for _, item := range list {
		res = append(res, &forms.AlarmCheatingInfo{
			ID:         item.ID,
			OriginId:   item.OriginID,
			OriginTime: item.OriginTime,
			YearMonth:  item.YearMonth,
			PlayerId:   item.PlayerID,
			ServerId:   int(item.ServerID),
			Dps:        item.Dps,
			Rate:       item.Rate,
			Valuation:  item.Valuation,
			Damage:     item.Damage,
			Ratio:      item.Ratio,
			RoleInfo:   item.RoleInfo,
			AlarmData:  item.AlarmData,
			Ban:        uBanMap[item.PlayerID],
		})
	}

	result.List = res
	result.Page = req.Page
	result.PerPage = req.PerPage
	result.PageCount = (count + req.PerPage - 1) / req.PerPage
	return serializer.Suc(result)
}
