package group_r

import (
	"fmt"
	"git.hilo.cn/hilo-common/domain"
	"git.hilo.cn/hilo-common/mycontext"
	"git.hilo.cn/hilo-common/resource/mysql"
	"git.hilo.cn/hilo-common/rpc"
	"git.hilo.cn/hilo-common/utils"
	"github.com/gin-gonic/gin"
	"hilo-group/_const/enum/gift_e"
	"hilo-group/_const/enum/group_e"
	"hilo-group/_const/enum/online_e"
	"hilo-group/cv/gift_cv"
	"hilo-group/cv/group_cv"
	"hilo-group/cv/group_power_cv"
	"hilo-group/cv/medal_cv"
	"hilo-group/cv/user_cv"
	"hilo-group/domain/cache/res_c"
	"hilo-group/domain/cache/room_c"
	"hilo-group/domain/model/game_m"
	"hilo-group/domain/model/group_m"
	"hilo-group/domain/model/noble_m"
	"hilo-group/domain/model/res_m"
	"hilo-group/domain/model/rocket_m"
	"hilo-group/domain/model/tim_m"
	"hilo-group/domain/model/user_m"
	"hilo-group/domain/service/group_s"
	"hilo-group/myerr"
	"hilo-group/myerr/bizerr"
	"hilo-group/req"
	"hilo-group/resp"
	"sort"
	"strconv"
	"time"
)

