package group_power_r

import (
	"context"
	"fmt"
	"git.hilo.cn/hilo-common/domain"
	"git.hilo.cn/hilo-common/mycontext"
	"git.hilo.cn/hilo-common/resource/config"
	"git.hilo.cn/hilo-common/resource/mysql"
	"git.hilo.cn/hilo-common/resource/redisCli"
	"git.hilo.cn/hilo-common/sdk/aws"
	"git.hilo.cn/hilo-common/sdk/tencentyun"
	"git.hilo.cn/hilo-common/txop/msg"
	"git.hilo.cn/hilo-common/utils"
	"github.com/gin-gonic/gin"
	"github.com/jinzhu/now"
	"hilo-group/_const/enum/groupPower_e"
	"hilo-group/_const/enum/group_e"
	"hilo-group/_const/enum/msg_e"
	"hilo-group/_const/redis_key"
	"hilo-group/common"
	"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/user_c"
	"hilo-group/domain/model/game_m"
	"hilo-group/domain/model/groupPower_m"
	"hilo-group/domain/model/group_m"
	"hilo-group/domain/model/res_m"
	"hilo-group/domain/model/rocket_m"
	"hilo-group/domain/model/user_m"
	"hilo-group/domain/service/group_power_s"
	"hilo-group/domain/service/group_s"
	"hilo-group/myerr"
	"hilo-group/myerr/bizerr"
	"hilo-group/req"
	"hilo-group/resp"
	"sort"
	"strconv"
	"strings"
	"time"
)

// @Tags 国家势力
// @Summary 加入国家势力
// @Accept application/x-www-form-urlencoded
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param groupPowerId formData int true "国家势力Id"
// @Success 200
// @Router /v1/groupPower/user [post]
func GroupPowerJoin(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)
	return myContext, bizerr.UpgradeRequired
	// 旧版本(3.5.0以下),提示升级
	//_, major, minor, _, err := req.GetAppVersion(c)
	//if err != nil {
	//	return myContext, err
	//}
	//if major <= 3 && minor < 5 {
	//	return myContext, bizerr.UpgradeRequired
	//}
	//
	//groupPowerId, err := strconv.ParseUint(c.PostForm("groupPowerId"), 10, 64)
	//if err != nil {
	//	return myContext, err
	//}
	////获取用户
	//userId, err := req.GetUserId(c)
	//if err != nil {
	//	return myContext, err
	//}
	//
	//// Aoxi要求不能让这些人加入家族
	//banUserMap := map[uint64]bool{251: true, 1384611: true, 4223511: true, 4338751: true, 4339471: true, 4339541: true,
	//	4354581: true, 6541: true, 23971: true}
	//if _, ok := banUserMap[userId]; ok {
	//	return myContext, bizerr.GroupPowerCannotJoin
	//}
	//
	//if err := group_power_s.NewGroupPowerService(myContext).GroupPowerUserJoin(groupPowerId, userId); err != nil {
	//	return myContext, err
	//}
	//resp.ResponseOk(c, nil)
	//return myContext, nil
}

// @Tags 国家势力
// @Summary 退出国家势力
// @Accept application/x-www-form-urlencoded
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param groupPowerId path int true "国家势力ID"
// @Success 200
// @Router /v1/groupPower/user/{groupPowerId} [delete]
func GroupPowerLeave(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)
	groupPowerId, err := strconv.ParseUint(c.Param("groupPowerId"), 10, 64)
	if err != nil {
		return myContext, err
	}
	//获取用户
	userId, err := req.GetUserId(c)
	if err != nil {
		return myContext, err
	}
	remainSeconds, err := group_power_s.NewGroupPowerService(myContext).GroupPowerUserLeave(groupPowerId, userId)
	if err != nil {
		if remainSeconds == 0 {
			return myContext, err
		}

		model := domain.CreateModelContext(myContext)

		user, newErr := user_m.GetUser(model, userId)
		if newErr != nil {
			return myContext, newErr
		} else if user == nil {
			return myContext, err
		} else {
			text := res_m.ResMultiText{MsgId: msg_e.MSG_ID_GROUP_LEAVE_POWER, Language: user.Language}
			if text.Get(model.Db) == nil {
				dayLimit := "0"
				day, sTime := formatSeconds(remainSeconds)
				sDay := fmt.Sprintf("%d", day)
				errmsg := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(text.Content, "%d", dayLimit), "%s", sDay), "xx:xx:xx", sTime)
				return myContext, myerr.NewBusinessCodeNoCheck(bizerr.GroupPowerStayTooShort.GetCode(), errmsg, myerr.BusinessData{})
			} else {
				return myContext, err
			}
		}
	}
	resp.ResponseOk(c, nil)
	return myContext, nil
}

func formatSeconds(seconds int) (int, string) {
	sec := seconds % 60
	minute := seconds / 60
	hour := minute / 60
	minute %= 60
	day := hour / 24
	hour %= 24
	sTime := fmt.Sprintf("%02d:%02d:%02d", hour, minute, sec)
	return day, sTime
}

// @Tags 国家势力
// @Summary 国家势力标题页
// @Accept application/x-www-form-urlencoded
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param groupPowerId path int true "国家势力ID"
// @Success 200 {object} group_cv.GroupPowerTitle
// @Router /v1/groupPower/title/{groupPowerId} [get]
func GetGroupPowerTitle(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)
	groupPowerId, err := strconv.ParseUint(c.Param("groupPowerId"), 10, 64)
	if err != nil {
		return myContext, err
	}

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

	model := domain.CreateModelContext(myContext)

	groupPower, err := groupPower_m.GetGroupPower(model, groupPowerId)
	if err != nil {
		return myContext, err
	}

	if groupPower == nil {
		return myContext, bizerr.GroupPowerNotExist
	}

	gi, err := group_m.GetGroupInfo(model, groupPower.GroupUid)
	if err != nil {
		return myContext, err
	}
	if gi == nil {
		return myContext, bizerr.GroupNotFound
	}
	gpu := groupPower_m.GroupPowerUser{GroupPowerId: groupPowerId}
	count, err := gpu.GetCount(model.Db)
	if err != nil {
		return myContext, err
	}

	gpu = groupPower_m.GroupPowerUser{GroupPowerId: groupPowerId, Role: groupPower_e.GroupPowerUserRoleMgr}
	records, err := gpu.Get(model.Db)
	if err != nil {
		return myContext, err
	}
	if len(records) != 1 {
		return myContext, bizerr.GroupPowerNoOwner
	}
	owner := records[0].UserId
	userIds := []uint64{owner}

	assistants, err := group_m.FindRolesInGroup(model.Db, groupPower.GroupUid, group_e.GROUP_ADMIN)
	if err != nil {
		return myContext, err
	}

	userIds = append(userIds, assistants...)
	users, err := user_cv.GetUserBaseMap(userIds, myUserId)
	if err != nil {
		return myContext, err
	}

	result := group_cv.GroupPowerTitle{
		Id:        groupPowerId,
		Name:      gi.Name,
		GroupId:   gi.TxGroupId,
		Avatar:    gi.FaceUrl,
		MemberNum: count,
	}

	if users[owner] != nil {
		result.Owner = *users[owner]
	}

	// FIXME:排序规则是什么?
	for _, i := range assistants {
		if users[i] != nil {
			result.Assistants = append(result.Assistants, *users[i])
		}
	}

	if len(result.Assistants) > 4 {
		result.Assistants = result.Assistants[0:4]
	}

	gp, err := groupPower_m.GetGroupPowerUserOrNil(model, myUserId)
	if err != nil {
		return myContext, err
	}
	if gp != nil && gp.GroupPowerId == groupPowerId {
		result.IsMyGroupPower = true
	} else {
		result.IsMyGroupPower = false
	}

	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)
