package models

import (
	"crypto/sha512"
	"errors"
	"fmt"
	orm "go-admin/common/global"
	"go-admin/logger"
	"strings"
	"time"
)

const (
	RedeemCodeStatusStock = "stocking"  // 库存
	RedeemCodeStatusHold  = "user-hold" // 用户持有
	RedeemCodeStatusUsed  = "used"      // 已使用
)
const (
	CodeTypeMemberCard30          = "member-card-30"                // 30天租卡会员
	CodeTypeMemberGoldMember      = "member-card-gold-member"       // 黄金会员
	CodeTypeMemberPlatinumMember  = "member-card-platinum-member"   // 白金会员
	CodeTypeMemberBlackGoldMember = "member-card-black-gold-member" // 黑金会员
	CodeTypeMemberPrivilegeMember = "member-card-privilege-member"  // 尊享会员
)

const (
	RedeemCodeSecretKey = "046033a527d1b723ed0a1012e6518d490"
)

const (
	UserRedeemCodeStatusHold = "user-hold"
	UserRedeemCodeStatusUsed = "used"
)

const (
	RedeemCodeActivityTypeStore      = 1 // 门店赠送
	RedeemCodeActivityTypeUserInvite = 2 // 用户邀请

)

// gen:qs
//
//go:generate goqueryset -in redeem_code.go
type RedeemCode struct {
	Model
	SerialCode     string    `json:"serial_code"  gorm:"index;comment:'兑换编码'"` // 兑换编码
	CodeType       string    `json:"code_type"`                                // CodeTypeMemberCard30
	Status         string    `json:"status" gorm:"index;comment:'兑换状态'"`       // stocking user-hold used
	StoreId        uint32    `json:"store_id" gorm:"index"`                    // 门店id
	CodeSecret     string    `json:"code_secret"`                              // 兑换密码
	EffectiveTime  time.Time `json:"effective_time"`                           // 生效时间
	ExpirationTime time.Time `json:"expiration_time"`                          // 过期时间
}

func (*RedeemCode) TableName() string {
	return "redeem_code"
}

// gen:qs
type UserRedeemCode struct {
	Model
	Uid          uint32    `json:"uid" gorm:"index;comment:'用户id'"`
	Status       string    `json:"status" gorm:"index;comment:'兑换状态'"`       // user-hold used
	StoreId      uint32    `json:"store_id" gorm:"index"`                    // 门店id
	SerialCode   string    `json:"serial_code"  gorm:"index;comment:'兑换编码'"` // 兑换编码
	CodeType     string    `json:"code_type"`                                // memberCard
	ConvertTime  time.Time `json:"convert_time"`
	ActivityType uint32    `json:"activity_type"` // 1-门店赠送 2-用户邀请
}

func (*UserRedeemCode) TableName() string {
	return "user_redeem_code"
}

//type BindingRedeemCodeRecord struct {
//	Model
//}

// 会员兑换码
// 用户押金
// 支付押金
// 押金
// 开通会员
// 管理端 发 会员 Sign  校验
// 押金300

func RedeemSecretCode(redeem string) string {
	semen := redeem[:13] + strings.ToUpper(RedeemCodeSecretKey)
	shaer := sha512.New()
	shaer.Write([]byte(semen))
	r := shaer.Sum(nil)
	hs := fmt.Sprintf("%x", r)
	return hs[:7]
}

type RedeemCodeListReq struct {
	PageIndex  int    `json:"pageIndex"`
	PageSize   int    `json:"pageSize"`
	Status     string `json:"status"`      // user-hold used
	SerialCode string `json:"serial_code"` // 兑换编码
	CodeType   string `json:"code_type"`   // 兑换码类型
}
type RedeemCodeListResp struct {
	List      []RedeemCode `json:"list"`
	PageIndex int          `json:"pageIndex"`
	Count     int          `json:"count"`
}