// @Tags 群组
// @Summary 查询热门群组
// @Accept application/x-www-form-urlencoded
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param pageSize query int false "分页大小 默认:10" default(10)
// @Param pageIndex query int false "第几个分页,从1开始 默认:1" default(1)
// @Success 200 {object} group_cv.PopularGroupInfo
// @Router /v1/imGroup/popular [get]
func GetPopularGroups(c *gin.Context) (*mycontext.MyContext, error) {
	start := time.Now()
	myContext := mycontext.CreateMyContext(c.Keys)

	pageSize, err := strconv.Atoi(c.Query("pageSize"))
	if err != nil || pageSize <= 0 {
		pageSize = 10
	}
	pageIndex, err := strconv.Atoi(c.Query("pageIndex"))
	if err != nil || pageIndex <= 0 {
		pageIndex = 1
	}

	myUserId, _, _, _, myCountry, err := req.GetUserEx(c, myContext)
	if err != nil {
		return myContext, err
	}

	model := domain.CreateModelContext(myContext)
	/* 2022-06-30 老板说先不分区
	regions, err := res_m.GetAllLangRegion(model)
	if err != nil {
		return myContext, err
	}
	myRegion := regions[myCountry]
	model.Log.Infof("GetPopularGroups: user %d, name = %s, country = %s, region = %s", myUserId, myNick, myCountry, myRegion)
	*/
	bannedGroups, err := group_m.GetBannedGroupsMap(model)
	if err != nil {
		return myContext, err
	}

	gs := group_m.GroupSetting{IsHidden: true}
	hiddenGroups, _ := gs.GetHidden(model.Db)
	if err != nil {
		return myContext, err
	}
	model.Log.Infof("GetPopularGroups: page size = %d, page index = %d, banMap %v, hidenMap %v,cost:%v", pageSize, pageIndex, bannedGroups, hiddenGroups, time.Now().Sub(start))

	hotGroupList := make([]group_m.GroupInfo, 0)

	// 获取麦上有人的所有群组及麦上人数	v10,只有麦上有人的能上热门
	micGroupNum, err := group_m.GetMicHasInGroupNum(model)
	if err != nil {
		return myContext, err
	}
	model.Log.Infof("GetMicHasInGroupNum: cost %v", time.Now().Sub(start))

	banCount := 0
	hiddenCount := 0
	groupIds := make([]string, 0)
	for i := range micGroupNum {
		// 过滤掉被封禁的群
		if bannedGroups[i] != 0 {
			banCount++
			continue
		}
		// 过滤掉被隐藏的群
		if _, exist := hiddenGroups[i]; exist {
			hiddenCount++
			continue
		}
		groupIds = append(groupIds, i)
	}
	model.Log.Infof("GetPopularGroups, micGroupNum: %v, banned %d, hidden %d,cost:%v", micGroupNum, banCount, hiddenCount, time.Now().Sub(start))

	// 3. 处理置顶群
	topGroupIds, err := getTopGroups(model, bannedGroups, hiddenGroups)
	if err != nil {
		return myContext, err
	}

	sortedGroupIds := make([]string, 0)
	for _, i := range groupIds {
		found := false
		for _, j := range topGroupIds {
			if i == j {
				found = true
				break
			}
		}
		// 已经在置顶群范围内的跳过
		if !found {
			sortedGroupIds = append(sortedGroupIds, i)
		}
	}

	groupIds = append(groupIds, topGroupIds...)
	groups, err := group_m.BatchGetGroupInfo(model, groupIds)
	if err != nil {
		return myContext, err
	}

	for _, i := range topGroupIds {
		/*	2022-06-30 老板说先不分区	// 置顶只对同语言区的生效
			if myRegion != regions[topGroupInfo[i].Country] {
				continue
			}

		*/
		// 已经置顶的,直接进队列,不再参与排序
		hotGroupList = append(hotGroupList, groups[i])
		//delete(groupIds, i)
	}

	// for pretty log
	//logstr := ""
	//for _, i := range hotGroupList {
	//logstr += " " + i.ImGroupId
	//}
	//logstr += " |"

	// 获取国家信息
	_, area, err := user_m.GetUserCountryArea(model, myUserId)
	if err != nil {
		model.Log.Errorf("GetUserCountryArea 获取国家资源错误 userId:%d, err:%v", myUserId, err)
		return myContext, err
	}
	myArea := fmt.Sprintf("%d", area)
	// 国家区域信息
	resAreaMap, err := res_c.GetCountryAreaMap(model)
	if err != nil {
		return myContext, err
	}
	areaScore := make(map[string]int)

	countryScore := make(map[string]int)
	if len(myCountry) > 0 {
		for _, i := range sortedGroupIds {
			if myCountry == groups[i].Country {
				countryScore[i] = 1
			} else {
				countryScore[i] = 0
			}
			if cArea, ok := resAreaMap[groups[i].Country]; ok {
				if myArea == cArea {
					areaScore[i] = 1
				} else {
					areaScore[i] = 0
				}
			}
		}
	}
	model.Log.Infof("GetPopularGroups, countryScore[*]: %v,cost:%v", countryScore, time.Now().Sub(start))

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

	visitCount, err := group_m.BatchGetRoomVisitCount(model.Log, groupIds)
	if err != nil {
		return myContext, err
	}

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

		// 1、老板说,优化按国家
		if countryScore[gi] > countryScore[gj] {
			return true
		} else if countryScore[gi] < countryScore[gj] {
			return false
		}
		// 不是我的国家,按区域排序
		if countryScore[gi] == 0 {
			if areaScore[gi] > areaScore[gj] {
				return true
			} else if areaScore[gi] < areaScore[gj] {
				return false
			}
		}

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

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

		// 4、按热度递减排序
		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
	})

	// for pretty log
	// * 同国家 ^ 麦上有人 + 开放群 - 需要等级的群
	for _, g := range sortedGroupIds {
		hotGroupList = append(hotGroupList, groups[g])
		//prefix := " "
		//if countryScore[g] == 0 {
		//prefix += "*"
		//}
		//logstr += prefix + g + ":" + groups[g].Code + ":" + strconv.Itoa(int(micGroupNum[g])) +
		//	":" + strconv.FormatUint(diamonds[g], 10) + ":" + strconv.Itoa(int(visitCount[g]))
	}
	total := len(hotGroupList)
	model.Log.Infof("GetPopularGroups: hotGroupList size = %d,cost:%v", total, time.Now().Sub(start))

	result := make([]group_cv.PopularGroupInfo, 0)

	beginPos := pageSize * (pageIndex - 1)
	endPos := pageSize * pageIndex
	if beginPos < total {
		if endPos > total {
			endPos = total
		}

		groupIds := make([]string, 0)
		owners := make([]uint64, 0)
		for _, i := range hotGroupList[beginPos:endPos] {
			groupIds = append(groupIds, i.ImGroupId)
			owners = append(owners, i.Owner)
		}
		powerIds, powerNames, powerNameplates, powerGrades, err := group_power_cv.BatchGetGroupPower(model.Db, owners)
		if err != nil {
			return myContext, err
		}
		groupMedals, err := group_m.BatchGetMedals(model.Db, groupIds)
		if err != nil {
			return myContext, err
		}
		resMedal, err := res_m.MedalGetAllMap(model.Db)
		if err != nil {
			return myContext, err
		}

		//roomMicUserMap, err := group_m.BatchGetAllMicUser(model, groupIds)
		//if err != nil {
		//	return myContext, err
		//}
		model.Log.Infof("GetPopularGroups: final start = %d, end = %d, groupIds %v,cost:%v", beginPos, endPos, groupIds, time.Now().Sub(start))

		roomCount, err := group_m.BatchGetRoomCount(model, groupIds)
		if err != nil {
			return nil, err
		}

		countryInfo, err := res_c.GetCountryIconMap(model)
		if err != nil {
			return myContext, err
		}

		supportLevels, err := group_s.NewGroupService(myContext).GetWeekMaxSupportLevelMap()
		if err != nil {
			return myContext, err
		}
		rr := rocket_m.RocketResult{}
		maxStageMap, err := rr.GetMaxStage(mysql.Db, groupIds)
		if err != nil {
			return myContext, err
		}
		// 正在进行的游戏
		games := game_m.GetNotEndGamesMap(model)

		for _, i := range hotGroupList[beginPos:endPos] {
			micUsers := make([]user_cv.CvUserTiny, 0)

			var maxStage *uint16 = nil
			if s, ok := maxStageMap[i.ImGroupId]; ok {
				maxStage = &s
			}

			medals := make([]medal_cv.PicElement, 0)

			// 补上房间流水勋章
			var pe *medal_cv.PicElement
			_, pe, err = medal_cv.GetGroupConsumeMedal(model, i.ImGroupId)
			if err != nil {
				model.Log.Infof("GetPopularGroups: GetGroupConsumeMedal: %s", err.Error())
			} else if pe != nil {
				medals = append(medals, medal_cv.PicElement{PicUrl: pe.PicUrl})
			}

			if m, ok := groupMedals[i.ImGroupId]; ok {
				for _, j := range m {
					mId := uint32(j)
					if e, ok := resMedal[mId]; ok {
						medals = append(medals, medal_cv.PicElement{
							PicUrl: e.PicUrl,
						})
					}
				}
			}

			var password *string = nil
			if len(i.Password) > 0 && i.Owner != myUserId {
				emptyStr := ""
				password = &emptyStr
			}

			result = append(result, group_cv.PopularGroupInfo{
				GroupInfo: group_cv.GroupInfo{
					GroupBasicInfo: group_cv.GroupBasicInfo{
						GroupId:             i.TxGroupId,
						Name:                i.Name,
						Introduction:        i.Introduction,
						Notification:        i.Notification,
						FaceUrl:             i.FaceUrl,
						Code:                i.Code,
						CountryIcon:         countryInfo[i.Country],
						Password:            password,
						SupportLevel:        supportLevels[i.ImGroupId],
						GroupInUserDuration: visitCount[i.ImGroupId],
						MicNumType:          int(i.MicNumType),
						GroupMedals:         medals,
					},
					HasOnMic:            true,
					GroupPowerId:        powerIds[i.Owner],
					GroupPowerName:      powerNames[i.Owner],
					GroupPowerNameplate: powerNameplates[i.Owner],
					GroupPower: group_cv.GroupPower{
						Id:        powerIds[i.Owner],
						Name:      powerNames[i.Owner],
						Nameplate: powerNameplates[i.Owner],
						Grade:     powerGrades[i.Owner],
					},
				},
				MicUsers:      micUsers,
				RoomUserCount: uint(roomCount[i.ImGroupId]),
				MaxStage:      maxStage,
				GameTypes:     games[i.TxGroupId],
			})
		}
	}

	resp.ResponsePageOk(c, result, uint(total), pageIndex)
	return myContext, nil
}

