package group_power_cv

import (
	"context"
	"git.hilo.cn/hilo-common/domain"
	"git.hilo.cn/hilo-common/mycontext"
	"git.hilo.cn/hilo-common/mylogrus"
	"git.hilo.cn/hilo-common/resource/mysql"
	"git.hilo.cn/hilo-common/resource/redisCli"
	"git.hilo.cn/hilo-common/utils"
	"gorm.io/gorm"
	"hilo-group/_const/enum/groupPower_e"
	"hilo-group/_const/enum/group_e"
	"hilo-group/_const/enum/res_e"
	"hilo-group/_const/redis_key"
	"hilo-group/cv/user_cv"
	"hilo-group/domain/model/groupPower_m"
	"hilo-group/domain/model/group_m"
	"hilo-group/domain/model/user_m"
	"hilo-group/myerr"
	"sort"
	"strconv"
	"time"
)

type CvGroupPowerTeam struct {
	//上一周
	LastWeek CvGroupPowerSupportCount `json:"lastWeek"`
	//这一周
	ThisWeek CvGroupPowerSupportCount `json:"thisWeek"`
	//拥有者 userBase, 一般只有一个,
	Owers []*user_cv.CvUserDetail `json:"owers"`
	//助手 userBase
	Assistants []*user_cv.CvUserDetail `json:"assistants"`
}

func GetGroupPower(groupPowerId mysql.ID) (string, error) {
	groupPower := groupPower_m.GroupPower{}
	if err := mysql.Db.Model(&groupPower_m.GroupPower{}).First(&groupPower, &groupPowerId).Error; err != nil {
		return "", myerr.WrapErr(err)
	}
	return groupPower.GroupUid, nil
}

func GetGroupPowerGroupUids(groupPowerIds []mysql.ID) ([]string, error) {
	groupPowers := []groupPower_m.GroupPower{}
	if err := mysql.Db.Model(&groupPower_m.GroupPower{}).Where("id in (?)", groupPowerIds).Find(&groupPowers).Error; err != nil {
		return nil, myerr.WrapErr(err)
	}
	//
	groupUids := make([]string, 0, len(groupPowers))
	for i, _ := range groupPowers {
		groupUids = append(groupUids, groupPowers[i].GroupUid)
	}

	return groupUids, nil
}

func GetCvGroupPowerTeam(myContext *mycontext.MyContext, groupPowerId mysql.ID, myUserId mysql.ID) (CvGroupPowerTeam, error) {
	cvGroupPowerTeam := CvGroupPowerTeam{}
	adminUserIds, err := GetCvGroupPowerAdmins(groupPowerId)
	if err != nil {
		return CvGroupPowerTeam{}, err
	}
	if owers, err := user_cv.GetUserDetailByIds(adminUserIds, myUserId); err != nil {
		return CvGroupPowerTeam{}, err
	} else {
		cvGroupPowerTeam.Owers = owers
	}
	groupUid, err := GetGroupPower(groupPowerId)
	if err != nil {
		return CvGroupPowerTeam{}, err
	}
	assistantIds, err := group_m.FindRolesInGroup(mysql.Db, groupUid, group_e.GROUP_ADMIN)
	if err != nil {
		return CvGroupPowerTeam{}, err
	}
	if assistants, err := user_cv.GetUserDetailByIds(assistantIds, myUserId); err != nil {
		return CvGroupPowerTeam{}, err
	} else {
		cvGroupPowerTeam.Assistants = assistants
	}

	now := time.Now()
	beginTime, endTime, _ := group_m.GetSupportLevelTime(now)

	//所有人
	//userIds, err := GetCvGroupPowerAllUsers(groupPowerId)
	userIds, err := GetCvGroupPowerUsers(groupPowerId)
	if err != nil {
		return CvGroupPowerTeam{}, err
	}
	myContext.Log.Infof("GetCvGroupPowerTeam %d, this week users: %v", groupPowerId, userIds)

	// fixme: 2.18后,不需要这个了 thisWeek
	if thisWeek, err := GetCvGroupPowerSupportCount(userIds, beginTime.Format(utils.DATE_FORMAT), endTime.Format(utils.DATE_FORMAT)); err != nil {
		return CvGroupPowerTeam{}, err
	} else {
		cvGroupPowerTeam.ThisWeek = thisWeek
	}

	//lastWeek
	lastWeekUserIds, err := GetLastWeekGroupPowerUsers(groupPowerId)
	myContext.Log.Infof("GetCvGroupPowerTeam %d, last week users: %v", groupPowerId, lastWeekUserIds)

	beginTime, endTime, _ = group_m.GetSupportLevelTime(now.AddDate(0, 0, -group_e.SUPPORT_LEVEL_PERIOD_DAY))
	if lastWeek, err := GetCvGroupPowerSupportCount(lastWeekUserIds, beginTime.Format(utils.DATE_FORMAT), endTime.Format(utils.DATE_FORMAT)); err != nil {
		return CvGroupPowerTeam{}, err
	} else {
		cvGroupPowerTeam.LastWeek = lastWeek
	}
	return cvGroupPowerTeam, nil
}

