package group_r

import (
	"fmt"
	"git.hilo.cn/hilo-common/domain"
	"git.hilo.cn/hilo-common/mycontext"
	"git.hilo.cn/hilo-common/resource/mysql"
	"github.com/gin-gonic/gin"
	"hilo-group/_const/enum/group_e"
	"hilo-group/_const/enum/msg_e"
	"hilo-group/cv/group_cv"
	"hilo-group/cv/user_cv"
	"hilo-group/domain/cache/group_c"
	"hilo-group/domain/model/group_m"
	"hilo-group/domain/model/res_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"
	"strings"
	"time"
)

// @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"
// @Success 200 {object} bool
// @Router /v1/imGroup/support/page/{groupId} [get]
func GetSupportPage(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)

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

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

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

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

	resp.ResponseOk(c, pa == userId)
	return myContext, nil
}

// @Tags 群组
// @Summary 支持页详情
// @Accept application/x-www-form-urlencoded
// @Param token header string true "token"
// @Param nonce header string true "随机数字"
// @Param groupId query string false "群ID"
// @Success 200 {object} group_cv.SupportPageDetail
// @Router /v1/imGroup/support/detail [get]
func GetSupportDetail(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)

	groupId := c.Query("groupId")
	txGroupId := groupId
	if len(groupId) <= 0 {
		// groupId 没填的话,用user自己的群
		groups, err := group_m.FindGroupByOwner(model, userId)
		if err != nil {
			return myContext, err
		}
		if len(groups) > 0 {
			groupId = groups[0].ImGroupId
			txGroupId = groups[0].TxGroupId
		} else {
			return myContext, bizerr.GroupNotFound
		}
	} else {
		groupId, err = group_m.ToImGroupId(model, groupId)
		if err != nil {
			return myContext, err
		}
	}

	pa, err := group_m.GetProfitAllocator(model, groupId)
	if err != nil {
		return myContext, err
	}
	if userId != pa {
		return myContext, bizerr.NoPrivileges
	}

	result := group_cv.SupportPageDetail{GroupId: txGroupId}

	now := time.Now()
	_, endTime, period := group_m.GetSupportLevelTime(now)
	result.RemainSecond = endTime.Unix() - now.Unix()

	//g := gift_m.GiftOperate{SceneType: gift_e.GroupSceneType, SceneUid: groupId, Model: model}
	//result.CurrentCount, result.CurrentConsume, err = g.GetConsumeByRange(beginTime, endTime)
	//if err != nil {
	//	return myContext, err
	//}
	result.CurrentConsume, result.CurrentCount, err = group_s.GetGroupConsumeCount(model, groupId, period)
	if err != nil {
		model.Log.Errorf("GetSupportDetail groupId:%s, err:%v", groupId, err)
		return myContext, err
	}

	_, _, periodLast := group_m.GetSupportLevelTime(now.AddDate(0, 0, -group_e.SUPPORT_LEVEL_PERIOD_DAY))
	//result.LastCount, result.LastConsume, err = g.GetConsumeByRange(beginTimeLast, endTimeLast)
	//if err != nil {
	//	return myContext, err
	//}
	result.LastConsume, result.LastCount, err = group_s.GetGroupConsumeCount(model, groupId, periodLast)
	if err != nil {
		model.Log.Errorf("GetSupportDetail groupId:%s, err:%v", groupId, err)
		return myContext, err
	}

	rec, err := res_m.GetResGroupSupportBy(model, result.LastCount, result.LastConsume)
	if err != nil {
		return myContext, err
	}
	if rec != nil {
		result.SupportLevel = string(64 + rec.Grade)
		result.SupporterLimit = rec.MgrNum
	}

	rec, err = res_m.GetResGroupSupportBy(model, result.CurrentCount, result.CurrentConsume)
	if err != nil {
		return myContext, err
	}
	if rec != nil {
		result.CurrentSupportLevel = string(64 + rec.Grade)
	}

	userBase, err := user_cv.GetUserBase(pa, userId)
	if err != nil {
		return myContext, err
	}
	if userBase != nil {
		result.ProfitAllocator = *userBase
	}

	// 判断这个周期这个群的奖金是否已经发过
	_, _, period = group_m.GetLastSupportPeriod(now)
	gsaa := group_m.GroupSupportAwardAdmin{Period: period, GroupUid: groupId}
	rows, err := gsaa.Get(model.Db)
	if err != nil {
		return myContext, err
	}

	if len(rows) > 0 {
		result.IsDispatched = true
	}

	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 false "群ID"