func getTopGroups(model *domain.Model, bannedGroups map[string]uint64, hiddenGroups map[string]struct{}) ([]string, error) {
	topGroups, err := group_m.GroupTopGetAll(model)
	if err != nil {
		return nil, err
	}

	result := make([]string, 0)
	for _, i := range topGroups {
		// 过滤掉被封禁的群。理论上是不需要的,因为被封禁的不会被置顶。这里只是为了保险
		if bannedGroups[i] != 0 {
			continue
		}
		// 过滤掉被隐藏的群
		if _, exist := hiddenGroups[i]; exist {
			continue
		}

		result = append(result, i)
	}
	return result, nil
}

type GetLatestGroupsReq struct {
	PageSize  int `form:"pageSize"` //  binding:"min=1"
	PageIndex int `form:"pageIndex"`
	LastId    int `form:"lastId"`
}

// @Tags 群组
// @Summary 查询最新群组
// @Accept application/x-www-form-urlencoded
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param pageSize query int false "分页大小 默认:10" default(10)
// @Param pageIndex query int false "第几个分页,从1开始 默认:1" default(1)
// @Param lastId query int false "上一页列表的最后一个id,避免分页重复 默认:0" default(1)
// @Success 200 {object} group_cv.LatestGroupInfo
// @Router /v1/imGroup/latest [get]
func GetLatestGroups(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)

	request := &GetLatestGroupsReq{}
	err := c.ShouldBindQuery(request)
	if err != nil {
		return myContext, err
	}

	if request.PageSize <= 0 {
		request.PageSize = 10
	}

	if request.PageIndex <= 0 {
		request.PageIndex = 1
	}

	// 上一页最后一个id, 避免分页变化数据重复
	if request.LastId <= 0 {
		request.LastId = 0
	}

	//offset := (req.PageIndex - 1) * req.PageSize

	model := domain.CreateModelContext(myContext)

	micGroupNum, err := group_m.GetMicHasInGroupNum(model)
	if err != nil {
		return myContext, err
	}

	gids := make([]string, 0)
	for i, _ := range micGroupNum {
		gids = append(gids, i)
	}
	// 获取最新群组列表
	groupInfos, err := group_m.GetLatestGroupInfos(model, request.PageSize, request.LastId, gids)
	if err != nil {
		return myContext, err
	}

	// 提取id
	groupIds := make([]string, 0, len(groupInfos))
	for _, group := range groupInfos {
		groupIds = append(groupIds, group.ImGroupId)
	}

	// 获取国家信息
	countryInfo, err := res_c.GetCountryIconMap(model)
	if err != nil {
		return myContext, err
	}

	// 获取本周最高的扶持等级
	supportLevels, err := group_s.NewGroupService(myContext).GetWeekMaxSupportLevelMap()
	if err != nil {
		return myContext, err
	}

	// 用户id
	myUserId, err := req.GetUserId(c)
	if err != nil {
		return myContext, err
	}

	// 获取房间浏览数量
	visitCount, err := group_m.BatchGetRoomVisitCount(model.Log, groupIds)
	if err != nil {
		return myContext, err
	}

	// 获取群势力信息
	owners := make([]uint64, 0)
	for _, group := range groupInfos {
		owners = append(owners, group.Owner)
	}
	powerIds, powerNames, powerNameplates, powerGrades, err := group_power_cv.BatchGetGroupPower(model.Db, owners)
	if err != nil {
		return myContext, err
	}

	// 获取群勋章信息
	groupMedals, err := group_m.BatchGetMedals(model.Db, groupIds)
	if err != nil {
		return myContext, err
	}
	resMedal, err := res_m.MedalGetAllMap(model.Db)
	if err != nil {
		return myContext, err
	}

	// 获取房间人数信息
	roomCount, err := group_m.BatchGetRoomCount(model, groupIds)
	if err != nil {
		return nil, err
	}

	// 获取火箭信息
	rr := rocket_m.RocketResult{}
	maxStageMap, err := rr.GetMaxStage(mysql.Db, groupIds)
	if err != nil {
		return myContext, err
	}
	// 正在进行的游戏
	games := game_m.GetNotEndGamesMap(model)

	result := make([]*group_cv.LatestGroupInfo, 0)

	for _, group := range groupInfos {
		micUsers := make([]user_cv.CvUserTiny, 0)

		// 密码应该是一直为空?
		var password *string = nil
		if len(group.Password) > 0 && group.Owner != myUserId {
			emptyStr := ""
			password = &emptyStr
		}

		// 勋章信息
		medals := make([]medal_cv.PicElement, 0)
		if m, ok := groupMedals[group.ImGroupId]; ok {
			for _, j := range m {
				mId := uint32(j)
				if e, ok := resMedal[mId]; ok {
					medals = append(medals, medal_cv.PicElement{
						PicUrl: e.PicUrl,
					})
				}
			}
		}

		// 补上房间流水勋章
		var pe *medal_cv.PicElement
		_, pe, err = medal_cv.GetGroupConsumeMedal(model, group.ImGroupId)
		if err != nil {
			model.Log.Infof("GetLatestGroups: GetGroupConsumeMedal: %s", err.Error())
		} else if pe != nil {
			medals = append(medals, medal_cv.PicElement{PicUrl: pe.PicUrl})
		}

		// 最大的火箭
		var maxStage *uint16 = nil
		if s, ok := maxStageMap[group.ImGroupId]; ok {
			maxStage = &s
		}

		result = append(result, &group_cv.LatestGroupInfo{
			GroupInfo: group_cv.GroupInfo{
				GroupBasicInfo: group_cv.GroupBasicInfo{
					Id:                  group.Id,
					GroupId:             group.TxGroupId,
					Name:                group.Name,
					Introduction:        group.Introduction,
					Notification:        group.Notification,
					FaceUrl:             group.FaceUrl,
					Code:                group.Code,
					CountryIcon:         countryInfo[group.Country],
					Password:            password,
					SupportLevel:        supportLevels[group.ImGroupId],
					GroupInUserDuration: visitCount[group.ImGroupId],
					MicNumType:          int(group.MicNumType),
					GroupMedals:         medals,
				},
				HasOnMic:            true,
				GroupPowerId:        powerIds[group.Owner],
				GroupPowerName:      powerNames[group.Owner],
				GroupPowerNameplate: powerNameplates[group.Owner],
				GroupPower: group_cv.GroupPower{
					Id:        powerIds[group.Owner],
					Name:      powerNames[group.Owner],
					Nameplate: powerNameplates[group.Owner],
					Grade:     powerGrades[group.Owner],
				},
			},
			MicUsers:      micUsers,
			RoomUserCount: uint(roomCount[group.ImGroupId]),
			MaxStage:      maxStage,
			GameTypes:     games[group.TxGroupId],
		})
	}

	resp.ResponseOk(c, result)
	return myContext, nil
}

