package group_s

import (
	"context"
	"git.hilo.cn/hilo-common/_const/rediskey"
	"git.hilo.cn/hilo-common/domain"
	"github.com/go-redis/redis/v8"
	"hilo-group/_const/enum/gift_e"
	"hilo-group/cv/gift_cv"
	"hilo-group/domain/cache/room_c"
	"hilo-group/domain/model/group_m"
	"hilo-group/domain/model/res_m"
	"sort"
	"strconv"
	"time"
)

func SortGroupCommonCountryList(model *domain.Model) {
	// 常用的国家
	countryMap := map[string]struct{}{"India": {}, "Indonesia": {}, "Iraq": {}, "KSA": {}, "Kuwait": {}, "Pakistan": {}, "Turkey": {}}
	for country, _ := range countryMap {
		sortGroupList, err := GetGroupSortList(model, country)
		if err != nil {
			model.Log.Errorf("SortGroupCommonCountryList err:%v", err)
			return
		}
		// 写入redis
		err = setToRedis(model, country, sortGroupList)
		if err != nil {
			model.Log.Errorf("SortGroupCommonCountryList country:%v, len(sortGroupList):%v, err:%v", country, len(sortGroupList), err)
			return
		}
		time.Sleep(time.Second * 3)
	}
}

func SortGroupNotCommonCountryList(model *domain.Model) {
	// 常用的国家
	countryMap := map[string]struct{}{"India": {}, "Indonesia": {}, "Iraq": {}, "KSA": {}, "Kuwait": {}, "Pakistan": {}, "Turkey": {}}
	// 取所有的国家名字
	allCountryList, err := res_m.GetCountryNameList(model)
	if err != nil {
		model.Log.Errorf("SortGroupNotCommonCountryList err:%v", err)
		return
	}
	for _, country := range allCountryList {
		if _, ok := countryMap[country]; ok {
			continue
		}
		// 计算非常用国家
		sortGroupList, err := GetGroupSortList(model, country)
		if err != nil {
			model.Log.Errorf("SortGroupNotCommonCountryList err:%v", err)
			return
		}
		// 写入redis
		err = setToRedis(model, country, sortGroupList)
		if err != nil {
			model.Log.Errorf("SortGroupNotCommonCountryList country:%v, len(sortGroupList):%v, err:%v", country, len(sortGroupList), err)
			return
		}
		time.Sleep(time.Second * 5)
	}
}

func setToRedis(model *domain.Model, country string, groupList []string) error {
	// 写入redis
	key := rediskey.GetGroupCountrySortList(country)
	for idx, group := range groupList {
		err := model.RedisCluster.ZRemRangeByRank(context.Background(), key, int64(idx), int64(idx)).Err() // 先删除旧的
		if err != nil {
			model.Log.Errorf("setToRedis SortGroup key:%v, idx:%v, err:%v", key, idx, err)
			return err
		}
		// 插入
		err = model.RedisCluster.ZAdd(context.Background(), key, &redis.Z{Score: float64(idx), Member: group}).Err()
		if err != nil {
			model.Log.Errorf("setToRedis SortGroup key:%v, idx:%v, group:%s, err:%v", key, idx, group, err)
			return err
		}
		if idx%1000 == 0 {
			time.Sleep(time.Millisecond * 50)
		}
	}
	return nil
}

