package service

// Cdk 订单
var Cdk = new(sCdk)

type sCdk struct{}

/*func (s *sCdk) List(ctx *gin.Context, req forms.CdkListReq) serializer.Response {

	type RedeemCode struct {
		model.RedeemCode
		Used int64 `json:"used"`
	}
	type RedeemReceived struct {
		Cid   int64 `json:"cid"`
		Total int64 `json:"total"`
	}

	var (
		r              = query.Use(config.DB).RedeemReceived
		count    int64 = 0
		offset   int64 = 0
		models   forms.UserAccountListRes
		lists    []*RedeemCode
		received []*RedeemReceived
	)
	models.Page = req.Page
	models.PerPage = req.PerPage

	redeemCodeQuery := config.DB.Table("redeem_code AS subquery").
		Select("subquery.id, subquery.sn, subquery.name, subquery.cdk, subquery.server_ids, subquery.type_id, subquery.openid, subquery.times, subquery.expired_at, subquery.award, subquery.date, subquery.operator, subquery.created_at, subquery.status").
		Joins("JOIN (SELECT sn, MIN(id) AS min_id FROM redeem_code GROUP BY sn) AS subquery_min ON subquery.sn = subquery_min.sn AND subquery.id = subquery_min.min_id").
		Order("subquery.created_at desc")
	if len(req.CreatedAt) == 2 {
		redeemCodeQuery.Where("subquery.created_at BETWEEN ? AND ?", req.CreatedAt[0], req.CreatedAt[1])
	}

	if req.Cdk != "" {
		redeemCodeQuery.Where("subquery.cdk = ?", req.Cdk)
	}
	if req.Sn != "" {
		redeemCodeQuery.Where("subquery.sn = ?", req.Sn)
	}
	if req.Name != "" {
		redeemCodeQuery.Where("subquery.name = ?", req.Name)
	}

	err := redeemCodeQuery.Count(&count).Error
	if err != nil {
		return serializer.Err(consts.CodeParamErr, "查询出错 count", err)
	}

	if count == 0 {
		return serializer.Suc(models)
	}

	req.Page, req.PerPage, offset = forms.CalculatePage(req.Page, req.PerPage)

	err = redeemCodeQuery.Limit(int(req.PerPage)).Offset(int(offset)).Find(&lists).Error
	if err != nil {
		return serializer.Err(consts.CodeParamErr, "查询出错 count", err)
	}

	// code id slice
	codeIds := make([]int64, len(lists))
	for i, v := range lists {
		codeIds[i] = v.ID
	}

	err = r.WithContext(ctx).Select(r.Cid, r.ID.Count().As("total")).Where(r.Cid.In(codeIds...)).Group(r.Cid).Scan(&received)
	if err != nil {
		return serializer.Err(consts.CodeParamErr, "查询出错 lists", err)
	}
	if len(received) != 0 {
		receivedMap := make(map[int64]int64, len(received))
		for _, item := range received {
			receivedMap[item.Cid] = item.Total
		}
		for _, v := range lists {
			v.Used = receivedMap[v.ID]
		}
	}
	models.List = lists
	models.PageCount = (count + req.PerPage - 1) / req.PerPage
	return serializer.Suc(models)
}
func (s *sCdk) Del(ctx *gin.Context, req forms.CdkDelReq) serializer.Response {
	var (
		q   = query.Use(config.DB).RedeemCode
		err error
	)

	// 编辑
	if req.ID <= 0 {
		return serializer.ParamErr("ID不能空，删除失败！", nil)
	}

	_, err = query.Use(config.DB).RedeemCode.WithContext(ctx).Where(q.ID.Eq(req.ID)).Delete()
	if err != nil {
		return serializer.DBErr(err.Error(), err)
	}

	return serializer.Suc(nil)
}

func (s *sCdk) Add(ctx *gin.Context, req forms.CdkAddReq) serializer.Response {
	var (
		q      = query.Use(config.DB).RedeemCode
		m      = q.WithContext(ctx).Where(q.Cdk.Eq(req.Cdk))
		models model.RedeemCode
		err    error
		codes  []*model.RedeemCode
		sn     = time.Now().Format("2006010215") + "T" + cast.ToString(req.TypeId) + "R" + character.RandStringRunes(5)
	)

	serverIds, _ := json.Marshal(req.ServerIds)

	award, err := json.Marshal(req.CdkAward)
	if err != nil {
		return serializer.ParamErr("解析奖励材料失败", err)
	}

	if req.Cdk != "" {
		// 生成自定义兑换码
		if err := m.Scan(&models); err != nil {
			return serializer.Err(
				consts.CodeParamErr,
				"查询出错",
				err,
			)
		}

		if models.ID > 0 {
			return serializer.Err(
				consts.CodeParamErr,
				"兑换已存在",
				err,
			)
		}

		codes = append(codes, &model.RedeemCode{
			ServerIds: string(serverIds),
			Sn:        sn,
			Name:      req.Name,
			Cdk:       req.Cdk,
			TypeID:    req.TypeId,
			Openid:    req.Openid,
			Times:     req.Times,
			ExpiredAt: int32(req.ExpiredAt),
			Award:     string(award),
			Date:      time.Now().Format("2006-01-02"),
			Operator:  req.Operator,
			CreatedAt: time.Now().Unix(),
		})

	} else {
		// 批量生成
		for i := 1; i <= req.Num; i++ {
			codes = append(codes, &model.RedeemCode{
				ServerIds: string(serverIds),
				Sn:        sn,
				Name:      req.Name,
				Cdk:       character.RandStringRunes(16),
				TypeID:    req.TypeId,
				Openid:    req.Openid,
				Times:     req.Times,
				ExpiredAt: int32(req.ExpiredAt),
				Award:     string(award),
				Date:      time.Now().Format("2006-01-02"),
				Operator:  req.Operator,
				CreatedAt: time.Now().Unix(),
			})
		}

	}
	if err = query.Use(config.DB).RedeemCode.WithContext(ctx).CreateInBatches(codes, req.Num); err != nil {
		return serializer.DBErr(err.Error(), err)
	}
	return serializer.Suc(nil)
}

func (s *sCdk) Received(ctx *gin.Context, req forms.CdkReceivedReq) serializer.Response {
	type RedeemReceived struct {
		model.RedeemReceived
		Server string `json:"server"`
	}

	var (
		q            = query.Use(config.DB).RedeemReceived
		m            = q.WithContext(ctx)
		offset int64 = 0
		models forms.UserAccountListRes
		lists  []RedeemReceived
	)

	m = m.Where(q.Cid.Eq(req.Cid)).Order(q.ID.Desc())

	req.Page, req.PerPage, offset = forms.CalculatePage(req.Page, req.PerPage)

	count, err := m.Count()
	if err != nil {
		return serializer.Err(consts.CodeParamErr, "查询出错 count", err)
	}

	if count > 0 {
		if err = m.Limit(int(req.PerPage)).Offset(int(offset)).Scan(&lists); err != nil {
			return serializer.Err(consts.CodeParamErr, "查询出错 lists", err)
		}
	}

	if len(lists) > 0 {
		for k, v := range lists {
			serverId, err := player.GetDBByUserId(v.Playerid)
			if err != nil {
				logrus.Warnf("CDK Received lists err:%+v", err)
				continue
			}

			name, err := ServerOption.GetName(ctx, int32(serverId))
			if err != nil {
				logrus.Warnf("CDK Received lists GetName err:%+v", err)
				continue
			}

			lists[k].Server = fmt.Sprintf("%v(%v)", name, serverId)
		}
	}

	models.List = lists
	models.Page = req.Page
	models.PerPage = req.PerPage
	models.PageCount = (count + req.PerPage - 1) / req.PerPage

	return serializer.Suc(models)
}

func (s *sCdk) Invalid(ctx *gin.Context, req forms.CdkInvalidReq) serializer.Response {
	var (
		q   = query.Use(config.DB).RedeemCode
		m   = query.Use(config.DB).RedeemCode.WithContext(ctx)
		err error
	)
	// 编辑
	if req.Sn == "" {
		return serializer.ParamErr("sn不能空，删除失败！", nil)
	}
	one, err := m.Where(q.Sn.Eq(req.Sn)).First()
	if err != nil {
		return serializer.DBErr(err.Error(), err)
	}
	if one.Status == req.Status {
		return serializer.Suc(nil)
	}

	_, err = query.Use(config.DB).RedeemCode.WithContext(ctx).Where(q.Sn.Eq(req.Sn)).Update(q.Status, req.Status)
	if err != nil {
		return serializer.DBErr(err.Error(), err)
	}

	return serializer.Suc(nil)
}

func (s *sCdk) RedeemCodeList(ctx *gin.Context, req forms.CdkRedeemCodeListReq) serializer.Response {
	type RedeemCode struct {
		model.RedeemCode
		Used int64 `json:"used"`
	}
	type RedeemReceived struct {
		Cid   int64 `json:"cid"`
		Total int64 `json:"total"`
	}

	var (
		q              = query.Use(config.DB).RedeemCode
		r              = query.Use(config.DB).RedeemReceived
		m              = q.WithContext(ctx)
		offset   int64 = 0
		models   forms.UserAccountListRes
		lists    []*RedeemCode
		received []*RedeemReceived
	)

	if req.Sn != "" {
		m = m.Where(q.Sn.Eq(req.Sn))
	}

	if req.Cdk != "" {
		m = m.Where(q.Cdk.Eq(req.Cdk))
	}
	if len(req.CreatedAt) == 2 {
		m = m.Where(q.CreatedAt.Between(req.CreatedAt[0], req.CreatedAt[1]))
	}

	m = m.Order(q.ID.Desc(), q.Sn.Desc())

	req.Page, req.PerPage, offset = forms.CalculatePage(req.Page, req.PerPage)

	count, err := m.Count()
	if err != nil {
		return serializer.Err(consts.CodeParamErr, "查询出错 count", err)
	}

	if count > 0 {
		if err = m.Limit(int(req.PerPage)).Offset(int(offset)).Scan(&lists); err != nil {
			return serializer.Err(consts.CodeParamErr, "查询出错 lists", err)
		}
	}
	// code id slice
	codeIds := make([]int64, len(lists))
	for i, v := range lists {
		codeIds[i] = v.ID
	}

	err = r.WithContext(ctx).Select(r.Cid, r.ID.Count().As("total")).Where(r.Cid.In(codeIds...)).Group(r.Cid).Scan(&received)
	if err != nil {
		return serializer.Err(consts.CodeParamErr, "查询出错 lists", err)
	}
	if len(received) != 0 {
		receivedMap := make(map[int64]int64, len(received))
		for _, item := range received {
			receivedMap[item.Cid] = item.Total
		}
		for _, v := range lists {
			v.Used = receivedMap[v.ID]
		}
	}

	models.List = lists
	models.Page = req.Page
	models.PerPage = req.PerPage
	models.PageCount = (count + req.PerPage - 1) / req.PerPage

	return serializer.Suc(models)
}

// Exchange 兑换物品
// ErrCode
// 0 兑换成功
// 501001 当前兑换人数过多，请稍后重试
// 501002 请输入正确地兑换码
// 501003 兑换码已过期
// 501004 该兑换码暂不支持当前账户领取
// 501005 查询异常，请稍后重试
// 501006 已经领取过啦
// 501007 查询异常，请稍后重试
// 501008 已被领完
// 501009 获取奖励物品失败
// 501010 兑换失败
// 501011 兑换失败，请稍后重试
func (s *sCdk) Exchange(ctx context.Context, req *msg.RedeemGoodsIs) (res msg.ResponseRedeemGoodsIs, err error) {

	if req.Code == "" || !character.IsLetterNumber(req.Code) {
		return msg.ResponseRedeemGoodsIs{
			ErrCode:  5010022, // 兑换码不存在
			PlayerId: req.PlayerId,
			GateId:   req.GateId,
		}, err
	}

	var (
		q        = query.Use(config.DB).RedeemCode
		r        = query.Use(config.DB).RedeemReceived
		models   *model.RedeemCode
		reModels *model.RedeemReceived
	)

	if err = q.WithContext(ctx).Where(q.Cdk.Eq(req.Code)).Scan(&models); err != nil {
		return msg.ResponseRedeemGoodsIs{
			ErrCode:  501001, // 查询异常，请稍后重试
			PlayerId: req.PlayerId,
			GateId:   req.GateId,
		}, err
	}

	if models == nil {
		return msg.ResponseRedeemGoodsIs{
			ErrCode:  501002, // 兑换码不存在
			PlayerId: req.PlayerId,
			GateId:   req.GateId,
		}, err
	}

	if int64(models.ExpiredAt) < time.Now().Unix() {
		return msg.ResponseRedeemGoodsIs{
			ErrCode:  501003, // 兑换码已过期
			PlayerId: req.PlayerId,
			GateId:   req.GateId,
		}, err
	}

	if models.Openid != "" && models.Openid != req.OpenId {
		return msg.ResponseRedeemGoodsIs{
			ErrCode:  501004, // 该兑换码暂不支持当前账户领取
			PlayerId: req.PlayerId,
			GateId:   req.GateId,
		}, err
	}

	if models.Status != 1 {
		return msg.ResponseRedeemGoodsIs{
			ErrCode:  501003, // 兑换码已过期
			PlayerId: req.PlayerId,
			GateId:   req.GateId,
		}, err
	}

	if err = s.checkServerOwner(models, req.PlayerId); err != nil {
		return msg.ResponseRedeemGoodsIs{
			ErrCode:  501004, // 该兑换码暂不支持当前账户领取
			PlayerId: req.PlayerId,
			GateId:   req.GateId,
		}, err
	}

	if err = r.WithContext(ctx).Where(r.Cid.Eq(models.ID), r.Playerid.Eq(req.PlayerId)).Scan(&reModels); err != nil {
		return msg.ResponseRedeemGoodsIs{
			ErrCode:  501005, // 查询异常，请稍后重试
			PlayerId: req.PlayerId,
			GateId:   req.GateId,
		}, err
	}

	if reModels != nil {
		return msg.ResponseRedeemGoodsIs{
			ErrCode:  501006, // 已经领取过啦
			PlayerId: req.PlayerId,
			GateId:   req.GateId,
		}, err
	}

	count, err := r.WithContext(ctx).Where(r.Cid.Eq(models.ID)).Count()
	if err != nil {
		return msg.ResponseRedeemGoodsIs{
			ErrCode:  501007, // 查询异常，请稍后重试
			PlayerId: req.PlayerId,
			GateId:   req.GateId,
		}, err
	}

	if count >= models.Times {
		return msg.ResponseRedeemGoodsIs{
			ErrCode:  501008, // 已领完
			PlayerId: req.PlayerId,
			GateId:   req.GateId,
		}, err
	}

	var award forms.CdkAward
	if err = json.Unmarshal([]byte(models.Award), &award); err != nil {
		return msg.ResponseRedeemGoodsIs{
			ErrCode:  501009, // 获取奖励物品失败
			PlayerId: req.PlayerId,
			GateId:   req.GateId,
		}, err
	}

	var data model.RedeemReceived
	data.Cid = models.ID
	data.Playerid = req.PlayerId
	data.Openid = req.OpenId
	data.CreatedAt = time.Now().Unix()

	if err = query.Use(config.DB).RedeemReceived.WithContext(ctx).Create(&data); err != nil {
		return msg.ResponseRedeemGoodsIs{
			ErrCode:  501010, // 兑换失败
			PlayerId: req.PlayerId,
			GateId:   req.GateId,
		}, err
	}

	if data.ID <= 0 {
		return msg.ResponseRedeemGoodsIs{
			ErrCode:  501011, // 兑换失败-2
			PlayerId: req.PlayerId,
			GateId:   req.GateId,
		}, err
	}

	return msg.ResponseRedeemGoodsIs{
		ErrCode:    0, // 兑换成功
		PlayerId:   req.PlayerId,
		GateId:     req.GateId,
		Materials:  award.Materials,
		Equipments: award.Equipment,
	}, nil

}

func (s *sCdk) checkServerOwner(models *model.RedeemCode, playerId int64) (err error) {
	logrus.Warnf("checkServerOwner..")
	if models.ServerIds == "" { // 不限制服务器
		return
	}

	var ids []int
	if err = json.Unmarshal([]byte(models.ServerIds), &ids); err != nil {
		return err
	}
	if len(ids) == 0 {
		return
	}

	for _, id := range ids {
		// 所有服务器，不效验
		if id == 0 {
			return
		}
	}

	// 检查玩家所在服务器
	serverId, err := player.GetDBByUserId(playerId)
	if err != nil {
		return err
	}

	for _, id := range ids {
		// 包含玩家所在服务器
		if id == serverId {
			return
		}
	}

	err = errors.New("玩家所在服务器不支持兑换")

	return
}
*/