// @Tags 群组
// @Summary 查询推荐的群组(version>=2.19)
// @Accept application/x-www-form-urlencoded
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Success 200 {object} group_cv.PopularGroupInfo
// @Router /v1/imGroup/recommended [get]
func GetRecommendGroup(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)

	model := domain.CreateModelContext(myContext)

	bannedGroups, err := group_m.GetBannedGroupsMap(model)
	if err != nil {
		return myContext, err
	}

	//noPwdGroups, err := group_m.FindNoPasswordGroups(model)
	//if err != nil {
	//	return myContext, err
	//}

	// 获取麦上有人的所有群组及麦上人数
	micGroupNum, err := group_m.GetMicHasInGroupNum(model)
	if err != nil {
		return myContext, err
	}
	var micGroupIds []string
	for groupId := range micGroupNum {
		micGroupIds = append(micGroupIds, groupId)
	}
	model.Log.Infof("GetRecommendGroups, micGroupNum : %v", micGroupNum)
	noPwdGroups, err := group_m.FindNoPasswordGroupsV2(model, micGroupIds)
	if err != nil {
		return myContext, err
	}
	model.Log.Infof("GetRecommendGroups: noPwdGroups = %d, bannedGroups = %d", len(noPwdGroups), len(bannedGroups))

	groupIds := make([]string, 0)
	banCount := 0
	for _, v := range noPwdGroups {
		if _, ok := micGroupNum[v.ImGroupId]; ok {
			if bannedGroups[v.ImGroupId] != 0 {
				banCount++
			} else {
				groupIds = append(groupIds, v.ImGroupId)
			}
		}
	}
	model.Log.Infof("GetRecommendGroups: size = %d, banned %d", len(groupIds), banCount)

	myService := domain.CreateService(myContext)
	result, _, err := group_cv.BuildJoinedGroupInfo(myService, 0, groupIds, group_e.GROUP_RECOMMEND_SIZE, 1)
	if err != nil {
		return myContext, err
	}

	resp.ResponseOk(c, result)
	return myContext, nil
}

// @Tags 群组
// @Summary 获取最近访问的房间
// @Accept application/x-www-form-urlencoded
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Success 200 {object} group_cv.JoinedGroupInfo
// @Router /v1/imGroup/myRecent [get]
func GetRecentGroup(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)

	userId, _, err := req.GetUserIdAndExtId(c, myContext)
	if err != nil {
		return myContext, err
	}

	model := domain.CreateModelContext(myContext)

	uer := group_m.UserEnterRoom{UserId: userId}
	rec, err := uer.Find(model.Db)
	if err != nil {
		return myContext, err
	}

	myGroups, err := group_m.FindGroupMapByOwner(model, userId)
	if err != nil {
		return myContext, err
	}

	// 剔除自己创建的群
	groupIds := make([]string, 0)
	for _, i := range rec {
		if _, ok := myGroups[i.GroupId]; !ok {
			groupIds = append(groupIds, i.GroupId)
		}
	}

	myService := domain.CreateService(myContext)
	result, _, err := group_cv.BuildJoinedGroupInfo(myService, userId, groupIds, 30, 1)
	if err != nil {
		return myContext, err
	}

	resp.ResponseOk(c, result)
	return myContext, nil
}