//国家势力下,群组支持等级
type CvGroupPowerSupportCount struct {
	O uint `json:"o"`
	N uint `json:"n"`
	M uint `json:"m"`
	L uint `json:"l"`
	K uint `json:"k"`
	J uint `json:"j"`
	I uint `json:"i"`
	H uint `json:"h"`
	G uint `json:"g"`
	F uint `json:"f"`
	E uint `json:"e"`
	D uint `json:"d"`
	C uint `json:"c"`
	B uint `json:"b"`
	A uint `json:"a"`
}

type CvGroupSupportGrade struct {
	GroupUid string
	Grade    uint8
}

func GetCvGroupPowerSupportCount(groupOwnerId []mysql.ID, beginDate string, endDate string) (CvGroupPowerSupportCount, error) {
	groupSupportGrades := []CvGroupSupportGrade{}
	if err := mysql.Db.Table("group_support_result AS r").Select("r.group_uid, MAX(r.grade) AS grade").
		Joins("INNER JOIN group_info i ON i.im_group_id = r.group_uid").
		Where("i.`owner` IN ? AND r.period > ? AND r.period <= ?", groupOwnerId, beginDate, endDate).
		Group("r.group_uid").Find(&groupSupportGrades).Error; err != nil {
		return CvGroupPowerSupportCount{}, myerr.WrapErr(err)
	}

	cvGroupPowerSupportCount := CvGroupPowerSupportCount{}
	for _, r := range groupSupportGrades {
		switch r.Grade {
		case res_e.Agrade:
			cvGroupPowerSupportCount.A = cvGroupPowerSupportCount.A + 1
		case res_e.Bgrade:
			cvGroupPowerSupportCount.B = cvGroupPowerSupportCount.B + 1
		case res_e.Cgrade:
			cvGroupPowerSupportCount.C = cvGroupPowerSupportCount.C + 1
		case res_e.Dgrade:
			cvGroupPowerSupportCount.D = cvGroupPowerSupportCount.D + 1
		case res_e.Egrade:
			cvGroupPowerSupportCount.E = cvGroupPowerSupportCount.E + 1
		case res_e.Fgrade:
			cvGroupPowerSupportCount.F = cvGroupPowerSupportCount.F + 1
		case res_e.Ggrade:
			cvGroupPowerSupportCount.G = cvGroupPowerSupportCount.G + 1
		case res_e.Hgrade:
			cvGroupPowerSupportCount.H = cvGroupPowerSupportCount.H + 1
		case res_e.Igrade:
			cvGroupPowerSupportCount.I = cvGroupPowerSupportCount.I + 1
		case res_e.Jgrade:
			cvGroupPowerSupportCount.J = cvGroupPowerSupportCount.J + 1
		case res_e.Kgrade:
			cvGroupPowerSupportCount.K = cvGroupPowerSupportCount.K + 1
		case res_e.Lgrade:
			cvGroupPowerSupportCount.L = cvGroupPowerSupportCount.L + 1
		case res_e.Mgrade:
			cvGroupPowerSupportCount.M = cvGroupPowerSupportCount.M + 1
		case res_e.Ngrade:
			cvGroupPowerSupportCount.N = cvGroupPowerSupportCount.N + 1
		case res_e.Ograde:
			cvGroupPowerSupportCount.O = cvGroupPowerSupportCount.O + 1
		}
	}
	return cvGroupPowerSupportCount, nil
}