// @Param groupPowerId path int true "国家势力ID"
// @Success 200 {object} group_cv.PopularGroupInfo
// @Router /v1/groupPower/group/{groupPowerId} [get]
func GetGroupPowerGroups(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)

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

	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
	}

	groupPowerId, err := strconv.ParseUint(c.Param("groupPowerId"), 10, 64)
	if err != nil {
		return myContext, err
	}

	model := domain.CreateModelContext(myContext)

	groupPower, err := groupPower_m.GetGroupPower(model, groupPowerId)
	if err != nil {
		return myContext, err
	}

	if groupPower == nil {
		return myContext, bizerr.GroupPowerNotExist
	}

	gpu := groupPower_m.GroupPowerUser{GroupPowerId: groupPowerId}
	records, err := gpu.Get(model.Db)
	if err != nil {
		return myContext, err
	}
	members := make([]uint64, 0)
	for _, i := range records {
		members = append(members, i.UserId)
	}
	groupMap, err := group_m.FindGroupByOwners(model.Db, members)
	if err != nil {
		return myContext, err
	}

	groupList := make([]*group_m.GroupInfo, 0)
	groupIds := make([]string, 0)
	visitCount := make(map[string]int64, 0)
	for _, i := range members {
		if g, ok := groupMap[i]; ok {
			groupList = append(groupList, &g)
			groupIds = append(groupIds, g.ImGroupId)
			if count, err := group_m.GetRoomVisitCount(g.ImGroupId); err == nil {
				visitCount[g.ImGroupId] = count
			}
		}
	}
	model.Log.Infof("GetGroupPowerGroups, members: %v, groupMap: %v, groupList %v", members, groupMap, groupList)

	// 获取麦上有人的所有群组
	micGroupList, err := group_m.GetMicHasInGroups()
	if err != nil {
		return myContext, err
	}
	micGroupMap := make(map[string]bool, 0)
	for _, i := range micGroupList {
		micGroupMap[i] = true
	}

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

	roomMicUserMap, err := group_m.BatchGetAllMicUser(model, groupIds)
	if err != nil {
		return myContext, err
	}
	model.Log.Infof("GetGroupPowerGroups, roomMicUserMap : %v", roomMicUserMap)

	sort.Slice(groupList, func(i, j int) bool {
		gi := groupList[i].ImGroupId
		gj := groupList[j].ImGroupId
		if micGroupMap[gi] == true && micGroupMap[gj] == false {
			return true
		} else if micGroupMap[gi] == false && micGroupMap[gj] == true {
			return false
		}
		if supportLevels[gi] > supportLevels[gj] {
			return true
		} else if supportLevels[gi] < supportLevels[gj] {
			return false
		}
		if len(roomMicUserMap[gi]) > len(roomMicUserMap[gj]) {
			return true
		} else if len(roomMicUserMap[gi]) < len(roomMicUserMap[gj]) {
			return false
		}
		if visitCount[gi] > visitCount[gj] {
			return true
		} else if visitCount[gi] < visitCount[gj] {
			return false
		}

		// * Final resort: 群组CODE,短号优先,然后按字母序
		return len(groupList[i].Code) < len(groupList[j].Code) || len(groupList[i].Code) == len(groupList[j].Code) && groupList[i].Code < groupList[j].Code
	})

	// for pretty log
	// ^ 麦上有人
	//logstr := ""
	//for _, i := range groupList {
	//hotGroupList = append(hotGroupList, groups[i])
	//prefix := " "
	//if len(roomMicUserMap[i.ImGroupId]) > 0 {
	//	prefix += "^"
	//}
	//logstr += prefix + i.ImGroupId + ":" + i.Code + ":" + strconv.Itoa(int(supportLevels[i.ImGroupId])) +
	//	":" + strconv.Itoa(len(roomMicUserMap[i.ImGroupId])) + ":" + strconv.Itoa(int(visitCount[i.ImGroupId]))
	//}
	total := len(groupList)
	model.Log.Infof("GetGroupPowerGroups: GroupList size = %d", 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 groupList[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("GetGroupPowerGroups: final start = %d, end = %d, %v", beginPos, endPos, groupIds)

		/*		txGroupInfoMap, err := cv.BatchGetGroupInfo(model, groupIds, false)
				if err != nil {
					return myContext, err
				}*/

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

		uids := make([]uint64, 0)
		micUsersMap := make(map[string][]uint64, 0)
		for _, i := range groupList[beginPos:endPos] {
			// 规则:麦上够4个就全用;全空的话,用群主补
			u := roomMicUserMap[i.ImGroupId]
			if len(u) >= 4 {
				micUsersMap[i.ImGroupId] = u[0:4]
			} else if len(u) > 0 {
				micUsersMap[i.ImGroupId] = u
			} else {
				micUsersMap[i.ImGroupId] = []uint64{i.Owner}
			}
			uids = append(uids, micUsersMap[i.ImGroupId]...)
		}

		uids = utils.UniqueSliceUInt64(uids)
		userTiny, err := user_cv.GetUserTinyMap(uids)
		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 groupList[beginPos:endPos] {
			micUsers := make([]user_cv.CvUserTiny, 0)
			for _, j := range micUsersMap[i.ImGroupId] {
				micUsers = append(micUsers, userTiny[j])
			}

			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("GetGroupPowerGroups: 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:            len(roomMicUserMap[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:      micUsers,
				RoomUserCount: uint(roomCount[i.ImGroupId]),
				MaxStage:      maxStage,
				GameTypes:     games[i.TxGroupId],
			})
		}
	}

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