// @Tags 群组
// @Summary 获取我成为永久会员的群
// @Accept application/x-www-form-urlencoded
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param pageSize query int false "分页大小 默认:10" default(10)
// @Param pageIndex query int false "第几个分页,从1开始 默认:1" default(1)
// @Success 200 {object} group_cv.JoinedGroupInfo
// @Router /v1/imGroup/myPermanent [get]
func GetMyGroup(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)

	pageSize, err := strconv.Atoi(c.Query("pageSize"))
	if err != nil || pageSize <= 0 {
		pageSize = 10
	}
	pageIndex, err := strconv.Atoi(c.Query("pageIndex"))
	if err != nil || pageIndex <= 0 {
		pageIndex = 1
	}

	userId, _, err := req.GetUserIdAndExtId(c, myContext)
	if err != nil {
		return myContext, err
	}

	model := domain.CreateModelContext(myContext)

	rec, err := group_m.GetJoinedGroups(model.Db, userId)
	if err != nil {
		return myContext, err
	}

	myGroups, err := group_m.FindGroupMapByOwner(model, userId)
	if err != nil {
		return myContext, err
	}

	// 剔除自己创建的群
	groupIds := make([]string, 0)
	for _, i := range rec {
		if _, ok := myGroups[i.GroupId]; !ok {
			groupIds = append(groupIds, i.GroupId)
		}
	}

	myService := domain.CreateService(myContext)
	result, _, err := group_cv.BuildJoinedGroupInfo(myService, userId, groupIds, pageSize, pageIndex)
	if err != nil {
		return myContext, err
	}

	resp.ResponseOk(c, result)
	return myContext, nil
}

// @Tags 群组
// @Summary 最近访问列表
// @Accept application/x-www-form-urlencoded
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param groupId path string true "群ID"
// @Param pageSize query int false "分页大小 默认:10" default(10)
// @Param pageIndex query int false "第几个分页,从1开始 默认:1" default(1)
// @Success 200 {object} GroupMembersRsp
// @Router /v1/imGroup/visitors/{groupId} [get]
func GetGroupVisitors(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)

	groupId := c.Param("groupId")
	if len(groupId) <= 0 {
		return myContext, bizerr.ParaMissing
	}

	pageSize, err := strconv.Atoi(c.Query("pageSize"))
	if err != nil || pageSize <= 0 {
		pageSize = 10
	}
	pageIndex, err := strconv.Atoi(c.Query("pageIndex"))
	if err != nil || pageIndex <= 0 {
		pageIndex = 1
	}

	userId, _, err := req.GetUserIdAndExtId(c, myContext)
	if err != nil {
		return myContext, err
	}

	model := domain.CreateModelContext(myContext)

	groupId, err = group_m.ToImGroupId(model, groupId)
	if err != nil {
		return myContext, err
	}

	uer := group_m.UserEnterRoom{GroupId: groupId}
	rows, err := uer.Find(model.Db)
	if err != nil {
		return myContext, err
	}

	now := time.Now()
	t := now.AddDate(0, 0, -15) // 只要15天内进入房间的人
	userIds := make([]uint64, 0)
	for _, i := range rows {
		if i.EnterTime.After(t) {
			userIds = append(userIds, i.UserId)
		}
	}
	users, err := user_m.GetUserMapByIds(model, userIds)
	if err != nil {
		return myContext, err
	}
	model.Log.Infof("GetGroupVisitors %s: memberNum = %d, user size = %d", groupId, len(rows), len(userIds))

	result := GroupMembersRsp{Total: uint(len(userIds))}

	beginPos := pageSize * (pageIndex - 1)
	if uint(beginPos) < result.Total {
		// 取在线状态
		extIds := make([]string, 0)
		for _, i := range users {
			extIds = append(extIds, i.ExternalId)
		}
		statusMap, err := tim_m.GetOnlineStatus(model, extIds)
		if err != nil {
			return myContext, err
		}

		result.Online = 0
		for _, v := range statusMap {
			if v == online_e.IM_STATUS_ON_LINE {
				result.Online++
			}
		}
		model.Log.Infof("GetGroupVisitors %s: statusMap size = %d, onLine = %d", groupId, len(statusMap), result.Online)

		roles, _, err := group_m.GetRolesInGroup(model, groupId)
		if err != nil {
			return myContext, err
		}

		nobleLevels, err := noble_m.BatchGetNobleLevel(model.Db, userIds)
		if err != nil {
			return myContext, err
		}
		svipLevels, err := rpc.MGetUserSvipLevel(model, userIds)
		if err != nil {
			return myContext, err
		}

		vips, err := user_m.BatchGetVips(userIds)
		if err != nil {
			return myContext, err
		}

		model.Log.Infof("GetGroupVisitors %s, users %v, roles: %v, nobles: %v, vips: %v", groupId, userIds, roles, nobleLevels, vips)

		roomUsers, err := group_m.RoomLivingExistsUserId(groupId)
		if err != nil {
			return myContext, err
		}

		roomUserMap := utils.SliceToMapUInt64(roomUsers)
		//model.Log.Infof("GetGroupMembers %s, roomStatusMap %v", groupId, roomStatusMap)

		// 排序规则 :在房间的优先,其次是在线,再次看角色,最后看贵族
		sort.Slice(userIds, func(i, j int) bool {
			ui := userIds[i]
			uj := userIds[j]

			_, ok1 := roomUserMap[ui]
			_, ok2 := roomUserMap[uj]
			if ok1 && !ok2 {
				return true
			} else if ok1 == ok2 {
				ei := users[ui].ExternalId
				ej := users[uj].ExternalId
				if statusMap[ei] > statusMap[ej] {
					return true
				}
				if statusMap[ei] == statusMap[ej] {
					if roles[ui] > roles[uj] {
						return true
					}
					if roles[ui] == roles[uj] {
						// SVIP>贵族5>贵族4>贵族3>贵族2>VIP
						if svipLevels[ui] > svipLevels[uj] {
							return true
						} else if svipLevels[ui] == svipLevels[uj] {
							if nobleLevels[ui] > nobleLevels[uj] && nobleLevels[ui] >= 2 {
								return true
							}
							if nobleLevels[ui] == nobleLevels[uj] || nobleLevels[ui] < 2 && nobleLevels[uj] < 2 {
								if vips[ui] != nil {
									if vips[uj] == nil {
										return true
									} else {
										return users[ui].Code < users[uj].Code
									}
								} else if vips[uj] == nil {
									return users[ui].Code < users[uj].Code
								}
							}
						}
					}
				}
			}
			return false
		})

		model.Log.Infof("GetGroupVisitors %s, sorted users: %v", groupId, userIds)

		endPos := pageSize * pageIndex
		if endPos > len(userIds) {
			endPos = len(userIds)
		}

		userIds = userIds[beginPos:endPos]
		userExtends, err := user_cv.BatchGetUserExtend(model, userIds, userId)
		if err != nil {
			return myContext, err
		}

		for _, u := range userIds {
			inRoom := false
			if _, ok := roomUserMap[u]; ok {
				inRoom = true
			}
			result.Members = append(result.Members, group_cv.MemberDetail{
				CvUserExtend: userExtends[u],
				Role:         roles[u],
				OnlineStatus: statusMap[users[u].ExternalId],
				InRoom:       inRoom,
			})
		}
	}
	resp.ResponseOk(c, result)
	return myContext, nil
}