//获取国家势力的所有管理人
func GetCvGroupPowerAdmins(groupPowerId uint64) ([]mysql.ID, error) {
	groupPowers := []groupPower_m.GroupPowerUser{}
	if err := mysql.Db.Where(&groupPower_m.GroupPowerUser{
		GroupPowerId: groupPowerId,
		Role:         groupPower_e.GroupPowerUserRoleMgr,
	}).Find(&groupPowers).Error; err != nil {
		return nil, myerr.WrapErr(err)
	}
	//
	usreIds := make([]mysql.ID, 0, len(groupPowers))
	for i, _ := range groupPowers {
		usreIds = append(usreIds, groupPowers[i].UserId)
	}
	return usreIds, nil
}

//获取国家势力的所有用户(角色,用户)
func GetCvGroupPowerAllUsers(groupPowerId uint64) ([]mysql.ID, error) {
	groupPowers := []groupPower_m.GroupPowerUser{}
	if err := mysql.Db.Where(&groupPower_m.GroupPowerUser{
		GroupPowerId: groupPowerId,
	}).Find(&groupPowers).Error; err != nil {
		return nil, myerr.WrapErr(err)
	}
	//
	usreIds := make([]mysql.ID, 0, len(groupPowers))
	for i, _ := range groupPowers {
		usreIds = append(usreIds, groupPowers[i].UserId)
	}
	return usreIds, nil
}

//获取国家势力的所有用户(角色,用户)
func GetCvGroupPowerUsers(groupPowerId uint64) ([]mysql.ID, error) {
	groupPowers := []groupPower_m.GroupPowerUser{}
	if err := mysql.Db.Where(&groupPower_m.GroupPowerUser{
		GroupPowerId: groupPowerId,
		Role:         groupPower_e.GroupPowerUserRoleUser,
	}).Find(&groupPowers).Error; err != nil {
		return nil, myerr.WrapErr(err)
	}
	//
	usreIds := make([]mysql.ID, 0, len(groupPowers))
	for i, _ := range groupPowers {
		usreIds = append(usreIds, groupPowers[i].UserId)
	}
	return usreIds, nil
}

// return userId->powerId userId->powerName userId->powerNameplate
func BatchGetGroupPower(db *gorm.DB, userIds []uint64) (map[uint64]uint64, map[uint64]string, map[uint64]string, map[uint64]groupPower_e.GroupPowerGrade, error) {
	if len(userIds) <= 0 {
		return nil, nil, nil, nil, nil
	}
	groupPowers, err := groupPower_m.GetGroupPowerMap(db, userIds)
	if err != nil {
		return nil, nil, nil, nil, err
	}

	gpIds := make([]uint64, 0)
	for _, i := range groupPowers {
		gpIds = append(gpIds, i)
	}
	powerNames, powerNameplates, err := groupPower_m.GetGroupPowerNames(db, gpIds)
	if err != nil {
		return nil, nil, nil, nil, err
	}
	groupPowerGrade, err := groupPower_m.MGetGroupPowerGrade(domain.CreateModelNil(), gpIds)
	if err != nil {
		return nil, nil, nil, nil, err
	}
	groupPowerNames := make(map[mysql.ID]string, 0)
	groupPowerNameplates := make(map[mysql.ID]string, 0)
	groupPowerGrades := make(map[mysql.ID]groupPower_e.GroupPowerGrade, 0)
	for i, g := range groupPowers {
		groupPowerNames[i] = powerNames[g]
		groupPowerNameplates[i] = powerNameplates[g]
		groupPowerGrades[i] = groupPowerGrade[g].Grade
	}
	return groupPowers, groupPowerNames, groupPowerNameplates, groupPowerGrades, nil
}