// @Tags 国家势力
// @Summary 国家势力团队信息
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param groupPowerId query int true "国家势力ID"
// @Success 200 {object} group_power_cv.CvGroupPowerTeam
// @Router /v1/groupPower/team [get]
func GroupPowerTeam(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)
	groupPowerId, err := strconv.ParseUint(c.Query("groupPowerId"), 10, 64)
	if err != nil {
		return myContext, err
	}
	usreId, err := req.GetUserId(c)
	if err != nil {
		return myContext, err
	}
	cvGroupPowerTeam, err := group_power_cv.GetCvGroupPowerTeam(myContext, groupPowerId, usreId)
	if err != nil {
		return myContext, err
	}
	resp.ResponseOk(c, cvGroupPowerTeam)
	return myContext, nil
}

// @Tags 国家势力
// @Summary 榜单排行榜,这周
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param type query int true "week:1:thisWeek 2:lastWeek" Enums(1,2)
// @Param pageSize query int true "分页大小 默认:10" default(10)
// @Param pageIndex query int true "第几个分页,从1开始 默认:1" default(1)
// @Success 200 {object} group_power_cv.CvGroupPowerDiamondTotal
// @Router /v1/groupPower/billboard/week [get]
func GroupPowerBillboardWeek(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)
	pageSize, err := strconv.Atoi(c.Query("pageSize"))
	if err != nil {
		pageSize = 10
	}
	pageIndex, err := strconv.Atoi(c.Query("pageIndex"))
	if err != nil {
		pageIndex = 1
	}
	t, err := strconv.ParseUint(c.Query("type"), 10, 64)
	if err != nil {
		return myContext, err
	}
	now := time.Now()
	monday := utils.GetMonday(now)
	midnight := time.Date(monday.Year(), monday.Month(), monday.Day(), 0, 0, 0, 0, time.Local)
	var beginTime, endTime time.Time
	if t == 1 {
		endTime = now
		beginTime = midnight
	} else if t == 2 {
		endTime = midnight
		beginTime = midnight.AddDate(0, 0, -7)
	} else {
		return myContext, myerr.NewSysError("type 参数错误")
	}
	cvGroupPowerDiamondTotals, err := group_power_cv.GetCvGroupPowerDiamondTotalList(beginTime, endTime, pageSize, pageIndex)
	if err != nil {
		return myContext, err
	}

	ids := make([]uint64, 0, len(cvGroupPowerDiamondTotals))
	for i, _ := range cvGroupPowerDiamondTotals {
		ids = append(ids, cvGroupPowerDiamondTotals[i].GroupPowerId)
	}

	userMap, err := group_power_cv.GetCvGroupPowerUserMapN(ids)
	if err != nil {
		return myContext, nil
	}

	for i, _ := range cvGroupPowerDiamondTotals {
		cvGroupPowerDiamondTotals[i].UserN = userMap[cvGroupPowerDiamondTotals[i].GroupPowerId]
	}

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

type ReturnGroupPowerBillboardOwnerWeek struct {
	User    user_cv.CvUserDetail `json:"user"`
	Diamond uint                 `json:"diamond"`
}

// @Tags 国家势力
// @Summary 榜单排行榜,这周,上周,top3,势力主的信息
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param type query int true "week:1:thisWeek 2:lastWeek" Enums(1,2)
// @Success 200 {object} ReturnGroupPowerBillboardOwnerWeek
// @Router /v1/groupPower/billboard/owner/week [get]
func GroupPowerBillboardOwnerWeek(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)
	userId, err := req.GetUserId(c)
	if err != nil {
		return myContext, err
	}
	t, err := strconv.ParseUint(c.Query("type"), 10, 64)
	if err != nil {
		return myContext, err
	}
	now := time.Now()
	monday := utils.GetMonday(now)
	midnight := time.Date(monday.Year(), monday.Month(), monday.Day(), 0, 0, 0, 0, time.Local)
	//var beginTime, endTime time.Time
	var beginTime time.Time
	if t == 1 {
		//endTime = now
		beginTime = midnight
	} else if t == 2 {
		//endTime = midnight
		beginTime = midnight.AddDate(0, 0, -7)
	} else {
		return myContext, myerr.NewSysError("type 参数错误")
	}

	type R struct {
		DiamondNum uint
		UserId     uint64
	}
	rs := []R{}
	//fixme:解决性能问题.
	/*	if err := mysql.Db.Raw("SELECT SUM(l.diamond_num) AS diamond_num, (SELECT u.user_id from group_power_user u where u.group_power_id = l.group_power_id and u.role = ?) as user_id  FROM group_power_diamond_log l, group_power p WHERE l.group_power_id = p.id and p.status = ? and l.created_time >= ? AND l.created_time < ? GROUP BY l.group_power_id ORDER BY diamond_num DESC LIMIT 3", groupPower_m2.GroupPowerUserRoleMgr, groupPower_m2.GroupPowerUserHas, beginTime, endTime).Scan(&rs).Error; err != nil {
		return myContext, err
	}*/
	//用缓存
	rows, err := redisCli.GetRedis().ZRevRangeWithScores(context.Background(), redis_key.GetGroupPowerDiamondLogWeek(beginTime.Format(utils.COMPACT_DATE_FORMAT)), 0, -1).Result()
	if err != nil {
		return nil, myerr.WrapErr(err)
	}
	groupPowerIds := make([]uint64, 0, len(rows))
	for i, _ := range rows {
		groupPowerId, err := strconv.ParseUint(rows[i].Member.(string), 10, 64)
		if err != nil {
			return nil, myerr.WrapErr(err)
		}
		groupPowerIds = append(groupPowerIds, groupPowerId)
	}
	//搜集所有的群组(有效) + 群组管理人
	groupPowerUsers := []groupPower_m.GroupPowerUser{}
	if err := mysql.Db.Raw("SELECT u.user_id, u.group_power_id FROM group_power_user u, group_power p WHERE u.group_power_id = p.id AND u.role = ? and p.status = ? and p.id in (?)", groupPower_e.GroupPowerUserRoleMgr, groupPower_e.GroupPowerUserHas, groupPowerIds).Scan(&groupPowerUsers).Error; err != nil {
		return nil, myerr.WrapErr(err)
	}
	//转换成map
	groupPowerIdUserIdMap := map[uint64]uint64{}
	for _, r := range groupPowerUsers {
		groupPowerIdUserIdMap[r.GroupPowerId] = r.UserId
	}
	//只需找到前3个
	for i, _ := range rows {
		groupPowerId, err := strconv.ParseUint(rows[i].Member.(string), 10, 64)
		if err != nil {
			return nil, myerr.WrapErr(err)
		}
		if len(rs) >= 3 {
			break
		} else if userId, flag := groupPowerIdUserIdMap[groupPowerId]; flag {
			rs = append(rs, R{
				DiamondNum: uint(rows[i].Score),
				UserId:     userId,
			})
		}
	}

	userIds := make([]uint64, 0, 64)
	for i, _ := range rs {
		userIds = append(userIds, rs[i].UserId)
	}

	userMap, err := user_cv.GetUserDetailMap(userIds, userId)
	if err != nil {
		return myContext, err
	}

	results := make([]ReturnGroupPowerBillboardOwnerWeek, 0, len(userIds))
	for i, _ := range rs {
		results = append(results, ReturnGroupPowerBillboardOwnerWeek{
			User:    *userMap[rs[i].UserId],
			Diamond: rs[i].DiamondNum,
		})
	}
	resp.ResponseOk(c, results)
	return myContext, nil
}