type OwnPublicGroupRsp struct {
	Total    uint                   `json:"total"`
	MyGroups []group_cv.GroupDetail `json:"myGroups"`
}

// @Tags 群组
// @Summary 查询某人创建的(公开)群组
// @Accept application/x-www-form-urlencoded
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param userExternalId path string true "用户ExternalID"
// @Success 200 {object} OwnPublicGroupRsp
// @Router /v1/imGroup/ownPublicGroup/{userExternalId} [get]
func GetOwnPublicGroup(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)

	externalId := c.Param("userExternalId")
	if len(externalId) <= 0 {
		return myContext, myerr.NewSysError("userExternalId 为必填项")
	}

	model := domain.CreateModelContext(myContext)

	user, err := user_m.GetUserByExtId(model, externalId)
	if err != nil {
		return myContext, err
	}

	if utils.IfLogout(user.LogoutTime) {
		resp.ResponseOk(c, OwnPublicGroupRsp{Total: 0})
		return myContext, nil
	}

	theirRoles, err := group_m.GetRolesByUser(model, user.ID)
	if err != nil {
		return myContext, err
	}
	model.Log.Info("GetOwnPublicGroup: theirRoles - ", theirRoles)

	countryInfo, err := res_c.GetCountryIconMap(model)
	if err != nil {
		return myContext, err
	}

	permanentGroups, err := group_m.GetJoinedGroups(model.Db, user.ID)
	if err != nil {
		return myContext, err
	}

	groups, err := group_m.FindGroupMapByOwner(model, user.ID)
	if err != nil {
		return myContext, err
	}

	result := OwnPublicGroupRsp{Total: uint(len(permanentGroups) + len(groups))}

	groupId := ""
	for i, j := range groups {
		// 只要公开的群
		if len(j.Password) == 0 {
			if r, ok := theirRoles[j.ImGroupId]; ok && r == group_e.GROUP_OWNER {
				// fixme:如果有多个群则展示群人数最多的群组
				groupId = i
				break
			}
		}
	}

	if len(groupId) > 0 {
		groupInfo := groups[groupId]

		roleMembers, myRole, err := buildRoleMembers(model, groupId, user.ID)
		if err != nil {
			return myContext, err
		}

		// 截取前N个
		endPos := group_e.GROUP_ROLE_PERSONAL_VIEW_LIMIT
		if endPos > len(roleMembers) {
			endPos = len(roleMembers)
		}

		// 找不到的,默认为空(可能被后台删了)
		themeUrl := ""
		var themeId uint64 = 0
		var themeType uint8 = 1
		if groupInfo.ThemeId > 0 {
			//官方主题
			// 找不到的,默认为空(可能被后台删了)
			themeType = 1
			themes, _ := res_m.GroupThemeGetAll(model.Db)
			for _, i := range themes {
				if i.ID == uint64(groupInfo.ThemeId) {
					themeUrl = i.Url
					themeId = i.ID
					break
				}
			}
		} else {
			//可能是自定义主题
			themeId, themeUrl, err = group_m.GetShowCustomTheme(model, groupInfo.ImGroupId)
			if err != nil {
				return myContext, err
			}
			if themeId != 0 {
				themeType = 2
			}
		}

		supportLevels, err := group_s.NewGroupService(myContext).GetWeekMaxSupportLevelMap()
		if err != nil {
			return myContext, err
		}

		mem, err := group_m.GetMembers(model.Db, groupId)
		if err != nil {
			return myContext, err
		}

		result.MyGroups = append(result.MyGroups, group_cv.GroupDetail{
			GroupBasicInfo: group_cv.GroupBasicInfo{
				GroupId:      groupInfo.TxGroupId,
				Name:         groupInfo.Name,
				Introduction: groupInfo.Introduction,
				Notification: groupInfo.Notification,
				FaceUrl:      groupInfo.FaceUrl,
				Code:         groupInfo.Code,
				MemberNum:    uint(len(mem)),
				CountryIcon:  countryInfo[groupInfo.Country],
				SupportLevel: supportLevels[groupId],
				MicNumType:   int(groupInfo.MicNumType),
			},
			MicOn:       groupInfo.MicOn,
			LoadHistory: groupInfo.LoadHistory,
			ThemeId:     themeId,
			ThemeUrl:    themeUrl,
			ThemeType:   themeType,
			Role:        myRole,
			RoleMembers: roleMembers[0:endPos],
		})
	}

	resp.ResponseOk(c, result)
	return myContext, nil
}