func (m *RedeemCodeListReq) RedeemCodeStockList() (*RedeemCodeListResp, error) {
	resp := &RedeemCodeListResp{
		PageIndex: m.PageIndex,
	}

	redeem := &RedeemCode{}
	qs := orm.Eloquent.Table(redeem.TableName())
	if m.Status != "" {
		qs = qs.Where("status=?", m.Status)
	}
	if m.SerialCode != "" {
		qs = qs.Where("serial_code=?", m.SerialCode)
	}
	if m.CodeType != "" {
		qs = qs.Where("code_type=?", m.CodeType)
	}

	var count int64
	err := qs.Count(&count).Error
	if err != nil {
		logger.Errorf("err:", logger.Field("err", err))
		return resp, err
	}
	resp.Count = int(count) + 1
	page := m.PageIndex - 1
	if page < 0 {
		page = 0
	}

	var redeems []RedeemCode
	err = qs.Order("id DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&redeems).Error
	if err != nil && err != RecordNotFound {
		logger.Errorf("err:", logger.Field("err", err))
		return resp, err
	}
	for i, _ := range redeems {
		redeems[i].CodeSecret = ""
	}
	resp.List = redeems

	return resp, nil
}

type UserRedeemCodeListReq struct {
	PageIndex    int    `json:"pageIndex"`
	PageSize     int    `json:"pageSize"`
	Status       string `json:"status"`      // user-hold used
	SerialCode   string `json:"serial_code"` // 兑换编码
	CodeType     string `json:"code_type"`   // 兑换码类型
	Uid          int    `json:"uid"`
	ConvertStart string `json:"convert_start"`
	ConvertEnd   string `json:"convert_end"`
}
type UserRedeemCodeListResp struct {
	List      []UserRedeemCodeInfo `json:"list"`
	PageIndex int                  `json:"pageIndex"`
	Count     int                  `json:"count"`
}

type UserRedeemCodeInfo struct {
	UserRedeemCode

	WxName   string `json:"wxName"`   // 昵称
	WxAvatar string `json:"wxAvatar"` // 头像
	Tel      string `json:"tel"`      // 电话
}

func (m *UserRedeemCodeListReq) UserSendRedeemCodeList() (*UserRedeemCodeListResp, error) {
	resp := &UserRedeemCodeListResp{
		PageIndex: m.PageIndex,
	}

	qs := orm.Eloquent.Table("user_redeem_code").Debug()

	if m.Status != "" {
		qs = qs.Where("status=?", m.Status)
	}
	if m.SerialCode != "" {
		qs = qs.Where("serial_code=?", m.SerialCode)
	}
	if m.Uid != 0 {
		qs = qs.Where("uid=?", m.Uid)
	}
	if m.CodeType != "" {
		qs = qs.Where("code_type=?", m.CodeType)
	}

	if m.ConvertStart != "" {
		parse, err := time.Parse(DateTimeFormat, m.ConvertStart)
		if err != nil {
			logger.Errorf("err:", logger.Field("err", err))
			return resp, err
		}
		qs = qs.Where("created_at >= ?", parse)
	}
	if m.ConvertEnd != "" {
		parse, err := time.Parse(DateTimeFormat, m.ConvertEnd)
		if err != nil {
			logger.Errorf("err:", logger.Field("err", err))
			return resp, err
		}
		qs = qs.Where("created_at <= ?", parse)
	}

	var count int64
	err := qs.Count(&count).Error
	if err != nil {
		logger.Errorf("err:", logger.Field("err", err))
		return resp, err
	}
	resp.Count = int(count)
	page := m.PageIndex - 1
	if page < 0 {
		page = 0
	}
	var userRedeemCodes []UserRedeemCode
	err = qs.Order("id DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&userRedeemCodes).Error
	if err != nil && err != RecordNotFound {
		logger.Errorf("err:", logger.Field("err", err))
		return resp, err
	}
	fmt.Println("userRedeemCodes:", len(userRedeemCodes))
	redeemCodeInfo := UserRedeemCodeToInfo(userRedeemCodes)
	resp.List = redeemCodeInfo
	fmt.Println("redeemCodeInfo:", len(redeemCodeInfo))
	return resp, nil
}

func CodeSendToUser(uid, storeId uint32, codeType string) error {
	var redeemCode RedeemCode
	err := orm.Eloquent.Table("redeem_code").Where("status=?", RedeemCodeStatusStock).
		Where("code_type=?", codeType).Order("id ASC").Limit(1).Find(&redeemCode).Error
	if err != nil {
		logger.Errorf("err:", logger.Field("err", err))
		return err
	}
	memberRedeemCode := int64(0)

	if redeemCode.ID == 0 {
		logger.Errorf("err:", logger.Field("err", "兑换券已消耗完，请联系运营同事添加"))
		return errors.New("redeem_code_none")
	}

	if redeemCode.CodeType == CodeTypeMemberPrivilegeMember { // 尊享会员
		err = orm.Eloquent.Table("user_redeem_code").Where("uid=?", uid).
			Where("code_type = ?", CodeTypeMemberPrivilegeMember).Count(&memberRedeemCode).Error
	} else { // 租卡会员
		err = orm.Eloquent.Table("user_redeem_code").Where("uid=?", uid).
			Where("code_type in (?)", []string{CodeTypeMemberGoldMember, CodeTypeMemberPlatinumMember,
				CodeTypeMemberBlackGoldMember}).Count(&memberRedeemCode).Error
	}
	if err != nil {
		logger.Errorf("err:", logger.Field("err", err))
		return err
	}

	if redeemCode.CodeType == CodeTypeMemberPrivilegeMember { // 尊享会员
		if memberRedeemCode > 0 {
			logger.Errorf("err:", logger.Field("err", err))
			return errors.New("member_redeem_code_only")
		}
	} else { // 租卡会员
		if memberRedeemCode > 0 && codeType != CodeTypeMemberCard30 {
			logger.Errorf("err:", logger.Field("err", err))
			return errors.New("member_redeem_code_only")
		}
	}

	if redeemCode.CodeType == CodeTypeMemberPrivilegeMember { // 尊享会员
		// 获取尊享会员信息
		var privilegeUserInfo PrivilegeMember
		if err := orm.Eloquent.Table("privilege_member").Where("uid = ?", uid).Find(&privilegeUserInfo).Error; err != nil {
			logger.Errorf("获取尊享会员信息出错:", logger.Field("err", err))
			return err
		}

		if privilegeUserInfo.MemberLevel == 6 { // 已经是尊享会员
			logger.Errorf("user is member:")
			return errors.New("user_is_member")
		}

	} else { // 租卡会员
		userInfo, err := GetUserInfoByUid(uid)
		if err != nil {
			logger.Errorf("err:", logger.Field("err", err))
			return err
		}

		if userInfo.MemberLevel != 1 && userInfo.MemberLevel != 3 && codeType != CodeTypeMemberCard30 {
			logger.Errorf("user is member:")
			return errors.New("user_is_member")
		}
	}

	fmt.Println("CodeSendToUser uid:", uid)
	_, err = IsUserInfoByUid(uid)
	if err != nil {
		logger.Error("err:", logger.Field("err", err))
		return err
	}

	begin := orm.Eloquent.Begin()

	sql := fmt.Sprintf("UPDATE redeem_code SET `status` ='%s',store_id=%d WHERE id =%d", RedeemCodeStatusHold, storeId, redeemCode.ID)
	err = begin.Exec(sql).Error
	if err != nil {
		logger.Errorf("err:", logger.Field("err", err))
		begin.Rollback()
		return err
	}
	userRedeemCode := &UserRedeemCode{
		Uid:          uid,
		Status:       UserRedeemCodeStatusHold,
		SerialCode:   redeemCode.SerialCode,
		CodeType:     redeemCode.CodeType,
		ActivityType: RedeemCodeActivityTypeStore,
		StoreId:      storeId,
	}
	err = begin.Create(userRedeemCode).Error
	if err != nil {
		logger.Errorf("err:", logger.Field("err", err))
		begin.Rollback()
		return err
	}
	err = begin.Commit().Error
	if err != nil {
		logger.Errorf("err:", logger.Field("err", err))
		begin.Rollback()
		return err
	}
	return nil
}

func UserRedeemCodeToInfo(userRedeems []UserRedeemCode) []UserRedeemCodeInfo {
	uids := make([]uint32, 0, len(userRedeems))
	for i, _ := range userRedeems {
		uids = append(uids, userRedeems[i].Uid)
	}
	//UserInfo{}
	list := make([]UserRedeemCodeInfo, 0, len(userRedeems))
	var users []UserInfo
	err := orm.Eloquent.Table("user").Where("uid in (?)", uids).Find(&users).Error
	if err != nil {
		logger.Errorf("err:", logger.Field("err", err))
		return list
	}

	userMap := make(map[uint32]UserInfo, 0)
	for i, _ := range users {
		userMap[users[i].Uid] = users[i]
	}
	for i, _ := range userRedeems {
		userInfo, ok := userMap[userRedeems[i].Uid]
		info := UserRedeemCodeInfo{
			UserRedeemCode: userRedeems[i],
		}
		if ok {
			info.WxName = userInfo.WxName
			info.WxAvatar = userInfo.WxAvatar
			info.Tel = userInfo.Tel
		} else {
			info.WxName = "未知用户"
			info.WxAvatar = "" // 可设默认头像路径
			info.Tel = ""
		}
		list = append(list, info)
	}

	return list
}