// @Tags 家族
// @Summary 家族信息
// @Param id query int true "家族id"
// @Success 200 {object} group_power_cv.GroupPowerInfo
// @Router /v1/groupPower/info [get]
func GroupPowerInfo(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)
	myUserId, err := req.GetUserId(c)
	if err != nil {
		return myContext, err
	}
	familyId, err := strconv.ParseUint(c.Query("id"), 10, 64)
	if err != nil {
		return myContext, err
	}
	model := domain.CreateModelContext(myContext)
	gp := &groupPower_m.GroupPower{Entity: mysql.Entity{ID: familyId}}
	gpInfo, err := gp.Get(model)
	if err != nil {
		return myContext, myerr.WrapErr(err)
	}
	gpU := &groupPower_m.GroupPowerUser{GroupPowerId: gpInfo.ID}
	members, total, _, _, err := gpU.GetBy(model, 5, 0)
	if err != nil {
		return myContext, myerr.WrapErr(err)
	}
	uids := make([]uint64, 0, len(members))
	for _, v := range members {
		uids = append(uids, v.UserId)
	}
	//查找用户信息
	//uids = common.UniqueSliceUInt64(uids)
	userMap, err := user_c.GetUserTinyMap(domain.CreateModelContext(myContext), uids, true)
	if err != nil {
		return myContext, err
	}
	resMembers := make([]*group_power_cv.GroupPowerUser, 0, len(members))
	for _, v := range members {
		resMembers = append(resMembers, &group_power_cv.GroupPowerUser{User: userMap[v.UserId], Role: v.Role})
	}
	gradeM, err := groupPower_m.MGetGroupPowerGrade(model, []mysql.ID{gp.ID})
	if err != nil {
		return myContext, err
	}
	grade := gradeM[gp.ID]
	nextExp := groupPower_e.GroupPowerGradeExp[groupPower_e.GroupPowerGradeMax]
	if grade.Grade != groupPower_e.GroupPowerGradeMax {
		nextExp = groupPower_e.GroupPowerGradeExp[grade.Grade+1]
	}
	maxNum := group_power_s.GetGroupPowerMaxMemberNum(model, gpInfo.ID, grade.Grade)
	info := &group_power_cv.GroupPower{
		Id: gpInfo.ID, Name: gpInfo.Name, Nameplate: gpInfo.Nameplate, Declaration: gpInfo.Declaration, Icon: gpInfo.Icon,
		Grade: grade.Grade, Exp: grade.Exp, NextExp: nextExp, GradeName: gpInfo.GradeName, GradeMedal: gpInfo.GradeMedal,
		MemberNum: mysql.Num(total), MemberMax: mysql.Num(maxNum),
	}
	if info.Icon != "" {
		info.Icon = common.MakeFullUrl(info.Icon)
	}
	if info.Nameplate == "" {
		groupInfo, err := group_m.GetGroupInfoByOwner(model, myUserId)
		if err != nil {
			return myContext, err
		}
		if groupInfo != nil {
			info.Nameplate = groupInfo.Name
			if len(info.Nameplate) > 6 {
				info.Nameplate = info.Nameplate[:6]
			}
		}
	}
	// 家族月排名
	beginDate, endDate := now.BeginningOfMonth().Format("2006-01-02"), now.EndOfMonth().Format("2006-01-02")
	info.MonthRank, err = groupPower_m.GetGroupPowerExpRankById(model, beginDate, endDate, 30, info.Id)
	if err != nil {
		return myContext, err
	}
	// 我在该家族中的角色
	myPU := groupPower_m.GroupPowerUser{UserId: myUserId}
	myGroupPUser, err := myPU.GetGroupPowerUser(model)
	if err != nil {
		return myContext, err
	}
	if myGroupPUser != nil && myGroupPUser.GroupPowerId == info.Id {
		info.Role = int(myGroupPUser.Role)
	} else {
		// 是否申请了加入
		apply, err := groupPower_m.GetGroupPowerApplyJoin(model, myUserId, info.Id, 0)
		if err != nil {
			return myContext, err
		}
		if apply != nil && apply.IsAccept == 0 {
			info.IsApply = true
		}
	}
	// 补上家族之星三个榜一
	stars, err := groupPower_m.GetGroupPowerMonthStartTop1(model, gp.ID)
	if err != nil {
		return myContext, myerr.WrapErr(err)
	}
	var cvStar []*group_power_cv.GroupPowerStar
	if len(stars) > 0 {
		var userIds []uint64
		for _, star := range stars {
			userIds = append(userIds, star.UserId)
		}
		userM, err := user_cv.GetUserTinyMap(userIds)
		if err != nil {
			return myContext, err
		}
		for _, star := range stars {
			cvStar = append(cvStar, &group_power_cv.GroupPowerStar{
				User:        userM[star.UserId],
				RankingType: groupPower_e.GroupPowerRankType(star.Type),
			})
		}
	}
	res := group_power_cv.GroupPowerInfo{Info: info, Members: resMembers, Stars: cvStar}

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

// @Tags 家族
// @Summary 获取某个家族房间列表
// @Param id query int true "家族id"
// @Param pageSize query int true "分页大小 默认:10" default(10)
// @Param pageIndex query int true "分页开始索引,偏移量" default(1)
// @Success 200 {object} []group_cv.PopularGroupInfo
// @Router /v1/groupPower/rooms [get]
func GroupPowerRooms(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)
	userId, err := req.GetUserId(c)
	if err != nil {
		return myContext, err
	}
	familyId, err := strconv.ParseUint(c.Query("id"), 10, 64)
	if err != nil {
		return myContext, err
	}
	pageSize, err := strconv.Atoi(c.Query("pageSize"))
	if err != nil {
		return myContext, err
	}
	pageIndex, err := strconv.Atoi(c.Query("pageIndex"))
	if err != nil {
		return myContext, err
	}
	if pageIndex == 1 {
		pageIndex = 0
	}
	model := domain.CreateModelContext(myContext)
	rooms, nextPageIndex, hasNextPage, err := group_m.GetFamilyRooms(model, familyId, pageSize, pageIndex)
	if err != nil {
		return myContext, err
	}
	resRooms, err := group_cv.BuildPopularGroupInfo(model, userId, rooms)
	if err != nil {
		return myContext, err
	}

	resp.ResponsePageBaseOk(c, resRooms, nextPageIndex, hasNextPage)
	return myContext, nil
}