func buildRoleMembers(model *domain.Model, groupId string, userId uint64) ([]group_cv.RoleMemberInfo, group_e.GroupRoleType, error) {
	myRole := group_e.GROUP_VISITOR
	roles, _, err := group_m.GetRolesInGroup(model, groupId)
	if err != nil {
		return nil, myRole, err
	}

	model.Log.Infof("buildRoleMembers: roles - %s, %v", groupId, roles)

	userIds := make([]uint64, 0)
	for u, r := range roles {
		userIds = append(userIds, u)

		if u == userId {
			myRole = r
		}
	}

	users, err := user_cv.GetUserTinyMap(userIds)
	if err != nil {
		return nil, myRole, err
	}

	vips, err := user_m.BatchGetVips(userIds)
	if err != nil {
		return nil, myRole, err
	}

	extIds := make([]string, 0)
	for _, i := range users {
		extIds = append(extIds, i.ExternalId)
	}
	status, err := tim_m.GetOnlineStatus(model, extIds)
	if err != nil {
		return nil, myRole, err
	}

	superManagerMap, err := user_m.GetSuperManagerMap(userIds)
	if err != nil {
		return nil, myRole, err
	}

	roleMembers := make([]group_cv.RoleMemberInfo, 0)
	for u, _ := range users {
		m := users[u]
		roleMembers = append(roleMembers, group_cv.RoleMemberInfo{
			CvUserBase: user_cv.CvUserBase{
				Avatar:          &m.Avatar,
				ExternalId:      &m.ExternalId,
				Nick:            &m.Nick,
				Sex:             &m.Sex,
				Country:         &m.CountryIcon,
				CountryIcon:     &m.CountryIcon,
				Code:            &m.Code,
				IsPrettyCode:    m.IsPrettyCode,
				IsVip:           vips[m.Id] != nil,
				IsOfficialStaff: superManagerMap[m.Id],
				VipExpireTime:   vips[m.Id],
			},
			Role:         roles[u],
			OnlineStatus: status[m.ExternalId],
		})
	}

	sort.SliceStable(roleMembers, func(i, j int) bool {
		if roleMembers[i].Role > roleMembers[j].Role {
			return true
		} else if roleMembers[i].Role == roleMembers[j].Role {
			if roleMembers[i].OnlineStatus > roleMembers[j].OnlineStatus {
				return true
			} else if roleMembers[i].OnlineStatus == roleMembers[j].OnlineStatus && *roleMembers[i].Code > *roleMembers[j].Code {
				return true
			}
		}
		return false
	})
	return roleMembers, myRole, nil
}