//获取国家势力的所有用户数量
func GetCvGroupPowerUserN(groupPowerId uint64) (int64, error) {
	var count int64
	if err := mysql.Db.Where(&groupPower_m.GroupPowerUser{
		GroupPowerId: groupPowerId,
	}).Count(&count).Error; err != nil {
		return 0, myerr.WrapErr(err)
	}
	return count, nil
}

//获取国家势力的所有用户数量
func GetCvGroupPowerUserMapN(groupPowerIds []uint64) (map[uint64]uint64, error) {

	type GroupPowerUser struct {
		GroupPowerId uint64
		N            uint64
	}
	groupPowerUsers := []GroupPowerUser{}
	if err := mysql.Db.Raw("SELECT u.group_power_id, COUNT(1) as n from group_power_user u where u.group_power_id in (?) GROUP BY u.group_power_id", groupPowerIds).Scan(&groupPowerUsers).Error; err != nil {
		return nil, myerr.WrapErr(err)
	}

	userN := map[uint64]uint64{}

	for _, r := range groupPowerUsers {
		userN[r.GroupPowerId] = r.N
	}

	return userN, nil
}

// 查询上周国家势力的所有用户(角色:用户),当前名单+时间倒序还原
func GetLastWeekGroupPowerUsers(groupPowerId uint64) ([]mysql.ID, error) {
	groupPowers := []groupPower_m.GroupPowerUser{}
	if err := mysql.Db.Where(&groupPower_m.GroupPowerUser{
		GroupPowerId: groupPowerId,
		Role:         groupPower_e.GroupPowerUserRoleUser,
	}).Find(&groupPowers).Error; err != nil {
		return nil, myerr.WrapErr(err)
	}
	//
	users := make(map[mysql.ID]time.Time, 0)
	for _, i := range groupPowers {
		users[i.UserId] = i.CreatedTime
	}
	beginTime := utils.GetZeroTime(utils.GetMonday(time.Now()))
	records, err := groupPower_m.GetGroupPowerUserLog(mysql.Db, groupPowerId, beginTime)
	if err != nil {
		return nil, err
	}
	userLogs := make(map[mysql.ID]string, 0)
	for _, i := range records {
		mylogrus.MyLog.Debugf("GetLastWeekGroupPowerUsers %d, user %d, %s, opType = %d", groupPowerId, i.UserId, i.CreatedTime.String(), i.OperateType)
		if i.OperateType == groupPower_e.GroupPowerUserLogTypeUserJoin || i.OperateType == groupPower_e.GroupPowerUserLogTypeOwerJoin {
			delete(users, i.UserId)
			userLogs[i.UserId] += "-" + i.CreatedTime.String() + " "
		} else if i.OperateType == groupPower_e.GroupPowerUserLogTypeUserLeave || i.OperateType == groupPower_e.GroupPowerUserLogTypeMgrLeave {
			users[i.UserId] = i.CreatedTime
			userLogs[i.UserId] += "+" + i.CreatedTime.String() + " "
		}
	}
	mylogrus.MyLog.Infof("GetLastWeekGroupPowerUsers %d : %v", groupPowerId, userLogs)

	userIds := make([]mysql.ID, 0)
	for u, _ := range users {
		userIds = append(userIds, u)
	}
	return userIds, nil
}