// @Tags 家族
// @Summary 获取家族成员列表
// @Param userCode query string false "用户extId,搜索时输入"
// @Param id query int true "家族id"
// @Param pageSize query int true "分页大小 默认:10" default(10)
// @Param pageIndex query int true "分页开始索引,偏移量" default(1)
// @Success 200 {object} []group_power_cv.FamilyMemberDetail
// @Router /v1/groupPower/members [get]
func GroupPowerMembers(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)
	userId, err := req.GetUserId(c)
	if err != nil {
		return myContext, err
	}
	familyId, err := strconv.ParseUint(c.Query("id"), 10, 64)
	if err != nil {
		return myContext, err
	}
	pageSize, err := strconv.Atoi(c.Query("pageSize"))
	if err != nil {
		return myContext, err
	}
	pageIndex, err := strconv.Atoi(c.Query("pageIndex"))
	if err != nil {
		return myContext, err
	}
	if pageIndex == 1 {
		pageIndex = 0
	}
	model := domain.CreateModelContext(myContext)
	userCode := c.Query("userCode")

	gpU := &groupPower_m.GroupPowerUser{GroupPowerId: familyId}
	if userCode != "" {
		u, err := user_m.GetUserByCode(model, userCode)
		if err != nil || u == nil || u.ID <= 0 {
			resp.ResponsePageBaseOk(c, nil, 0, false)
			return myContext, nil
		}
		if u != nil && u.ID > 0 {
			gpU.UserId = u.ID
		}
	}

	members, _, nextPageIndex, hasNextPage, err := gpU.GetBy(model, pageSize, pageIndex)
	if err != nil {
		return myContext, err
	}

	userIds := make([]uint64, 0)
	for _, v := range members {
		userIds = append(userIds, v.UserId)
	}

	result := make([]group_power_cv.FamilyMemberDetail, 0)
	if len(userIds) > 0 {
		users, err := user_cv.BatchGetUserExtend(model, userIds, userId)
		if err != nil {
			return myContext, err
		}

		for _, v := range members {
			result = append(result, group_power_cv.FamilyMemberDetail{
				User: users[v.UserId],
				Role: v.Role,
			})
		}
	}

	resp.ResponsePageBaseOk(c, result, nextPageIndex, hasNextPage)
	return myContext, nil
}