// @Tags 群组
// @Summary 国家A,群主是属于国家A下的群
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param countryShortName query string true "国家缩写"
// @Param pageSize query int true "分页大小 默认:10" default(10)
// @Param pageIndex query int true "第几个分页,从1开始 默认:1" default(1)
// @Success 200 {object} group_cv.PopularGroupInfo
// @Router /v1/imGroup/country [get]
func GetGroupByCountry(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)
	myUserId, err := req.GetUserId(c)
	if err != nil {
		return myContext, err
	}

	countryShortName := c.Query("countryShortName")
	if countryShortName == "" {
		return myContext, myerr.NewSysError("countryShortName 为必填项")
	}
	pageSize, err := strconv.Atoi(c.Query("pageSize"))
	if err != nil || pageSize <= 0 {
		pageSize = 10
	}
	pageIndex, err := strconv.Atoi(c.Query("pageIndex"))
	if err != nil || pageIndex <= 0 {
		pageIndex = 1
	}

	model := domain.CreateModelContext(myContext)

	bannedGroups, err := group_m.GetBannedGroupsMap(model)
	if err != nil {
		return myContext, err
	}

	model.Log.Infof("GetGroupByCountry: page size = %d, page index = %d, banMap %v", pageSize, pageIndex, bannedGroups)

	beginTime := time.Now()
	groups, banCount, visitCount, err := getCandidatesByCountry(model, bannedGroups, countryShortName)
	if err != nil {
		return myContext, err
	}
	endTime := time.Now()
	model.Log.Infof("GetGroupByCountry: candidates size = %d, takes %d ms banned = %d, visitCount size = %d",
		len(groups), endTime.Sub(beginTime).Milliseconds(), banCount, len(visitCount))
	model.Log.Infof("GetGroupByCountry cost1:%v", time.Now().Sub(beginTime))

	hotGroupList := make([]*group_m.GroupInfo, 0)

	// 获取麦上有人的所有群组及麦上人数
	micGroupNum, err := group_m.GetMicHasInGroupNum(model)
	if err != nil {
		return myContext, err
	}
	model.Log.Infof("GetGroupByCountry, micGroupNum : %v", micGroupNum)
	model.Log.Infof("GetGroupByCountry 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 myContext, err
	}
	model.Log.Infof("GetGroupByCountry, diamonds in 30 mins: %v", diamonds)
	model.Log.Infof("GetGroupByCountry cost3:%v", time.Now().Sub(beginTime))

	supportLevels, err := group_s.NewGroupService(myContext).GetWeekMaxSupportLevelMap()
	if err != nil {
		return myContext, err
	}
	model.Log.Infof("GetGroupByCountry, supportLevels : %v", supportLevels)
	model.Log.Infof("GetGroupByCountry 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("GetGroupByCountry cost5:%v", time.Now().Sub(beginTime))

	// for pretty log
	//logstr := ""
	// * 同语言区 ^ 麦上有人 + 开放群 - 需要等级的群
	for _, i := range sortedGroupIds {
		hotGroupList = append(hotGroupList, groups[i])
		//prefix := " "
		//if micGroupNum[i] > 0 {
		//prefix += "^"
		//}
		//logstr += prefix + i + ":" + groups[i].Code + ":" +
		//	strconv.Itoa(int(supportLevels[i])) + ":" + strconv.Itoa(int(micGroupNum[i])) + ":" + strconv.Itoa(int(visitCount[i]))
	}
	total := len(hotGroupList)
	model.Log.Infof("GetGroupByCountry: size = %d, %s", total)

	result := make([]group_cv.PopularGroupInfo, 0)

	beginPos := pageSize * (pageIndex - 1)
	endPos := pageSize * pageIndex
	if beginPos < total {
		if endPos > total {
			endPos = total
		}

		groupIds := make([]string, 0)
		owners := make([]uint64, 0)
		for _, i := range hotGroupList[beginPos:endPos] {
			groupIds = append(groupIds, i.ImGroupId)
			owners = append(owners, i.Owner)
		}
		powerIds, powerNames, powerNameplates, powerGrades, err := group_power_cv.BatchGetGroupPower(model.Db, owners)
		if err != nil {
			return myContext, err
		}
		groupMedals, err := group_m.BatchGetMedals(model.Db, groupIds)
		if err != nil {
			return myContext, err
		}
		resMedal, err := res_m.MedalGetAllMap(model.Db)
		if err != nil {
			return myContext, err
		}

		model.Log.Infof("GetGroupByCountry: final start = %d, end = %d, groupIds %v", beginPos, endPos, groupIds)

		countryInfo, err := res_c.GetCountryIconMap(model)
		if err != nil {
			return myContext, err
		}

		rr := rocket_m.RocketResult{}
		maxStageMap, err := rr.GetMaxStage(mysql.Db, groupIds)
		if err != nil {
			return myContext, err
		}

		roomCount, err := group_m.BatchGetRoomCount(model, groupIds)
		if err != nil {
			return nil, err
		}
		// 正在进行的游戏
		games := game_m.GetNotEndGamesMap(model)

		for _, i := range hotGroupList[beginPos:endPos] {
			var maxStage *uint16 = nil
			if s, ok := maxStageMap[i.ImGroupId]; ok {
				maxStage = &s
			}

			medals := make([]medal_cv.PicElement, 0)
			if m, ok := groupMedals[i.ImGroupId]; ok {
				for _, j := range m {
					mId := uint32(j)
					if e, ok := resMedal[mId]; ok {
						medals = append(medals, medal_cv.PicElement{
							PicUrl: e.PicUrl,
						})
					}
				}
			}
			// 补上房间流水勋章
			var pe *medal_cv.PicElement
			_, pe, err = medal_cv.GetGroupConsumeMedal(model, i.ImGroupId)
			if err != nil {
				model.Log.Infof("GetGroupByCountry: GetGroupConsumeMedal: %s", err.Error())
			} else if pe != nil {
				medals = append(medals, medal_cv.PicElement{PicUrl: pe.PicUrl})
			}

			var password *string = nil
			if len(i.Password) > 0 && i.Owner != myUserId {
				emptyStr := ""
				password = &emptyStr
			}
			result = append(result, group_cv.PopularGroupInfo{
				GroupInfo: group_cv.GroupInfo{
					GroupBasicInfo: group_cv.GroupBasicInfo{
						GroupId:             i.TxGroupId,
						Name:                i.Name,
						Introduction:        i.Introduction,
						Notification:        i.Notification,
						FaceUrl:             i.FaceUrl,
						Code:                i.Code,
						CountryIcon:         countryInfo[i.Country],
						Password:            password,
						SupportLevel:        supportLevels[i.ImGroupId],
						GroupInUserDuration: visitCount[i.ImGroupId],
						MicNumType:          int(i.MicNumType),
						GroupMedals:         medals,
					},
					HasOnMic:            micGroupNum[i.ImGroupId] > 0,
					GroupPowerId:        powerIds[i.Owner],
					GroupPowerName:      powerNames[i.Owner],
					GroupPowerNameplate: powerNameplates[i.Owner],
					GroupPower: group_cv.GroupPower{
						Id:        powerIds[i.Owner],
						Name:      powerNames[i.Owner],
						Nameplate: powerNameplates[i.Owner],
						Grade:     powerGrades[i.Owner],
					},
				},
				MicUsers:      []user_cv.CvUserTiny{},
				RoomUserCount: uint(roomCount[i.ImGroupId]),
				MaxStage:      maxStage,
				GameTypes:     games[i.TxGroupId],
			})
		}
	}
	model.Log.Infof("GetGroupByCountry cost6:%v", time.Now().Sub(beginTime))
	resp.ResponsePageOk(c, result, uint(total), pageIndex)
	return myContext, 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
	}

	roomVisitCount, err := room_c.GetAllRoomVisitCount()
	if err != nil {
		return nil, 0, nil, err
	}

	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 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
}

// @Tags 资源
// @Summary 国家资源
// @Param token header string true "token"
// @Param timestamp header string true "时间戳"
// @Param nonce header string true "随机数字"
// @Param signature header string true "sha1加密结果"
// @Param deviceType header string true "系统类型 ios android"
// @Param deviceVersion header string true "系统版本"
// @Success 200 {object} group_cv.CvCountry
// @Router /v1/imGroup/country/prior [get]
func GroupountryPrior(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)
	//沙特、科威特、伊拉克、阿尔及利亚、印度、菲律宾、土耳其
	//沙特,伊拉克,科威特,土耳其。印度,巴基斯坦,印尼
	resCountry, err := res_m.GetAllCountryByFilter(domain.CreateModelNil(), []string{"KSA", "Iraq", "Kuwait", "Turkey", "India", "Pakistan", "Indonesia"})
	if err != nil {
		return myContext, err
	}

	var cvContrys []group_cv.CvCountry
	for i := 0; i < len(resCountry); i++ {
		cvContrys = append(cvContrys, group_cv.CvCountry{
			Name:      &resCountry[i].Name,
			ShortName: &resCountry[i].ShortName,
			Icon:      &resCountry[i].Icon,
			Code:      &resCountry[i].Code,
		})
	}

	resp.ResponseOk(c, cvContrys)
	return myContext, nil
}