//分页获取国家势力的用户
func GetCvGroupPowerUser(groupPowerId uint64, pageSize int, pageIndex int) ([]mysql.ID, error) {
	groupPowers := []groupPower_m.GroupPowerUser{}
	if err := mysql.Db.Where(&groupPower_m.GroupPowerUser{
		GroupPowerId: groupPowerId,
		Role:         groupPower_e.GroupPowerUserRoleUser,
	}).Limit(pageSize).Offset((pageIndex - 1) * pageSize).Find(&groupPowers).Error; err != nil {
		return nil, myerr.WrapErr(err)
	}
	//
	usreIds := make([]mysql.ID, 0, len(groupPowers))
	for i, _ := range groupPowers {
		usreIds = append(usreIds, groupPowers[i].UserId)
	}
	return usreIds, nil
}

type CvGroupPowerDiamondTotal struct {
	//势力ID
	GroupPowerId mysql.ID `json:"groupPowerId"`
	//名字
	Name string `json:"name"`
	//头像
	FaceUrl string `json:"faceUrl"`
	//钻石数量
	DiamondNum uint `json:"diamondNum"`
	//用户数量
	UserN uint64 `json:"userN"`
}

func GetCvGroupPowerDiamondTotalList(weekBeginTime time.Time, endTime time.Time, pageSize int, pageIndex int) ([]CvGroupPowerDiamondTotal, error) {
	/*	cvGroupPowerDiamondTotals := []CvGroupPowerDiamondTotal{}
		if err := mysql.Db.Raw("SELECT t1.*, t2.diamond_num from (SELECT p.id as group_power_id, i.`name`, i.face_url from group_power p, group_info i where p.status = ? and p.group_uid = i.im_group_id) t1 LEFT JOIN (SELECT l.group_power_id, SUM(l.diamond_num) as diamond_num from group_power_diamond_log l where l.created_time >= ? AND l.created_time < ? GROUP BY l.group_power_id) t2 on t1.group_power_id = t2.group_power_id order by t2.diamond_num DESC, t1.group_power_id desc LIMIT ?, ?", groupPower_m2.GroupPowerUserHas, beginTime, endTime, (pageIndex-1)*pageSize, pageSize).Scan(&cvGroupPowerDiamondTotals).Error; err != nil {
			return nil, myerr.WrapErr(err)
		}
		return cvGroupPowerDiamondTotals, nil*/

	//用缓存
	rows, err := redisCli.GetRedis().ZRevRangeWithScores(context.Background(), redis_key.GetGroupPowerDiamondLogWeek(weekBeginTime.Format(utils.COMPACT_DATE_FORMAT)), 0, -1).Result()
	if err != nil {
		return nil, myerr.WrapErr(err)
	}
	groupPowerIds := make([]uint64, 0, len(rows))
	groupPowerDiamondMap := map[uint64]uint{}
	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)
		groupPowerDiamondMap[groupPowerId] = uint(rows[i].Score)
	}
	//搜集所有的群组
	cvGroupPowerDiamondTotals := []CvGroupPowerDiamondTotal{}
	if err := mysql.Db.Raw("SELECT p.id as group_power_id, i.`name`, i.face_url from group_power p, group_info i where p.status = ? and p.group_uid = i.im_group_id AND p.id in (?)", groupPower_e.GroupPowerUserHas, groupPowerIds).Scan(&cvGroupPowerDiamondTotals).Error; err != nil {
		return nil, myerr.WrapErr(err)
	}
	//将分数放进去
	for i, r := range cvGroupPowerDiamondTotals {
		cvGroupPowerDiamondTotals[i].DiamondNum = groupPowerDiamondMap[r.GroupPowerId]
	}
	//排序
	//从高到低排序
	sort.Slice(cvGroupPowerDiamondTotals, func(i, j int) bool {
		return cvGroupPowerDiamondTotals[i].DiamondNum > cvGroupPowerDiamondTotals[j].DiamondNum
	})

	//总长度
	l := len(cvGroupPowerDiamondTotals)
	if (pageIndex-1)*pageSize >= l {
		return []CvGroupPowerDiamondTotal{}, nil
	} else if pageIndex*pageSize > l {
		//分页切片
		newGroupPowerDiamondTotal := cvGroupPowerDiamondTotals[(pageIndex-1)*pageSize : l]
		return newGroupPowerDiamondTotal, nil
	} else {
		//分页切片
		newGroupPowerDiamondTotal := cvGroupPowerDiamondTotals[(pageIndex-1)*pageSize : pageIndex*pageSize]
		return newGroupPowerDiamondTotal, nil
	}

}

