package jobs

import (
	"context"
	"encoding/json"
	"gadmin/config"
	"gadmin/internal/admin/service"
	"gadmin/internal/gorm/model"
	"gadmin/internal/gorm/query"
	"gadmin/utility"
	"gadmin/utility/player"
	"github.com/jinzhu/now"
	"github.com/sirupsen/logrus"
	"gorm.io/gen"
	"os"
	"sync"
	"time"
)

var RolesCount = new(jRolesCount)

type jRolesCount struct {
	ctx context.Context
}

func (j *jRolesCount) Run() {
	j.ctx = context.TODO()
	logrus.Info("jRolesCount Run.....")
	if os.Getenv("GIN_MODE") == "release" || os.Getenv("ADMIN_IS_LOCAL") == "1" {
		for serverId, _ := range config.GDBGroup {
			j.RolesCount(serverId)
		}
	} else {
		logrus.Warn("非正式环境无需进行，跳过..")
	}
}

var (
	loadRolesLock sync.RWMutex
)

func (j *jRolesCount) RolesCount(serverId int) {
	loadRolesLock.RLock()
	defer loadRolesLock.RUnlock()

	DB, err := player.GetDBByServerID(serverId)
	if err != nil {
		logrus.Warningf("RolesCount GetDBByServerID，err：%v", err)
		return
	}

	// 前一天的日期
	yesterday := now.With(time.Now().AddDate(0, 0, -1))
	var (
		allRoles = make(map[string]map[int64]int64)
		date     = utility.Format(yesterday.Time)
		endUnix  = yesterday.EndOfDay().Unix()
	)
	logrus.Infof("正在统计英雄分布等级，date：%v, Unix:%+v", date, endUnix)

	channelIds, err := service.Channel.Ids()
	if err != nil {
		logrus.Warningf("Channel.Ids，err：%v", err)
		return
	}

	type RolesData struct {
		ID int64
	}

	// 计算渠道玩家
	allRoles["-1"] = make(map[int64]int64)
	for _, channelId := range channelIds {
		if allRoles[channelId] == nil {
			allRoles[channelId] = make(map[int64]int64)
		}

		if channelId == "0" {
			continue
		}
		tmpIds := service.PlayerChannel.PlayerIds(j.ctx, channelId)
		pIds := utility.SpiltInt64BySizeFromInt64(tmpIds, 10000)
		for _, ids := range pIds {

			var results []*model.PlayerMaterial
			u := query.Use(config.GDBGroup[DB]).PlayerMaterial
			err = u.Select(u.ID, u.Roles).Where(u.Playerid.In(ids...)).FindInBatches(&results, 10000, func(tx gen.Dao, batch int) error {
				for _, result := range results {
					var rolesData []RolesData
					if err := json.Unmarshal([]byte(result.Roles), &rolesData); err != nil {
						logrus.Errorf("json.Unmarshal err:%+v", result.Roles)
						continue
					}

					for i := 0; i < len(rolesData); i++ {
						allRoles[channelId][rolesData[i].ID] += 1
						allRoles["-1"][rolesData[i].ID] += 1
					}
				}
				return nil
			})

			if err != nil {
				logrus.Errorf("RolesLog FindInBatches err:%+v", err)
				return
			}

		}
	}

	// 计算自然玩家
	var results []*model.PlayerMaterial
	u := query.Use(config.GDBGroup[DB]).PlayerMaterial
	err = u.Select(u.ID, u.Roles).FindInBatches(&results, 1000, func(tx gen.Dao, batch int) error {
		for _, result := range results {
			var rolesData []RolesData
			if err := json.Unmarshal([]byte(result.Roles), &rolesData); err != nil {
				logrus.Errorf("json.Unmarshal err:%+v", result.Roles)
				continue
			}

			for i := 0; i < len(rolesData); i++ {
				allRoles["0"][rolesData[i].ID] += 1
			}
		}
		return nil
	})
	if err != nil {
		logrus.Errorf("RolesLog FindInBatches err:%+v", err)
		return
	}

	for k, v := range allRoles["-1"] {
		allRoles["0"][k] -= v
	}

	for channelId, collect := range allRoles {
		if channelId == "-1" {
			continue
		}

		str, err := json.Marshal(collect)
		if err != nil {
			logrus.Errorf("RolesLog Save Marshal err:%+v", err)
			return
		}

		reportDao := query.Use(config.DB).RolesLog // 统计表
		arl, _ := reportDao.Where(reportDao.Date.Eq(date), reportDao.ChannelID.Eq(channelId), reportDao.ServerID.Eq(int32(serverId))).FirstOrInit()
		arl.Date = date
		arl.ChannelID = channelId
		arl.ServerID = int32(serverId)
		arl.Collect = string(str)
		if err = reportDao.Save(arl); err != nil {
			logrus.Errorf("RolesLog Save err:%+v", err)
			return
		}
	}

	logrus.Info("统计角色等级完成..")
}