// 计算国家群组列表排序
func GetGroupSortList(model *domain.Model, country string) ([]string, error) {
	bannedGroups, err := group_m.GetBannedGroupsMap(model)
	if err != nil {
		return nil, err
	}
	beginTime := time.Now()
	groups, banCount, visitCount, err := GetCandidatesByCountry(model, bannedGroups, country)
	if err != nil {
		return nil, err
	}
	endTime := time.Now()
	model.Log.Infof("GroupCountryListSort: candidates size = %d, takes %d ms banned = %d, visitCount size = %d",
		len(groups), endTime.Sub(beginTime).Milliseconds(), banCount, len(visitCount))

	// 获取麦上有人的所有群组及麦上人数
	micGroupNum, err := group_m.GetMicHasInGroupNum(model)
	if err != nil {
		return nil, err
	}
	model.Log.Infof("GroupCountryListSort, micGroupNum : %v", micGroupNum)
	model.Log.Infof("GroupCountryListSort cost2:%v", time.Now().Sub(beginTime))

	sortedGroupIds := make([]string, 0)
	diamondGroupIds := make([]string, 0)
	for i, _ := range groups {
		// 麦上没人也放出来
		sortedGroupIds = append(sortedGroupIds, i)
		// 麦上有人才计算流水
		if micGroupNum[i] > 0 {
			diamondGroupIds = append(diamondGroupIds, i)
		}
	}

	now := time.Now()
	bTime := now.Add(-time.Minute * 30)
	g := gift_cv.GiftOperate{SceneType: gift_e.GroupSceneType}
	diamonds, err := g.GetRangeConsumeSummaryV2(bTime, now, diamondGroupIds)
	if err != nil {
		return nil, err
	}
	model.Log.Infof("GroupCountryListSort, diamonds in 30 mins: %v", diamonds)
	model.Log.Infof("GroupCountryListSort cost3:%v", time.Now().Sub(beginTime))

	//supportLevels, err := NewGroupService(model.MyContext).GetWeekMaxSupportLevelMap()
	//if err != nil {
	//	return nil, err
	//}
	//model.Log.Infof("GroupCountryListSort, supportLevels : %v", supportLevels)
	model.Log.Infof("GroupCountryListSort cost4:%v", time.Now().Sub(beginTime))

	// 排序优先级2022-07-25
	sort.Slice(sortedGroupIds, func(i, j int) bool {
		gi := sortedGroupIds[i]
		gj := sortedGroupIds[j]

		// 1、按麦上人数多少排序
		if micGroupNum[gi] > micGroupNum[gj] {
			return true
		} else if micGroupNum[gi] < micGroupNum[gj] {
			return false
		}

		// 2、麦上人数相同,按30分钟内送礼钻石数排序
		if diamonds[gi] > diamonds[gj] {
			return true
		} else if diamonds[gi] < diamonds[gj] {
			return false
		}
		// 3. 根据热度排序groupInUserDuration
		if visitCount[gi] > visitCount[gj] {
			return true
		} else if visitCount[gi] < visitCount[gj] {
			return false
		}

		// * Final resort: 群组CODE,短号优先,然后按字母序
		return len(groups[gi].Code) < len(groups[gj].Code) || len(groups[gi].Code) == len(groups[gj].Code) && groups[gi].Code < groups[gj].Code
	})
	model.Log.Infof("GroupCountryListSort cost5:%v", time.Now().Sub(beginTime))
	return sortedGroupIds, nil
}

// 国家群候选:没有密码且没被封禁的群, 有国家
func GetCandidatesByCountry(model *domain.Model, bannedGroups map[string]uint64, country string) (map[string]*group_m.GroupInfo, int, map[string]int64, error) {
	noPwdGroups, err := group_m.FindOwnerCountryGroups(model, country)
	if err != nil {
		return nil, 0, nil, err
	}
	var groupIds []string
	for _, v := range noPwdGroups {
		groupIds = append(groupIds, v.ImGroupId) // imGroupId
	}

	//roomVisitCount, err := room_c.GetAllRoomVisitCount()
	roomVisitCount, err := room_c.MGetRoomVisitCount(groupIds)
	if err != nil {
		return nil, 0, nil, err
	}
	gameRoom := group_m.GetGameGroupsMap(model)

	banCount := 0
	groups := make(map[string]*group_m.GroupInfo, 0)
	visitCount := make(map[string]int64)
	for i, v := range noPwdGroups {
		// 过滤掉被封禁的群
		if bannedGroups[v.ImGroupId] != 0 {
			banCount++
			continue
		}
		// 过滤游戏房
		if gameRoom[v.ImGroupId] {
			continue
		}

		// 先从二级缓存中找
		if c, ok := roomVisitCount[v.ImGroupId]; ok {
			if vc, err := strconv.ParseInt(c, 10, 64); err == nil && vc > 0 {
				//model.Log.Debugf("getPopularCandidates, from roomVisitCount %s(%s) - %d", v.ImGroupId, v.Code, vc)

				groups[v.ImGroupId] = &noPwdGroups[i]
				visitCount[v.ImGroupId] = vc
			}
		} else {
			// 如果没有,就从roomVisit中取
			if vc, err := room_c.GetSetRoomVisitCount(v.ImGroupId); err == nil && vc > 0 {
				model.Log.Infof("getPopularCandidates, from roomVisit %s(%s) - %d", v.ImGroupId, v.Code, vc)

				groups[v.ImGroupId] = &noPwdGroups[i]
				visitCount[v.ImGroupId] = vc
			}
		}
	}
	return groups, banCount, visitCount, nil
}

func GetVisitCount(groupIds []string) (map[string]int64, error) {
	roomVisitCount, err := room_c.MGetRoomVisitCount(groupIds)
	if err != nil {
		return nil, err
	}
	visitCount := make(map[string]int64)
	for _, v := range groupIds {
		// 先从二级缓存中找
		if c, ok := roomVisitCount[v]; ok {
			if vc, err := strconv.ParseInt(c, 10, 64); err == nil && vc > 0 {
				visitCount[v] = vc
			}
		} else {
			// 如果没有,就从roomVisit中取
			if vc, err := room_c.GetSetRoomVisitCount(v); err == nil && vc > 0 {
				visitCount[v] = vc
			}
		}
	}
	return visitCount, nil
}