type powerInfoRec struct {
	GroupPowerId uint64
	Name         string
	FaceUrl      string
}

func getPowerGroupMap(db *gorm.DB) (map[uint64]powerInfoRec, error) {
	rows := make([]powerInfoRec, 0)
	err := db.Model(&groupPower_m.GroupPower{}).Select("p.id AS group_power_id, i.name, i.face_url").
		Joins("AS p INNER JOIN group_info AS i ON p.group_uid = i.im_group_id").
		Where("p.status = ?", 1). // STATUS_IN_USE = 1;STATUS_UNUSED = 2
		Find(&rows).Error
	if err != nil {
		return nil, err
	}

	powerInfo := make(map[uint64]powerInfoRec, 0)
	for _, i := range rows {
		powerInfo[i.GroupPowerId] = i
	}
	return powerInfo, nil
}

type GroupPowerDiamondLog struct {
	GroupPowerId uint64
	DiamondNum   uint
}

// 按时间范围计算势力流水
/*func getPowerDiamondLogByRange(db *gorm.DB, beginTime, endTime time.Time) ([]GroupPowerDiamondLog, error) {
	rows := make([]GroupPowerDiamondLog, 0)
	err := db.Model(&GroupPowerDiamondLog{}).Select("group_power_id, SUM(diamond_num) as diamond_num").
		Where("created_time BETWEEN ? AND ?", beginTime, endTime).
		Group("group_power_id").Order("diamond_num DESC").Find(&rows).Error
	if err != nil {
		return nil, err
	}
	return rows, nil
}*/

func getPowerDiamondLogByRange(weekBeginDate time.Time) ([]GroupPowerDiamondLog, error) {
	rows, err := redisCli.GetRedis().ZRevRangeWithScores(context.Background(), redis_key.GetGroupPowerDiamondLogWeek(weekBeginDate.Format(utils.COMPACT_DATE_FORMAT)), 0, 3).Result()
	if err != nil {
		return nil, myerr.WrapErr(err)
	}
	logs := []GroupPowerDiamondLog{}
	for i, _ := range rows {
		groupPowerId, err := strconv.ParseUint(rows[i].Member.(string), 10, 64)
		if err != nil {
			return nil, myerr.WrapErr(err)
		}
		logs = append(logs, GroupPowerDiamondLog{
			GroupPowerId: groupPowerId,
			DiamondNum:   uint(rows[i].Score),
		})
	}
	return logs, err
}

type GroupPowerTop struct {
	ThisWeek []CvGroupPowerDiamondTotal `json:"thisWeek"`
	LastWeek []CvGroupPowerDiamondTotal `json:"lastWeek"`
}