// @Tags 家族
// @Summary 申请加入家族
// @Param id formData int true "家族id"
// @Success 200
// @Router /v1/groupPower/apply [post]
func GroupPowerApplyJoin(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)
	userId, err := req.GetUserId(c)
	if err != nil {
		return myContext, err
	}
	familyId, err := strconv.ParseUint(c.PostForm("id"), 10, 64)
	if err != nil {
		return myContext, myerr.WrapErr(err)
	}
	// Aoxi要求不能让这些人加入家族
	var banUserIds = []uint64{251, 1384611, 4223511, 4338751, 4339471, 4339541, 4354581, 6541, 23971, 5191971, 5192161, 5192201, 5429011, 5429121, 5429191, 5687371, 6160461, 6185321, 6194741, 6315381}
	var banUserMap = make(map[uint64]bool)
	for _, id := range banUserIds {
		banUserMap[id] = true
	}
	if _, ok := banUserMap[userId]; ok {
		return myContext, bizerr.GroupPowerCannotJoin
	}
	model := domain.CreateModelContext(myContext)

	// 判断家族是否存在
	gp := &groupPower_m.GroupPower{Entity: mysql.Entity{ID: familyId}}
	gpInfo, err := gp.Get(model)
	if err != nil {
		return myContext, err
	}
	if gpInfo == nil || gpInfo.ID <= 0 {
		return myContext, bizerr.GroupPowerNotExist
	}
	// 判断是否加入了家族
	gpU := groupPower_m.GroupPowerUser{UserId: userId}
	uList, err := gpU.Get(model.Db)
	if err != nil {
		return myContext, err
	}
	if len(uList) > 0 {
		return myContext, bizerr.GroupPowerHasJoinOther
	}
	// 判断家族是否满人了
	nowNum, err := groupPower_m.GetMemberNum(model, familyId)
	if err != nil {
		return myContext, myerr.WrapErr(err)
	}
	maxNum := group_power_s.GetGroupPowerMaxMemberNum(model, familyId, gpInfo.Grade)
	//maxNum := group_power_cv.GroupPowerGradePrivilegeNum[gpInfo.Grade][0].Num
	if nowNum+1 > int64(maxNum) {
		return myContext, bizerr.GroupPowerMemberMax
	}

	// 插入申请表
	err = groupPower_m.InsertGroupPowerApplyJoin(model, userId, gpInfo.ID)
	if err != nil {
		return myContext, err
	}

	// 找到家族管理员们
	mgrList, err := groupPower_m.GetGroupPowerMgrList(model, gpInfo.ID)
	if err != nil {
		model.Log.Errorf("GroupPowerApplyJoin err:%v, id:%v", err, gpInfo.ID)
	} else {
		for _, v := range mgrList {
			// 发小助手通知用户
			msg.SendLittleAssistantMsg(model, v, 0, "", "", "", "", "")
			//msg.SendLittleAssistantMsg(model, v, msg_e.GroupPowerApplyJoinMsg, "", "", "", "", "")
		}

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

// @Tags 家族
// @Summary 审核加入家族申请
// @Param userExtId formData string true "用户extId"
// @Param type formData int true "1.通过,2.不通过"
// @Success 200
// @Router /v1/groupPower/apply/pass [post]
func GroupPowerApplyPass(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)
	userId, err := req.GetUserId(c)
	if err != nil {
		return myContext, err
	}
	optType, err := strconv.Atoi(c.PostForm("type"))
	if err != nil {
		return myContext, bizerr.InvalidParameter
	}
	if optType < 1 || optType > 2 {
		return myContext, bizerr.InvalidParameter
	}
	userExtId := c.PostForm("userExtId")
	if userExtId == "" {
		return myContext, bizerr.InvalidParameter
	}
	model := domain.CreateModelContext(myContext)
	optUser, err := user_c.GetUserByExternalId(model, userExtId)
	if err != nil {
		return myContext, err
	}
	// Aoxi要求不能让这些人加入家族
	banUserMap := map[uint64]bool{251: true, 1384611: true, 4223511: true, 4338751: true, 4339471: true, 4339541: true,
		4354581: true, 6541: true, 23971: true}
	if _, ok := banUserMap[optUser.ID]; ok {
		return myContext, bizerr.GroupPowerHaveNoPower
	}

	// 判断是否加入了家族
	gpU := groupPower_m.GroupPowerUser{UserId: userId}
	myGroupPUser, err := gpU.GetGroupPowerUser(model)
	if err != nil {
		return myContext, err
	}
	// 操作者是否加入了家族,是否有操作权限
	if myGroupPUser == nil || myGroupPUser.ID == 0 {
		return myContext, bizerr.GroupPowerHaveNoJoin
	}
	if myGroupPUser.Role == 0 || myGroupPUser.Role == groupPower_e.GroupPowerUserRoleUser {
		return myContext, bizerr.GroupPowerHaveNoPower
	}
	// 查找申请记录
	apply, err := groupPower_m.GetGroupPowerApplyJoin(model, optUser.ID, myGroupPUser.GroupPowerId, 0)
	if err != nil {
		return myContext, err
	}
	if apply == nil {
		return myContext, bizerr.GroupPowerHaveNoApply
	}

	if optType == 2 { // 拒绝
		// 更改申请表状态
		err = groupPower_m.OptGroupPowerApplyJoinById(model, apply.Id, userId, optType)
		if err != nil {
			return myContext, err
		}
		resp.ResponseOk(c, nil)
		// 家族小助手通知
		go group_power_s.CheckoutSendMsgToMgr(myContext, myGroupPUser.GroupPowerId)
		return myContext, nil
	}
	// 判断家族是否满人了
	nowNum, err := groupPower_m.GetMemberNum(model, apply.GroupPowerId)
	if err != nil {
		return myContext, myerr.WrapErr(err)
	}
	gradeM, err := groupPower_m.MGetGroupPowerGrade(model, []mysql.ID{apply.GroupPowerId})
	if err != nil {
		return myContext, err
	}
	grade := gradeM[apply.GroupPowerId]
	//maxNum := group_power_cv.GroupPowerGradePrivilegeNum[grade.Grade][0].Num
	maxNum := group_power_s.GetGroupPowerMaxMemberNum(model, apply.GroupPowerId, grade.Grade)
	if int(nowNum+1) > maxNum {
		return myContext, bizerr.GroupPowerMemberMax
	}

	err = model.Transaction(func(model *domain.Model) error {
		txModel := domain.CreateModel(model.CtxAndDb)
		// 插入家族成员表
		gpU := groupPower_m.GroupPowerUser{GroupPowerId: apply.GroupPowerId, UserId: apply.UserId, Role: groupPower_e.GroupPowerUserRoleUser}
		err := gpU.Create(txModel.Db)
		if err != nil {
			txModel.Log.Errorf("GroupPowerApplyPass err:%v, info:%v", err, gpU)
			return err
		}
		newNum, err := groupPower_m.GetMemberNum(txModel, apply.GroupPowerId)
		if err != nil {
			txModel.Log.Errorf("GroupPowerApplyPass err:%v, info:%v", err, gpU)
			return err
		}
		if int(newNum) > maxNum {
			txModel.Log.Errorf("GroupPowerApplyPass err:%v, info:%v", bizerr.GroupPowerMemberMax, gpU)
			return bizerr.GroupPowerMemberMax
		}
		// 更改申请表状态
		err = groupPower_m.OptGroupPowerApplyJoinById(model, apply.Id, userId, optType)
		if err != nil {
			return err
		}
		// 删除他在其他家族未处理的申请
		err = groupPower_m.DelGroupPowerApplyJoinNoDeal(model, apply.UserId)
		if err != nil {
			return err
		}

		return nil
	})
	if err != nil {
		return myContext, err
	}
	// 发小助手通知用户
	//err = msg.SendLittleAssistantMsg(model, apply.UserId, msg_e.GroupPowerWelcomeJoin, "", "", "", "", "")
	//if err != nil {
	//	model.Log.Errorf("GroupPowerApplyPass msg err:%v", err)
	//}
	// 家族小助手通知
	go group_power_s.CheckoutSendMsgToMgr(myContext, myGroupPUser.GroupPowerId)

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

// @Tags 家族
// @Summary 申请加入列表
// @Param pageSize query int true "分页大小 默认:10" default(10)
// @Param pageIndex query int true "分页开始索引,偏移量" default(1)
// @Success 200 {object} []group_power_cv.FamilyApplyList
// @Router /v1/groupPower/apply/list [get]
func GroupPowerApplyList(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)
	userId, err := req.GetUserId(c)
	if err != nil {
		return myContext, err
	}
	pageSize, err := strconv.Atoi(c.Query("pageSize"))
	if err != nil {
		return myContext, err
	}
	pageIndex, err := strconv.Atoi(c.Query("pageIndex"))
	if err != nil {
		return myContext, err
	}
	if pageIndex == 1 {
		pageIndex = 0
	}
	model := domain.CreateModelContext(myContext)

	// 判断是否加入了家族
	gpU := groupPower_m.GroupPowerUser{UserId: userId}
	myGroupPUser, err := gpU.GetGroupPowerUser(model)
	if err != nil {
		return myContext, err
	}
	// 操作者是否加入了家族,是否有操作权限
	if myGroupPUser == nil || myGroupPUser.ID == 0 {
		return myContext, bizerr.GroupPowerHaveNoJoin
	}
	if myGroupPUser.Role == 0 || myGroupPUser.Role == groupPower_e.GroupPowerUserRoleUser {
		return myContext, bizerr.GroupPowerHaveNoPower
	}
	// 申请列表
	rows, nextPageIndex, hasNextPage, err := groupPower_m.OptGroupPowerApplyList(model, myGroupPUser.GroupPowerId, pageSize, pageIndex)
	if err != nil {
		return myContext, err
	}

	uids := make([]uint64, 0, len(rows))
	for _, v := range rows {
		uids = append(uids, v.UserId, v.MgrId)
	}
	//查找用户信息
	uids = common.UniqueSliceUInt64(uids)
	userMap, err := user_c.GetUserTinyMap(domain.CreateModelContext(myContext), uids, true)

	result := make([]*group_power_cv.FamilyApplyList, 0, len(rows))
	for _, v := range rows {
		info := &group_power_cv.FamilyApplyList{User: userMap[v.UserId], Time: v.CreatedTime.UnixMilli(), Status: v.IsAccept}
		if v.MgrId > 0 {
			info.MgrName = userMap[v.MgrId].Nick
		}
		result = append(result, info)
	}

	resp.ResponsePageBaseOk(c, result, nextPageIndex, hasNextPage)
	return myContext, nil
}

// @Tags 家族
// @Summary 申请人数
// @Success 200 {object} int
// @Router /v1/groupPower/apply/count [get]
func GroupPowerApplyCount(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)
	userId, err := req.GetUserId(c)
	if err != nil {
		return myContext, err
	}
	model := domain.CreateModelContext(myContext)

	// 判断是否加入了家族
	gpU := groupPower_m.GroupPowerUser{UserId: userId}
	myGroupPUser, err := gpU.GetGroupPowerUser(model)
	if err != nil {
		return myContext, err
	}
	// 操作者是否加入了家族,是否有操作权限
	if myGroupPUser == nil || myGroupPUser.ID == 0 {
		return myContext, bizerr.GroupPowerHaveNoJoin
	}
	if myGroupPUser.Role == 0 || myGroupPUser.Role == groupPower_e.GroupPowerUserRoleUser {
		return myContext, bizerr.GroupPowerHaveNoPower
	}
	// 申请人数
	cnt, err := groupPower_m.CountGroupPowerApply(model, myGroupPUser.GroupPowerId, 0)
	if err != nil {
		return myContext, err
	}

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