// @Param externalId query string true "用户的externalId"
// @Success 200
// @Router /v1/imGroup/support/award/{groupId} [get]
func TryAddSupporter(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)

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

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

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

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

	pa, err := group_m.GetProfitAllocator(model, groupId)
	if err != nil {
		return myContext, err
	}
	if myUserId != pa {
		return myContext, bizerr.NoPrivileges
	}

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

	role, err := group_m.GetRoleInGroup(model, userId, groupId)
	if err != nil {
		return myContext, err
	}

	if role != group_e.GROUP_MANAGER && role != group_e.GROUP_ADMIN {
		return myContext, bizerr.NotManagerOrAdmin
	}
	// 判断财富等级必须要大于等于3级
	wealthGrade, _, err := user_m.GetWealthGrade(model, userId)
	if err != nil {
		return myContext, err
	}
	if wealthGrade < 3 {
		if msg, _ := res_m.GetResMultiTextBy(model.DB(), 187, lang); msg != nil { // 187:res_multi_text 财富等级为到8级
			return myContext, myerr.NewBusinessCodeNoCheck(bizerr.GroupSupportWealthLevel3.GetCode(), msg.Content, myerr.BusinessData{})
		}
		return myContext, bizerr.GroupSupportWealthLevel3
	}
	// 判断用户是否作为助手领取过奖励
	sameImeiUsers, err := user_m.GetSameImeiMap(model, userId)
	if err != nil {
		return myContext, err
	}
	_, _, period := group_m.GetLastSupportPeriod(time.Now())
	gsaa := group_m.GroupSupportAwardMgr{Period: period}
	awards, err := gsaa.Get(model.Db)
	if err != nil {
		return myContext, err
	}

	for _, i := range awards {
		if _, ok := sameImeiUsers[i.UserId]; ok {
			if i.UserId == userId {
				return myContext, bizerr.UserAlreadyAwarded
			} else {
				return myContext, bizerr.ImeiAlreadyAwarded
			}
		}
	}

	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 groupId path string true "群ID"