func buildGroupPowerTop3(powerInfo map[uint64]powerInfoRec, diamonds []GroupPowerDiamondLog) []CvGroupPowerDiamondTotal {
	// Disgusting: 按groupPowerId从大到小排序,以防diamond>0的势力不足3个的情况
	gpIds := make([]uint64, 0)
	for _, i := range powerInfo {
		gpIds = append(gpIds, i.GroupPowerId)
	}
	sort.Slice(gpIds, func(i, j int) bool {
		return gpIds[i] > gpIds[j]
	})

	used := make(map[uint64]struct{}, 0)
	result := make([]CvGroupPowerDiamondTotal, 0)
	for _, i := range diamonds {
		if e, ok := powerInfo[i.GroupPowerId]; ok {
			result = append(result, CvGroupPowerDiamondTotal{
				GroupPowerId: i.GroupPowerId,
				Name:         e.Name,
				FaceUrl:      e.FaceUrl,
				DiamondNum:   i.DiamondNum,
			})
			used[i.GroupPowerId] = struct{}{}
			if len(result) >= 3 {
				break
			}
		}
	}
	if len(result) < 3 {
		for _, i := range gpIds {
			if _, exists := used[i]; !exists {
				if gi, ok := powerInfo[i]; ok {
					result = append(result, CvGroupPowerDiamondTotal{
						GroupPowerId: i,
						Name:         gi.Name,
						FaceUrl:      gi.FaceUrl,
						DiamondNum:   0,
					})
					if len(result) >= 3 {
						break
					}
				}
			}
		}
	}
	return result
}

func GetGroupPowerTop3(model *domain.Model) (GroupPowerTop, error) {
	result := GroupPowerTop{}
	powerInfo, err := getPowerGroupMap(model.Db)
	if err != nil {
		return result, err
	}
	model.Log.Infof("GetGroupPowerTop3, powerInfo: %v", powerInfo)

	beginDate, endDate, err := GetWeekByNow()
	if err != nil {
		return result, err
	}

	//diamonds, err := getPowerDiamondLogByRange(model.Db, beginDate, endDate)
	diamonds, err := getPowerDiamondLogByRange(beginDate)
	if err != nil {
		return result, err
	}

	result.ThisWeek = buildGroupPowerTop3(powerInfo, diamonds)

	endDate = beginDate
	beginDate = endDate.AddDate(0, 0, -7)

	diamonds, err = getPowerDiamond(model, beginDate, endDate)
	if err != nil {
		return result, err
	}
	result.LastWeek = buildGroupPowerTop3(powerInfo, diamonds)

	return result, nil
}

//当前日期的自然周
func GetWeekByNow() (time.Time, time.Time, error) {
	now := time.Now()
	nowTime, err := time.ParseInLocation(utils.DATE_FORMAT, now.Format(utils.DATE_FORMAT), time.Local)
	if err != nil {
		return time.Time{}, time.Time{}, myerr.WrapErr(err)
	}
	beginDate := utils.GetMonday(nowTime)
	return beginDate, now, nil
}

func getPowerDiamond(model *domain.Model, beginTime, endTime time.Time) ([]GroupPowerDiamondLog, error) {
	period := beginTime.Format(utils.DATE_FORMAT)
	values, err := GetAllPowerDiamond(period)

	if err != nil {
		return nil, err
	}
	model.Log.Infof("GetPowerDiamond, GET %s: %v", period, values)

	diamonds := make(map[uint64]uint, 0)
	result := make([]GroupPowerDiamondLog, 0)
	if len(values) > 0 {
		powerIds := make([]uint64, 0)
		for k, v := range values {
			d, err := strconv.ParseUint(v, 10, 32)
			if err == nil {
				p, err := strconv.ParseUint(k, 10, 64)
				if err == nil {
					diamonds[p] = uint(d)
					powerIds = append(powerIds, p)
				}
			}
		}
		// 排序
		sort.Slice(powerIds, func(i, j int) bool {
			return diamonds[powerIds[i]] > diamonds[powerIds[j]]
		})
		for _, i := range powerIds {
			result = append(result, GroupPowerDiamondLog{
				GroupPowerId: i,
				DiamondNum:   diamonds[i],
			})
		}
	} else {
		//d, err := getPowerDiamondLogByRange(model.Db, beginTime, endTime)
		d, err := getPowerDiamondLogByRange(beginTime)
		for _, i := range d {
			diamonds[i.GroupPowerId] = i.DiamondNum
			result = append(result, GroupPowerDiamondLog{
				GroupPowerId: i.GroupPowerId,
				DiamondNum:   i.DiamondNum,
			})
		}

		ret, err := SaveAllPowerDiamond(period, diamonds)
		model.Log.Infof("GetPowerDiamond SAVE ret = %d, err: %v", ret, err)
	}
	model.Log.Infof("GetPowerDiamond for %s, %v", period, result)
	return result, nil
}