// @Tags 家族
// @Summary 退出/踢出家族
// @Param type formData int true "1.自己退出,2.踢人"
// @Param userExtId formData string false "用户extId"
// @Success 200
// @Router /v1/groupPower/quit [post]
func GroupPowerQuit(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)
	userId, err := req.GetUserId(c)
	if err != nil {
		return myContext, err
	}
	quitType, err := strconv.Atoi(c.PostForm("type"))
	if err != nil {
		return myContext, myerr.WrapErr(err)
	}
	if quitType < 1 || quitType > 2 {
		return myContext, bizerr.InvalidParameter
	}
	model := domain.CreateModelContext(myContext)

	if quitType == 1 { // 主动退出
		// 判断是否加入了家族
		gpU := groupPower_m.GroupPowerUser{UserId: userId}
		groupPUser, err := gpU.GetGroupPowerUser(model)
		if err != nil {
			return myContext, err
		}
		if groupPUser == nil {
			return myContext, bizerr.GroupPowerHaveNoJoin
		}
		if groupPUser.Role == groupPower_e.GroupPowerUserRoleMgr {
			return myContext, bizerr.GroupPowerCannotQuit
		}
		// 退出家族、log
		err = model.Transaction(func(model *domain.Model) error {
			return groupPower_m.QuitFamily(model, userId, userId, groupPUser.GroupPowerId)
		})
		if err != nil {
			return myContext, err
		}

		resp.ResponseOk(c, nil)
		return myContext, nil
	}
	// 判断是否加入了家族
	gpU := groupPower_m.GroupPowerUser{UserId: userId}
	myGroupPUser, err := gpU.GetGroupPowerUser(model)
	if err != nil {
		return myContext, err
	}
	// 操作者是否加入了家族,是否有操作权限
	if myGroupPUser == nil {
		return myContext, bizerr.GroupPowerHaveNoJoin
	}
	if myGroupPUser.Role == 0 || myGroupPUser.Role == groupPower_e.GroupPowerUserRoleUser {
		return myContext, bizerr.GroupPowerHaveNoPower
	}
	// 被踢人信息
	userExtId := c.PostForm("userExtId")
	if userExtId == "" {
		return myContext, bizerr.InvalidParameter
	}
	u, err := user_c.GetUserByExternalId(model, userExtId)
	if err != nil {
		return myContext, err
	}
	// 被踢者
	gpUKick := groupPower_m.GroupPowerUser{UserId: userId}
	kickGroupPUser, err := gpUKick.GetGroupPowerUser(model)
	if err != nil {
		return myContext, err
	}
	if kickGroupPUser == nil {
		return myContext, bizerr.GroupPowerHaveNoJoin
	}
	// 退出家族、log
	err = model.Transaction(func(model *domain.Model) error {
		return groupPower_m.QuitFamily(model, u.ID, userId, kickGroupPUser.GroupPowerId)
	})
	if err != nil {
		return myContext, err
	}

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

// @Tags 家族
// @Summary 家族退出列表
// @Param pageSize query int true "分页大小 默认:10" default(10)
// @Param pageIndex query int true "第几个分页,从1开始 默认:1" default(1)
// @Success 200 {object} []group_power_cv.FamilyQuitList
// @Router /v1/groupPower/quit/list [get]
func GroupPowerQuitList(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)
	userId, err := req.GetUserId(c)
	if err != nil {
		return myContext, err
	}
	pageSize, err := strconv.Atoi(c.Query("pageSize"))
	if err != nil {
		return myContext, err
	}
	pageIndex, err := strconv.Atoi(c.Query("pageIndex"))
	if err != nil {
		return myContext, err
	}
	if pageIndex == 1 {
		pageIndex = 0
	}
	model := domain.CreateModelContext(myContext)

	// 判断是否加入了家族
	gpU := groupPower_m.GroupPowerUser{UserId: userId}
	myGroupPUser, err := gpU.GetGroupPowerUser(model)
	if err != nil {
		return myContext, err
	}
	// 操作者是否加入了家族,是否有操作权限
	if myGroupPUser == nil || myGroupPUser.ID == 0 {
		return myContext, bizerr.GroupPowerHaveNoJoin
	}
	if myGroupPUser.Role == 0 || myGroupPUser.Role == groupPower_e.GroupPowerUserRoleUser {
		return myContext, bizerr.GroupPowerHaveNoPower
	}
	// 列表
	rows, nextPageIndex, hasNextPage, err := groupPower_m.GroupPowerQuitList(model, myGroupPUser.GroupPowerId, pageSize, pageIndex)
	if err != nil {
		return myContext, err
	}

	uids := make([]uint64, 0, len(rows))
	for _, v := range rows {
		uids = append(uids, v.UserId, v.MgrId)
	}
	//查找用户信息
	uids = common.UniqueSliceUInt64(uids)
	userMap, err := user_c.GetUserTinyMap(domain.CreateModelContext(myContext), uids, true)

	result := make([]*group_power_cv.FamilyQuitList, 0, len(rows))
	for _, v := range rows {
		item := &group_power_cv.FamilyQuitList{User: userMap[v.UserId], Time: v.CreatedTime.UnixMilli()}
		if v.UserId == v.MgrId {
			item.QuitType = 1 // 主动退出
		} else {
			item.QuitType = 2 // 被踢出
			item.MgrName = userMap[v.MgrId].Nick
		}
		result = append(result, item)
	}

	resp.ResponsePageBaseOk(c, result, nextPageIndex, hasNextPage)
	return myContext, nil
}