// @Param supporters formData string false "群支持者的externalId,用逗号分隔"
// @Success 200 {object} group_cv.AwardResult
// @Router /v1/imGroup/support/award/{groupId} [post]
func TakeSupportAward(c *gin.Context) (*mycontext.MyContext, error) {
	myContext := mycontext.CreateMyContext(c.Keys)

	//userId, err := getUserId(c)
	userId, lang, err := req.GetUserIdLang(c, myContext)
	if err != nil {
		return myContext, err
	}

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

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

	pa, err := group_m.GetProfitAllocator(model, groupId)
	if err != nil {
		return myContext, err
	}
	if userId != pa {
		return myContext, bizerr.NoPrivileges
	}

	s := c.PostForm("supporters")
	extIds := make([]string, 0)
	extId2Uid := make(map[string]uint64, 0)
	uid2extId := make(map[uint64]string, 0)
	codeMap := make(map[mysql.ID]string, 0)
	if len(s) > 0 {
		extIds = strings.Split(s, ",")
		users, err := user_m.BatchGetUserByExtIds(model, extIds)
		if err != nil {
			return myContext, err
		}
		for _, i := range users {
			extId2Uid[i.ExternalId] = i.ID
			uid2extId[i.ID] = i.ExternalId
			codeMap[i.ID] = i.Code
		}
	}

	userIds := make([]uint64, 0)
	for _, i := range extIds {
		if _, ok := extId2Uid[i]; ok {
			userIds = append(userIds, extId2Uid[i])
		} else {
			// FIXME: report error
		}
	}

	//  检查是否已经发放了
	_, _, period := group_m.GetLastSupportPeriod(time.Now())
	gsa := group_m.GroupSupportAwardAdmin{Period: period, GroupUid: groupId}
	rows, err := gsa.Get(model.Db)
	if err != nil {
		return myContext, err
	}

	if len(rows) > 0 {
		return myContext, bizerr.GroupAlreadyAwarded
	}

	model = domain.CreateModelContext(myContext)

	resSupport, supportLevel, err := group_s.NewGroupService(myContext).GetSupportLevelByRedis(groupId)
	if err != nil {
		return myContext, err
	}

	if resSupport.ID <= 0 {
		return myContext, bizerr.NotQualified
	}

	userIds, outUserIds, err := group_s.NewGroupService(myContext).GroupSupportList(groupId, userIds, supportLevel)
	model.Log.Infof("TakeSupportAward: %v, %v", userIds, outUserIds)
	if err != nil {
		model.Log.Errorf("TakeSupportAward groupId:%v, userId:%v err:%v", groupId, userId, err)
		return myContext, err
	}

	// 检查userIds的ip限制
	userIp, err := user_m.GetUserIpMap(model.Db, userIds)
	if err != nil {
		return myContext, err
	}
	var sameIp = make(map[string]int)
	var ipUser = make(map[string]mysql.ID)
	for uid, ip := range userIp {
		sameIp[ip]++
		ipUser[ip] = uid
		if len(ip) > 0 {
			// IP已经领取过6次奖励,点击领奖校验则提示“ID:%s为重复账户
			var msg = fmt.Sprintf(bizerr.GroupSupportIpLimit.GetMsg(), codeMap[uid])
			if resMul, _ := res_m.GetResMultiTextBy(model.Db, msg_e.MSG_ID_REPEAT_ACCOUNT, lang); resMul != nil {
				msg = fmt.Sprintf(resMul.Content, codeMap[uid])
			}
			if times, err := group_c.GetGroupSupportAwardIpTimes(model, ip); err != nil || times >= 6 {
				myContext.Log.Infof("ip more 6:%v-%v-%v", times, ip, uid)
				return myContext, myerr.NewBusinessCodeNoCheck(bizerr.GroupSupportIpLimit.GetCode(), msg, myerr.BusinessData{})
			}
		}
	}
	for ip, cnt := range sameIp {
		if cnt >= 6 {
			var msg = fmt.Sprintf(bizerr.GroupSupportIpLimit.GetMsg(), codeMap[ipUser[ip]])
			if resMul, _ := res_m.GetResMultiTextBy(model.Db, msg_e.MSG_ID_REPEAT_ACCOUNT, lang); resMul != nil {
				msg = fmt.Sprintf(resMul.Content, codeMap[ipUser[ip]])
			}
			myContext.Log.Infof("ip more 6 two:%v-%v-%v", cnt, ip, ipUser[ip])
			return myContext, myerr.NewBusinessCodeNoCheck(bizerr.GroupSupportIpLimit.GetCode(), msg, myerr.BusinessData{})
		}
	}

	groupInfo, err := group_m.GetGroupInfo(model, groupId)
	if groupInfo == nil || groupInfo.Id <= 0 {
		return myContext, bizerr.GroupNotFound
	}
	// 真正地放奖励
	err = group_s.NewGroupService(myContext).GroupSupportAward(groupId, pa, userIds, resSupport, period, groupInfo)
	if err != nil {
		return myContext, err
	}

	// 记录ip获奖
	for _, userId := range userIds {
		if ip, ok := userIp[userId]; ok && len(ip) > 0 {
			_, _ = group_c.IncrGroupSupportAwardIp(model, ip)
		}
	}

	// 保存记录
	if err = group_s.NewGroupService(myContext).RenewGroupSupporter(groupId, userIds); err != nil {
		model.Log.Warnf("TakeSupportAward, failed in saving group %s supporters", groupId)
	}

	result := group_cv.AwardResult{}
	for _, i := range userIds {
		result.Success = append(result.Success, uid2extId[i])
	}
	for _, i := range outUserIds {
		result.Failed = append(result.Failed, uid2extId[i])
	}

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