func SaveAllPowerDiamond(period string, diamonds map[uint64]uint) (int64, error) {
	values := make(map[string]interface{}, 0)
	for p, d := range diamonds {
		if d > 0 {
			values[strconv.FormatUint(p, 10)] = d
		}
	}
	if len(values) <= 0 {
		return 0, nil
	}
	key := redis_key.GetPrefixGroupPowerDiamond(period)
	ret, err := redisCli.GetRedis().HSet(context.Background(), key, values).Result()

	if err == nil {
		// 设置一个TTL保险一些 TODO: 可以优化,保证数据总是有的
		redisCli.GetRedis().Expire(context.Background(), key, time.Hour)
	}
	return ret, err
}

func GetAllPowerDiamond(period string) (map[string]string, error) {
	key := redis_key.GetPrefixGroupPowerDiamond(period)
	return redisCli.GetRedis().HGetAll(context.Background(), key).Result()
}

type GroupPowerInfo struct {
	Info    *GroupPower       `json:"info"`
	Members []*GroupPowerUser `json:"members"`
	Stars   []*GroupPowerStar `json:"stars,omitempty"`
}

type GroupPower struct {
	Id          uint64                       `json:"id"`
	Name        string                       `json:"name"`
	Nameplate   string                       `json:"nameplate"`          // 铭牌
	Declaration string                       `json:"declaration"`        // 宣言
	Icon        string                       `json:"icon"`               // 头像
	Grade       groupPower_e.GroupPowerGrade `json:"grade" gorm:"-"`     // 等级
	Exp         mysql.Num                    `json:"exp" gorm:"-"`       // 当前经验值
	NextExp     mysql.Num                    `json:"nextExp" gorm:"-"`   // 升到下一级需要的经验值
	GradeName   mysql.Str                    `json:"gradeName"`          // 等级称号
	GradeMedal  mysql.Str                    `json:"gradeMedal"`         // 等级勋章图片
	MemberNum   mysql.Num                    `json:"memberNum" gorm:"-"` // 当前人数
	MemberMax   mysql.Num                    `json:"memberMax" gorm:"-"` // 最大人数
	Role        int                          `json:"role" gorm:"-"`      // 我在此家族中的角色 0.路人 1.成员 2.家族长 3.管理员
	IsApply     bool                         `json:"isApply" gorm:"-"`   // 最大人数
	MonthRank   int                          `json:"monthRank" gorm:"-"` // 家族月排名
}

type GroupPowerUser struct {
	User *user_m.UserTiny                `json:"user"`
	Role groupPower_e.GroupPowerUserRole `json:"role"`
}

type GroupPowerStar struct {
	User        user_cv.CvUserTiny              `json:"user"`
	RankingType groupPower_e.GroupPowerRankType `json:"rankingType"`
}

type FamilyMemberDetail struct {
	User user_cv.CvUserExtend            `json:"user"`
	Role groupPower_e.GroupPowerUserRole `json:"role"`
}

type FamilyApplyList struct {
	User    *user_m.UserTiny `json:"user"`
	Time    int64            `json:"time"`
	Status  int8             `json:"status"`  // 0未操作,1已接受,2.已拒绝
	MgrName string           `json:"mgrName"` // 管理员名称
}

type FamilyQuitList struct {
	User     *user_m.UserTiny `json:"user"`
	Time     int64            `json:"time"`
	QuitType int8             `json:"quitType"` // 1.主动退出 2.被踢出
	MgrName  string           `json:"mgrName"`  // 管理员名称
}