// @Tags 家族
// @Summary 设置/取消管理员
// @Param userExtId formData string false "用户extId"
// @Param type formData int true "1.设置为管理员,2.取消管理员"
// @Success 200
// @Router /v1/groupPower/admin [post]
func GroupPowerSetAdmin(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)
	userId, err := req.GetUserId(c)
	if err != nil {
		return myContext, err
	}
	optType, err := strconv.Atoi(c.PostForm("type"))
	if err != nil {
		return myContext, bizerr.InvalidParameter
	}
	if optType < 1 || optType > 2 {
		return myContext, bizerr.InvalidParameter
	}
	userExtId := c.PostForm("userExtId")
	if userExtId == "" {
		return myContext, bizerr.InvalidParameter
	}
	model := domain.CreateModelContext(myContext)
	optUser, err := user_c.GetUserByExternalId(model, userExtId)
	if err != nil {
		return myContext, err
	}

	// 判断是否加入了家族
	gpU := groupPower_m.GroupPowerUser{UserId: userId}
	myGroupPUser, err := gpU.GetGroupPowerUser(model)
	if err != nil {
		return myContext, err
	}
	// 操作者是否加入了家族,是否有操作权限
	if myGroupPUser == nil {
		return myContext, bizerr.GroupPowerHaveNoJoin
	}
	if myGroupPUser.Role != groupPower_e.GroupPowerUserRoleMgr {
		return myContext, bizerr.GroupPowerHaveNoPower
	}
	// 被操作者是否加入了家族
	gpOptUser := groupPower_m.GroupPowerUser{UserId: optUser.ID}
	optGroupPUser, err := gpOptUser.GetGroupPowerUser(model)
	if err != nil {
		return myContext, err
	}
	if optGroupPUser == nil {
		return myContext, bizerr.GroupPowerUserHaveNoJoin
	}
	if optUser.ID == userId { // 不能操作自己
		return myContext, bizerr.GroupPowerHaveNoPower
	}
	// 目标身份
	var targetRole groupPower_e.GroupPowerUserRole
	if optType == 1 {
		targetRole = groupPower_e.GroupPowerUserRoleAdmin
	} else {
		targetRole = groupPower_e.GroupPowerUserRoleUser
	}
	// 和原来的身份是否一致
	if optGroupPUser.Role == targetRole {
		return myContext, bizerr.GroupPowerHaveAlreadyChange
	}
	// 变更
	err = groupPower_m.UpdateFamilyAdmin(model, optGroupPUser.UserId, optGroupPUser.GroupPowerId, targetRole)
	if optGroupPUser == nil {
		return myContext, myerr.WrapErr(err)
	}

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

// @Tags 家族
// @Summary 设置家族信息
// @Param id formData int true "家族id"
// @Param icon formData string false "家族图片"
// @Param name formData string false "家族名称"
// @Param nameplate formData string false "家族铭牌"
// @Param declaration formData string false "家族宣言"
// @Success 200 {object} group_power_cv.GroupPower
// @Router /v1/groupPower/info/set [post]
func GroupPowerSetInfo(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)
	userId, lang, err := req.GetUserIdLang(c, myContext)
	if err != nil {
		return myContext, err
	}
	type param struct {
		Id          uint64 `form:"id"`
		Name        string `form:"name"`
		Nameplate   string `form:"nameplate"`   // 铭牌
		Declaration string `form:"declaration"` // 宣言
		Icon        string `form:"icon"`        // 头像
	}
	var para param
	if err := c.ShouldBind(&para); err != nil {
		return myContext, err
	}
	if para.Id <= 0 {
		return myContext, bizerr.InvalidParameter
	}
	model := domain.CreateModelContext(myContext)

	// 判断是否加入了家族
	gpU := groupPower_m.GroupPowerUser{UserId: userId}
	myGroupPUser, err := gpU.GetGroupPowerUser(model)
	if err != nil {
		return myContext, err
	}
	// 操作者是否加入了家族,是否有操作权限
	if myGroupPUser == nil {
		return myContext, bizerr.GroupPowerHaveNoJoin
	}
	if myGroupPUser.Role != groupPower_e.GroupPowerUserRoleMgr {
		return myContext, bizerr.GroupPowerHaveNoPower
	}
	// 检查铭牌是否能够修改
	if para.Nameplate != "" {
		// 等级检查
		gradeM, err := groupPower_m.MGetGroupPowerGrade(model, []mysql.ID{myGroupPUser.GroupPowerId})
		if err != nil {
			return myContext, err
		}
		grade := gradeM[myGroupPUser.GroupPowerId]
		if grade.Grade < 1 {
			return myContext, res_m.GetErrByLanguage(model.Db, common.MSG_ID_SET_FAMILY_NAMEPL, lang, bizerr.GroupPowerChangeNameplate)
		}
		// 检查铭牌长度和唯一性
		if len(para.Nameplate) > groupPower_e.LongestNameplate {
			return myContext, bizerr.GroupPowerHaveTooLong
		}
		if groupPower_m.IsExistsNameplate(model, para.Nameplate) {
			return myContext, bizerr.GroupPowerCannotRepeated
		}
	}
	if para.Icon != "" {
		switch config.GetConfigApp().MODERATE {
		case "AWS":
			passed, err := aws.ModerateLabels(model.Log, userId, para.Icon)
			if err == nil {
				if !passed {
					return myContext, bizerr.ImagePolicyViolation
				}
			} else {
				model.Log.Warnf("ModerateLabels err:%v", err)
			}
		case "TENCENT":
			label, err := tencentyun.ModerateImage(model, userId, "", utils.StripAwsPrefix(para.Icon), para.Icon)
			if err == nil && label != "Pass" {
				return myContext, bizerr.ImagePolicyViolation
			}
		}
	}

	// 修改家族信息
	err = groupPower_m.UpdateFamily(model, para.Id, para.Name, para.Nameplate, para.Declaration, para.Icon)
	if err != nil {
		return myContext, myerr.WrapErr(err)
	}
	// 返回家族信息
	gp := &groupPower_m.GroupPower{Entity: mysql.Entity{ID: para.Id}}
	gpInfo, err := gp.Get(model)
	if err != nil {
		return myContext, myerr.WrapErr(err)
	}
	gpMember := &groupPower_m.GroupPowerUser{GroupPowerId: gpInfo.ID}
	_, total, _, _, err := gpMember.GetBy(model, 5, 0)
	if err != nil {
		return myContext, myerr.WrapErr(err)
	}
	gradeM, err := groupPower_m.MGetGroupPowerGrade(model, []mysql.ID{gp.ID})
	if err != nil {
		return myContext, err
	}
	grade := gradeM[gp.ID]
	nextExp := groupPower_e.GroupPowerGradeExp[groupPower_e.GroupPowerGradeMax]
	if grade.Grade != groupPower_e.GroupPowerGradeMax {
		nextExp = groupPower_e.GroupPowerGradeExp[grade.Grade+1]
	}
	maxNum := group_power_s.GetGroupPowerMaxMemberNum(model, gpInfo.ID, grade.Grade)
	info := &group_power_cv.GroupPower{
		Id: gpInfo.ID, Name: gpInfo.Name, Nameplate: gpInfo.Nameplate, Declaration: gpInfo.Declaration, Icon: gpInfo.Icon,
		Grade: grade.Grade, Exp: grade.Exp, NextExp: nextExp, GradeName: gpInfo.GradeName, GradeMedal: gpInfo.GradeMedal,
		MemberNum: mysql.Num(total), MemberMax: mysql.Num(maxNum),
	}
	if info.Icon != "" {
		info.Icon = common.MakeFullUrl(info.Icon)
	}
	// 我在该家族中的角色
	if myGroupPUser != nil && myGroupPUser.GroupPowerId == info.Id {
		info.Role = int(myGroupPUser.Role)
	}

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