package models

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	utils "go-admin/app/admin/models/tools"
	orm "go-admin/common/global"
	"go-admin/logger"
	"go-admin/tools/config"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"strings"
	"time"
)

const (
	ErpCouponUnStarted  = 1 // 未开始
	ErpCouponSending    = 2 // 发放中
	ErpCouponInProgress = 3 // 进行中
	ErpCouponFinished   = 4 // 已结束
	ErpCouponSendFailed = 5 // 发放失败

	TaskInProgress = "in_progress" // 执行中
	TaskCompleted  = "completed"   // 已完成
	TaskFailed     = "failed"      // 发送失败

	AccessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token"
	WXAppID        = "wx806c079463b5b56c"
	WXSecret       = "cb125688bf4e482f66e8c46062d568fc"

	WxSubscribeMessage = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token="
	TemplateId         = "aP3c503T3wn-tJtpDccvxtNi7b1qjrwavFFfo-k2SAQ"
	WxJumpUrl          = "/pages/voucher/voucher" // 跳转微信小程序的页面路径

	WXGenerateSchema = "https://api.weixin.qq.com/wxa/generatescheme?access_token="

	SMSHead = "【明慧科技】"
)

// WxAccessToken 微信access_token
type WxAccessToken struct {
	Model
	Appid       string    `json:"appid"`        // 小程序appid
	AccessToken string    `json:"access_token"` // 获取到的凭证
	ExpiresTime time.Time `json:"expires_time"` // 凭证有效时间
}

// CouponIssuanceTask 优惠券发放任务表
type CouponIssuanceTask struct {
	Model
	ErpCouponId   uint32 `json:"erp_coupon_id"`                  // 优惠券id
	ErpCouponName string `json:"erp_coupon_name"`                // 优惠券名称
	Status        string `json:"status"`                         // 任务状态：in_progress(执行中）、completed（已完成）、failed（发送失败）
	LastUserID    uint32 `json:"last_user_id"`                   // 上次处理的用户ID
	ErrorMessage  string `json:"error_message" gorm:"type:text"` // 错误信息，若任务失败时记录
}

// ErpCoupon 营销管理-优惠券
type ErpCoupon struct {
	Model
	Name              string     `json:"name" gorm:"index"`            // 优惠券名称
	Remark            string     `json:"remark"`                       // 备注
	Describe          string     `json:"describe" gorm:"type:text"`    // 优惠券简介
	Rule              string     `json:"rule" gorm:"type:text"`        // 优惠券使用规则
	CategoryNumber    string     `json:"category_number"`              // 可以使用该优惠券的商品分类，如果为空则表示没限制
	ActiveDate        uint32     `json:"active_date"`                  // 有效期（天）
	Amount            uint32     `json:"amount"`                       // 金额（元）
	UserType          uint32     `json:"user_type"`                    // 领取人限制：1-所有人 2-未付费用户 3-已付费用户 4-尊享会员
	Limit             uint32     `json:"limit"`                        // 优惠券叠加限制 0-不限制；1-仅限原价购买时使用
	StartTime         *time.Time `json:"start_time"`                   // 启动时间
	State             uint32     `json:"state" gorm:"index"`           // 当前状态 1-未开始；2-发放中；3-进行中；4-已结束；5-发放失败
	SendCount         uint32     `json:"send_count"`                   // 已发放
	UsedCount         uint32     `json:"used_count"`                   // 已使用
	TotalPayAmount    float64    `json:"total_pay_amount"`             // 支付金额（元）
	PerCustomerAmount float64    `json:"per_customer_amount"`          // 客单价（元）
	SmsContent        string     `json:"sms_content" gorm:"type:text"` // 短信提示内容
}

// ErpMarketingCouponListReq 优惠券列表入参
type ErpMarketingCouponListReq struct {
	Name             string `json:"name" gorm:"index"`  // 优惠券名称
	State            uint32 `json:"state" gorm:"index"` // 当前状态 1-未开始；2-发放中；3-进行中；4-已结束
	CreatedTimeStart string `json:"created_time_start"` // 创建开始时间
	CreatedTimeEnd   string `json:"created_time_end"`   // 创建结束时间
	PageIndex        int    `json:"pageIndex"`          // 页码
	PageSize         int    `json:"pageSize"`           // 页面条数
	IsExport         uint32 `json:"is_export"`          // 1-导出
}

// ErpMarketingCouponListResp 优惠券列表出参
type ErpMarketingCouponListResp struct {
	List      []ErpCoupon `json:"list"`
	Total     int         `json:"total"`      // 总条数
	PageIndex int         `json:"pageIndex"`  // 页码
	PageSize  int         `json:"pageSize"`   // 页面条数
	ExportUrl string      `json:"export_url"` // 导出excel路径
}

// ErpMarketingCouponCreateReq 新增优惠券入参
type ErpMarketingCouponCreateReq struct {
	Name           string `json:"name" validate:"required"`            // 优惠券名称
	Remark         string `json:"remark"`                              // 备注
	Describe       string `json:"describe" gorm:"type:text"`           // 优惠券简介
	Rule           string `json:"rule"  gorm:"type:text"`              // 优惠券使用规则
	CategoryNumber string `json:"category_number" validate:"required"` // 可以使用该优惠券的商品分类编号，如果为空则表示没限制
	ActiveDate     uint32 `json:"active_date" validate:"required"`     // 有效期（天）
	Amount         uint32 `json:"amount" validate:"required"`          // 金额（元）
	UserType       uint32 `json:"user_type" validate:"required"`       // 领取人限制：1-所有人 2-未付费用户 3-已付费用户 4-尊享会员
	Limit          uint32 `json:"limit"`                               // 优惠券叠加限制 0-不限制；1-仅限原价购买时使用
	SmsContent     string `json:"sms_content" validate:"required"`     // 短信提示内容
}

// ErpMarketingCouponEditReq 编辑优惠券入参
type ErpMarketingCouponEditReq struct {
	ErpCouponId    uint32 `json:"erp_coupon_id" validate:"required"`   // 优惠券id
	Name           string `json:"name" validate:"required"`            // 优惠券名称
	Remark         string `json:"remark"`                              // 名称备注
	Describe       string `json:"describe" gorm:"type:text"`           // 优惠券简介
	Rule           string `json:"rule"  gorm:"type:text"`              // 优惠券使用规则
	CategoryNumber string `json:"category_number" validate:"required"` // 可以使用该优惠券的商品分类，如果为空则表示没限制
	ActiveDate     uint32 `json:"active_date" validate:"required"`     // 有效期（天）
	Amount         uint32 `json:"amount" validate:"required"`          // 金额（元）
	UserType       uint32 `json:"user_type" validate:"required"`       // 领取人限制：1-所有人 2-未付费用户 3-已付费用户 4-尊享会员
	Limit          uint32 `json:"limit"`                               // 优惠券叠加限制 0-不限制；1-仅限原价购买时使用
	SmsContent     string `json:"sms_content" validate:"required"`     // 短信提示内容
}

// ErpMarketingCouponDetailReq 优惠券详情入参
type ErpMarketingCouponDetailReq struct {
	ErpCouponId uint32 `json:"erp_coupon_id" validate:"required"` // 优惠券id
}

// ErpMarketingCouponDeleteReq 删除优惠券入参
type ErpMarketingCouponDeleteReq struct {
	ErpCouponId uint32 `json:"erp_coupon_id" validate:"required"` // 优惠券id
}

// ErpMarketingCouponStartReq 启动优惠券发放
type ErpMarketingCouponStartReq struct {
	ErpCouponId []uint32 `json:"erp_coupon_id" validate:"required"` // 优惠券id
	Remark      string   `json:"remark" validate:"required"`        // 活动名称备注
	SmsContent  string   `json:"sms_content" validate:"required"`   // 短信提示内容
}

// ErpMarketingCouponDataReq 优惠券数据入参
type ErpMarketingCouponDataReq struct {
	ErpCouponId uint32 `json:"erp_coupon_id" validate:"required"` // 优惠券id
}

// ErpMarketingCouponDataResp 优惠券数据出参
type ErpMarketingCouponDataResp struct {
	TotalAmount       float64       `json:"total_amount"`       // 用券总成交额：使用该优惠券的订单付款总金额
	TotalDiscount     float64       `json:"total_discount"`     // 优惠总金额：使用该优惠券优惠的总金额
	CostEffectiveness float64       `json:"cost_effectiveness"` // 费效比：优惠总金额 / 用券总成交额
	OrderCount        int           `json:"order_count"`        // 订单数：使用该优惠券的付款订单数
	UnitPrice         float64       `json:"unit_price"`         // 用券笔单价：用券总成交额 / 使用该优惠券的付款订单数
	CustomerCount     int           `json:"customer_count"`     // 用券客户数：使用该优惠券的成交客户数
	ProductCount      int           `json:"product_count"`      // 购买商品件数：使用该优惠券购买的商品数量
	Products          []ProductInfo `json:"products"`           // 商品信息：包含每个商品的ID、名称、付款件数、付款人数等信息
}

// ProductInfo 商品信息结构体
type ProductInfo struct {
	ProductID   int    `json:"product_id"`   // 商品ID
	ProductName string `json:"product_name"` // 商品名称
	PayCount    int    `json:"pay_count"`    // 付款件数：使用该优惠券购买该商品的付款件数
	PayCustomer int    `json:"pay_customer"` // 付款人数：购买该商品并使用优惠券的客户人数
}

type GenerateSchemeReq struct {
	Path       string `json:"path" validate:"required"` // 跳转小程序页面
	EnvVersion string `json:"env_version"`              // 默认值"release"。要打开的小程序版本。正式版为"release"，体验版为"trial"，开发版为"develop"
}

type GenerateSchemeResp struct {
	Openlink string `json:"openlink"` // 小程序跳转链接
}

type WXGenerateSchemeResponse struct {
	Errcode  int    `json:"errcode"`
	Errmsg   string `json:"errmsg"`
	Openlink string `json:"openlink"`
}

// List 查询优惠券列表
func (m *ErpMarketingCouponListReq) List() (*ErpMarketingCouponListResp, error) {
	resp := &ErpMarketingCouponListResp{
		PageIndex: m.PageIndex,
		PageSize:  m.PageSize,
	}
	page := m.PageIndex - 1
	if page < 0 {
		page = 0
	}
	if m.PageSize == 0 {
		m.PageSize = 10
	}
	qs := orm.Eloquent.Table("erp_coupon")

	if m.Name != "" {
		qs = qs.Where("name = ?", m.Name)
	}
	if m.State != 0 {
		qs = qs.Where("state = ?", m.State)
	}
	if m.CreatedTimeStart != "" {
		parse, err := time.Parse(QueryTimeFormat, m.CreatedTimeStart)
		if err != nil {
			logger.Errorf("erpPurchaseOrderList err:", err)
			return nil, err
		}
		qs = qs.Where("created_at > ?", parse)
	}
	if m.CreatedTimeEnd != "" {
		parse, err := time.Parse(QueryTimeFormat, m.CreatedTimeEnd)
		if err != nil {
			logger.Errorf("erpPurchaseOrderList err:", err)
			return nil, err
		}
		qs = qs.Where("created_at < ?", parse)
	}

	var count int64
	err := qs.Count(&count).Error
	if err != nil {
		logger.Error("count err:", logger.Field("err", err))
		return resp, err
	}
	resp.Total = int(count)

	var couponList []ErpCoupon
	err = qs.Order("id DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&couponList).Error
	if err != nil && err != RecordNotFound {
		logger.Error("erp_coupon list err:", logger.Field("err", err))
		return resp, err
	}

	for i, v := range couponList {
		couponList[i].Amount = v.Amount / 100
	}

	resp.List = couponList

	return resp, nil
}

// CreateErpMarketingCoupon 新增优惠券
func CreateErpMarketingCoupon(req *ErpMarketingCouponCreateReq) error {
	erpCoupon := &ErpCoupon{
		Name:           req.Name,
		Remark:         req.Remark,
		Describe:       req.Describe,
		Rule:           req.Rule,
		CategoryNumber: req.CategoryNumber,
		ActiveDate:     req.ActiveDate,
		Amount:         req.Amount * 100,
		UserType:       req.UserType,
		Limit:          req.Limit,
		State:          ErpCouponUnStarted,
		SmsContent:     req.SmsContent,
	}

	err := orm.Eloquent.Create(erpCoupon).Error
	if err != nil {
		logger.Error("create  purchase order err:", logger.Field("err", err))
		return err
	}

	coupon := &Coupon{
		Name:           req.Name,
		Describe:       req.Describe,
		Rule:           req.Rule,
		CouponType:     "deduction",
		Value:          req.Amount * 100,
		CategoryNumber: req.CategoryNumber,
		ActivityType:   666,
		ErpCouponId:    erpCoupon.ID,
		ActiveStart:    Now(),
		ActiveEnd:      Now().AddDate(0, 0, int(req.ActiveDate)),
		Limit:          req.Limit,
	}

	err = orm.Eloquent.Create(coupon).Error
	if err != nil {
		logger.Error("create coupon order err:", logger.Field("err", err))
		return err
	}

	return nil
}

// EditErpMarketingCoupon 编辑优惠券
func EditErpMarketingCoupon(req *ErpMarketingCouponEditReq) error {
	// 查询订单信息
	var erpCoupon ErpCoupon
	err := orm.Eloquent.Table("erp_coupon").Where("id=?", req.ErpCouponId).Find(&erpCoupon).Error
	if err != nil {
		logger.Error("query erp_coupon err:", logger.Field("err", err))
		return err
	}

	if erpCoupon.ID == 0 {
		logger.Error("delete err, erpCoupon ID is:", logger.Field("erpCoupon.ID", req.ErpCouponId))
		return errors.New(fmt.Sprintf("编辑失败:未查询到优惠券id[%d]", req.ErpCouponId))
	}

	// 1-更新优惠券信息
	erpCoupon.Name = req.Name
	erpCoupon.Remark = req.Remark
	erpCoupon.Rule = req.Rule
	erpCoupon.Describe = req.Describe
	erpCoupon.CategoryNumber = req.CategoryNumber
	erpCoupon.ActiveDate = req.ActiveDate
	erpCoupon.Amount = req.Amount * 100
	erpCoupon.UserType = req.UserType
	erpCoupon.Limit = req.Limit
	erpCoupon.SmsContent = req.SmsContent

	begin := orm.Eloquent.Begin()
	err = begin.Model(&ErpCoupon{}).Where("id = ?", req.ErpCouponId).
		Omit("created_at").Save(erpCoupon).Error
	if err != nil {
		begin.Rollback()
		logger.Error("update erp_coupon err:", logger.Field("err", err))
		return err
	}

	// 查询订单信息
	var coupon Coupon
	err = orm.Eloquent.Table("coupon").Where("erp_coupon_id=?", req.ErpCouponId).Find(&coupon).Error
	if err != nil {
		begin.Rollback()
		logger.Error("query coupon err:", logger.Field("err", err))
		return err
	}

	coupon.Name = req.Name
	coupon.Describe = req.Describe
	coupon.Rule = req.Rule
	coupon.Value = req.Amount * 100
	coupon.ActiveStart = Now()
	coupon.ActiveEnd = Now().AddDate(0, 0, int(req.ActiveDate))

	err = begin.Model(&Coupon{}).Where("erp_coupon_id = ?", req.ErpCouponId).
		Omit("created_at").Save(coupon).Error
	if err != nil {
		begin.Rollback()
		logger.Error("update coupon err:", logger.Field("err", err))
		return err
	}

	err = begin.Commit().Error
	if err != nil {
		begin.Rollback()
		logger.Error("commit update erp_coupon err:", logger.Field("err", err))
		return err
	}

	return nil
}

// DeleteErpMarketingCoupon 删除优惠券
func DeleteErpMarketingCoupon(req *ErpMarketingCouponDeleteReq) error {
	// 查询订单信息
	var erpCoupon ErpCoupon
	err := orm.Eloquent.Table("erp_coupon").Where("id=?", req.ErpCouponId).Find(&erpCoupon).Error
	if err != nil {
		logger.Error("purchase order err:", logger.Field("err", err))
		return err
	}

	if erpCoupon.ID == 0 {
		logger.Error("delete err, erpCoupon ID is:", logger.Field("erpCoupon.ID", req.ErpCouponId))
		return errors.New(fmt.Sprintf("删除失败:未查询到优惠券id[%d]", req.ErpCouponId))
	}

	// 仅未开始和已结束的订单可删除
	if erpCoupon.State != ErpCouponUnStarted && erpCoupon.State != ErpCouponFinished {
		logger.Error("delete err, erpCoupon.State is:", logger.Field("erpCoupon.State", erpCoupon.State))
		return errors.New("删除失败:仅未开始和已结束的优惠券可删除")
	}

	// 删除优惠订单
	begin := orm.Eloquent.Begin()
	err = begin.Delete(erpCoupon).Error
	if err != nil {
		begin.Rollback()
		logger.Error("erp_coupon delete err:", logger.Field("err", err))
		return err
	}

	err = begin.Table("coupon").Where("erp_coupon_id", req.ErpCouponId).Delete(&Coupon{}).Error
	if err != nil {
		begin.Rollback()
		logger.Error("coupon delete err:", logger.Field("err", err))
		return err
	}

	err = begin.Commit().Error
	if err != nil {
		begin.Rollback()
		logger.Error("commit erp_coupon delete err:", logger.Field("err", err))
		return err
	}

	return nil
}

// StartCouponIssuanceTask 启动发放优惠券的任务
func StartCouponIssuanceTask(req *ErpMarketingCouponStartReq, taskList []CouponIssuanceTask) error {
	var erpCouponList []ErpCoupon
	err := orm.Eloquent.Table("erp_coupon").Where("id in ?", req.ErpCouponId).Find(&erpCouponList).Error
	if err != nil {
		logger.Error("purchase order err:", logger.Field("err", err))
		return err
	}

	if len(taskList) < len(erpCouponList) {
		for _, erpCoupon := range erpCouponList {
			exitFlag := false
			for _, task := range taskList {
				if erpCoupon.ID == task.ErpCouponId {
					exitFlag = true
					break
				} else {
					continue
				}
			}

			if !exitFlag {
				// 新建任务
				taskInfo := CouponIssuanceTask{
					ErpCouponId:   erpCoupon.ID,
					ErpCouponName: erpCoupon.Name,
					Status:        TaskInProgress,
					LastUserID:    0,
					ErrorMessage:  "",
				}
				err := orm.Eloquent.Create(&taskInfo).Error
				if err != nil {
					logger.Error("create CouponIssuanceTask err:", logger.Field("err", err))
					return err
				}

				taskList = append(taskList, taskInfo)
			}
		}
	}

	// 遍历taskList，获取最小的lastUserID
	var lastUserID uint32
	for _, task := range taskList {
		if lastUserID == 0 {
			lastUserID = task.LastUserID
		}

		if lastUserID > task.LastUserID {
			lastUserID = task.LastUserID
		}
	}

	var nTotalCount int
	// 处理任务，从上次中断的用户ID开始
	for {
		// 查询用户ID大于 lastUserID 的用户
		users, err := getUsersAfterID(lastUserID, erpCouponList[0].UserType)
		if err != nil || len(users) == 0 {
			log.Println("没有更多用户，任务结束")
			break
		}

		// 发放优惠券
		count, err := issueCouponsToUsers(users, req.ErpCouponId)
		if err != nil {
			log.Printf("发放优惠券失败: %v", err)
			return err
		}

		// 更新任务进度：记录处理到的最后一个用户ID
		lastUserID = users[len(users)-1].ID
		nTotalCount += count
		//err = updateTaskProgress(req.ErpCouponId, lastUserID, err.Error())
		//if err != nil {
		//	log.Printf("更新任务进度失败: %v", err)
		//	break
		//}
	}

	// 任务完成，更新状态
	err = markTaskAsCompleted(req.ErpCouponId, nTotalCount)
	if err != nil {
		return nil
	}

	return nil
}

// CheckUserType 校验批量选择的优惠券使用人群是否相同
func CheckUserType(erpCouponId []uint32) bool {
	var erpCouponList []ErpCoupon
	err := orm.Eloquent.Table("erp_coupon").Where("id in ?", erpCouponId).Find(&erpCouponList).Error
	if err != nil || err == RecordNotFound {
		logger.Error("query erp_coupon err:", logger.Field("err", err))
		return false
	}

	var userType uint32
	for _, erpCoupon := range erpCouponList {
		if userType == 0 {
			userType = erpCoupon.UserType
		}

		if userType != erpCoupon.UserType {
			return false
		}
	}

	return true
}

// GetTaskProgress 查询优惠券任务执行情况
func GetTaskProgress(erpCouponId []uint32) ([]CouponIssuanceTask, error) {
	var task []CouponIssuanceTask
	err := orm.Eloquent.Table("coupon_issuance_task").Where("erp_coupon_id in ?", erpCouponId).
		Order("updated_at desc").First(&task).Error
	if err != nil && err.Error() != "record not found" {
		return nil, err
	}

	return task, nil
}

func getUsersAfterID(lastUserID, userType uint32) ([]UserInfo, error) {
	var err error
	var users []UserInfo
	// 获取尊享会员信息
	var privilegeUserList []PrivilegeMember

	switch userType {
	case 2: // 2-未付费用户：MemberLevel 不能是 (2, 3, 4, 5)，不包含已过期的租卡用户
		err = orm.Eloquent.Model(&UserInfo{}).Where("id > ? and member_level not in ? and member_expire = ?",
			lastUserID, []uint32{MemberLevelGold, MemberLevelPeriod, MemberLevelPlatinum, MemberLevelBlackGold},
			"0000-00-00 00:00:00").Order("id asc").Limit(100).Find(&users).Error

	case 3: // 3-已付费用户：MemberLevel 必须是 (2, 3, 4, 5)
		err = orm.Eloquent.Model(&UserInfo{}).Where("id > ? and member_level in ?", lastUserID, []uint32{
			MemberLevelGold, MemberLevelPeriod, MemberLevelPlatinum, MemberLevelBlackGold}).
			Order("id asc").Limit(100).Find(&users).Error

	case 4: // 尊享会员
		err = orm.Eloquent.Model(&PrivilegeMember{}).Where("id > ? and member_level = ?",
			lastUserID, MemberLevelPrivilege).Order("id asc").Limit(100).Find(&privilegeUserList).Error
		if err != nil {
			return nil, err
		}
		for _, privilegeUser := range privilegeUserList {
			user, _ := GetUserInfoByUid(privilegeUser.Uid)
			if user.ID == 0 { // 没查到数据
				user.Uid = privilegeUser.Uid
				user.Tel = privilegeUser.Tel
			}

			user.ID = privilegeUser.ID
			user.MemberLevel = MemberLevelPrivilege
			users = append(users, user)
		}

	case 5: // 测试用户
		if lastUserID == 0 {
			users, err = GetTestUserConfig()
			if err != nil {
				return nil, err
			}
		}

	case 1: // 1-所有人：不限制会员等级，所有人均可领取
		fallthrough
	default:
		err = orm.Eloquent.Model(&UserInfo{}).Where("id > ?", lastUserID).
			Order("id asc").Limit(100).Find(&users).Error
	}

	if err != nil {
		return nil, err
	}

	return users, nil
}

func updateTaskProgress(erpCouponId []uint32, lastUserID uint32, errMsg string) error {
	err := orm.Eloquent.Table("coupon_issuance_task").Where("erp_coupon_id in ?", erpCouponId).
		Updates(map[string]interface{}{
			"last_user_id":  lastUserID,
			"error_message": errMsg,
			"updated_at":    time.Now(),
		}).Error
	if err != nil {
		return err
	}
	return nil
}

func markTaskAsCompleted(erpCouponId []uint32, nTotalCount int) error {
	err := orm.Eloquent.Table("coupon_issuance_task").Where("erp_coupon_id in ?", erpCouponId).
		Updates(map[string]interface{}{
			"Status":     TaskCompleted,
			"updated_at": time.Now(),
		}).Error
	if err != nil {
		log.Printf("更新任务完成状态失败: %v", err)
		return err
	}

	err = orm.Eloquent.Table("erp_coupon").Where("id in ?", erpCouponId).
		Updates(map[string]interface{}{
			"state":      ErpCouponInProgress,
			"send_count": nTotalCount,
			"updated_at": time.Now(),
		}).Error
	if err != nil {
		log.Printf("更新任务完成状态失败: %v", err)
		return err
	}

	log.Println("任务完成")
	return nil
}

// 校验用户是否符合领取优惠券的条件
func isEligibleForCoupon(user UserInfo, erpCoupon ErpCoupon) bool {
	switch erpCoupon.UserType {
	case 1:
		// 1-所有人：不限制会员等级，所有人均可领取
		return true
	case 2:
		// 2-未付费用户：MemberLevel 不能是 (2, 3, 4, 5)
		if user.MemberLevel == MemberLevelGold ||
			user.MemberLevel == MemberLevelPeriod ||
			user.MemberLevel == MemberLevelPlatinum ||
			user.MemberLevel == MemberLevelBlackGold {
			return false
		}

		if IsValidPrivilegeMember(user.Uid) { // 如果是尊享会员
			return false
		}

		return true
	case 3:
		// 3-已付费用户：MemberLevel 必须是 (2, 3, 4, 5)
		if user.MemberLevel == MemberLevelGold ||
			user.MemberLevel == MemberLevelPeriod ||
			user.MemberLevel == MemberLevelPlatinum ||
			user.MemberLevel == MemberLevelBlackGold {
			return true
		}

		if IsValidPrivilegeMember(user.Uid) { // 如果是尊享会员
			return true
		}

		return false
	case 4: // 尊享会员
		if user.MemberLevel == MemberLevelPrivilege {
			return true
		}

		if IsValidPrivilegeMember(user.Uid) { // 如果是尊享会员
			return true
		}

		return false
	case 5: // 测试用户
		if user.MemberLevel == MemberLevelTest {
			return true
		}
		return false
	default:
		// 未知类型，不发放
		return false
	}
}

func issueCouponsToUsers(users []UserInfo, erpCouponId []uint32) (int, error) {
	var erpCoupon []ErpCoupon
	err := orm.Eloquent.Table("erp_coupon").Where("id in ?", erpCouponId).Find(&erpCoupon).Error
	if err != nil || err == RecordNotFound {
		logger.Error("query erp_coupon err:", logger.Field("err", err))
		return 0, err
	}

	var nSendCount int
	for _, user := range users {
		// 根据条件发放优惠券
		if isEligibleForCoupon(user, erpCoupon[0]) {
			// 发放优惠券
			var coupons []Coupon
			err = orm.Eloquent.Table("coupon").Where("erp_coupon_id in ?", erpCouponId).Find(&coupons).Error
			if err != nil {
				logger.Error("query coupon err:", logger.Field("err", err))
				return 0, err
			}

			for _, coupon := range coupons {
				duration := coupon.ActiveEnd.Sub(coupon.ActiveStart).Hours() / 24
				couponCode, _ := utils.GenerateRandomNumber19()
				userCoupon := &UserCoupon{
					Uid:            user.Uid,
					CouponId:       coupon.ID,
					CouponType:     coupon.CouponType,
					Value:          coupon.Value,
					State:          1,
					ActiveStart:    time.Now(),
					ActiveEnd:      time.Now().Add(time.Duration(duration) * 24 * time.Hour),
					RedeemCode:     "",
					CategoryNumber: coupon.CategoryNumber,
					Code:           couponCode,
					ActivityType:   coupon.ActivityType,
					Limit:          coupon.Limit,
				}

				err = orm.Eloquent.Create(userCoupon).Error
				if err != nil {
					logger.Error("create user coupon err:", logger.Field("err", err))
					err = updateTaskProgress(erpCouponId, user.ID, err.Error())
					if err != nil {
						log.Printf("更新任务进度失败: %v", err)
					}
					return 0, err
				}
			}

			// 发送订阅通知
			var wxToken WxAccessToken
			err = orm.Eloquent.Table("wx_access_token").Where("appid = ?", WXAppID).First(&wxToken).Error
			if err != nil {
				logger.Error("query wx_access_token err:", logger.Field("err", err))
			}

			if wxToken.ID == 0 || wxToken.ExpiresTime.Before(time.Now()) {
				CheckAccessToken()

				err = orm.Eloquent.Table("wx_access_token").Where("appid = ?", WXAppID).First(&wxToken).Error
				if err != nil {
					logger.Error("query wx_access_token err:", logger.Field("err", err))
				}
			}

			toUserOpenid := user.WxOpenID
			templateId := TemplateId
			data := map[string]interface{}{
				"thing1": map[string]interface{}{"value": coupons[0].Name},
				"thing5": map[string]interface{}{"value": coupons[0].Describe},
				"date3":  map[string]interface{}{"value": coupons[0].ActiveEnd.Format("2006年01月02日")},
				"thing4": map[string]interface{}{"value": coupons[0].Rule},
			}
			//developer为开发版；trial为体验版；formal为正式版；默认为正式版
			miniProgramState := config.MessageConfig.MiniProgramState
			_, err = SendMessage(wxToken.AccessToken, toUserOpenid, templateId, data, WxJumpUrl, miniProgramState)
			if err != nil {
				logger.Errorf("SendMessage err:", err)
				// 如果订阅通知发送失败，则发送短信
				err = GtSendMessage([]string{user.Tel}, ComposeSMSContent(erpCoupon[0].SmsContent))
				if err != nil {
					logger.Error(err.Error())
				}
			}

			nSendCount++
		}
	}
	return nSendCount, nil
}

func ComposeSMSContent(content string) string {
	// 1. 判断短信内容开头是否有【明慧科技】，没有的话添加上
	if !strings.HasPrefix(content, SMSHead) {
		content = SMSHead + content
	}

	// 2. 判断短信内容中是否有 http 开头的链接，没有的话在最后加上
	if !strings.Contains(content, "http") {
		content += " 详情请点击：" + config.MessageConfig.SmsUrl
	}

	return content
}

// Response 请求微信返回基础数据
type Response struct {
	Errcode int    `json:"errcode"`
	Errmsg  string `json:"errmsg"`
}

// AccessTokenResponse 返回给用户的数据
type AccessTokenResponse struct {
	AccessToken string `json:"access_token"` // 获取到的凭证
	ExpiresIn   int64  `json:"expires_in"`   // 凭证有效时间，单位：秒。目前是7200秒之内的值。
}

type accessTokenResponse struct {
	Response
	AccessTokenResponse
}

// CheckAccessToken 定期更新access_token
func CheckAccessToken() {
	accessToken, err := GetWxAccessToken()
	if err != nil {
		logger.Error("query wx_access_token err:", logger.Field("err", err))
	} else {
		now := time.Now()
		twoHoursLater := now.Add(2 * time.Hour)

		// 查询access_token
		var wxToken WxAccessToken
		err = orm.Eloquent.Table("wx_access_token").Where("appid = ?", WXAppID).First(&wxToken).Error
		if err != nil {
			logger.Error("query wx_access_token err:", logger.Field("err", err))
		}

		if wxToken.ID != 0 { // 更新
			// 更新access_token
			err = orm.Eloquent.Table("wx_access_token").Where("appid = ?", WXAppID).
				Updates(map[string]interface{}{
					"access_token": accessToken.AccessToken,
					"expires_time": twoHoursLater,
				}).Error
			if err != nil {
				logger.Errorf("更新wx_access_token失败: %v", err)
			}
		} else { // 插入
			tempToken := &WxAccessToken{
				Appid:       WXAppID,
				AccessToken: accessToken.AccessToken,
				ExpiresTime: twoHoursLater,
			}
			err = orm.Eloquent.Create(tempToken).Error
			if err != nil {
				logger.Error("create wx_access_token err:", logger.Field("err", err))
			}
		}
	}
}

// GetWxAccessToken 获取小程序的access_token
func GetWxAccessToken() (lures AccessTokenResponse, err error) {
	api, err := code2url(WXAppID, WXSecret)
	if err != nil {
		return
	}

	res, err := http.Get(api)
	if err != nil {
		return
	}
	defer res.Body.Close()

	if res.StatusCode != 200 {
		err = errors.New("微信服务器发生错误")
		return
	}

	var data accessTokenResponse
	err = json.NewDecoder(res.Body).Decode(&data)
	if err != nil {
		return
	}

	if data.Errcode != 0 {
		err = errors.New(data.Errmsg)
		return
	}

	lures = data.AccessTokenResponse
	return
}

// 拼接 获取 session_key 的 URL
func code2url(appID, secret string) (string, error) {
	url, err := url.Parse(AccessTokenUrl)
	if err != nil {
		return "", err
	}

	query := url.Query()

	query.Set("appid", appID)
	query.Set("secret", secret)
	query.Set("grant_type", "client_credential")

	url.RawQuery = query.Encode()

	return url.String(), nil
}

// SendMessageReq 消息订阅请求参数
type SendMessageReq struct {
	TemplateId       string      `json:"template_id"`
	Page             string      `json:"page"`
	Touser           string      `json:"touser"`
	Data             interface{} `json:"data"`
	MiniprogramState string      `json:"miniprogram_state"`
	Lang             string      `json:"lang"`
}

// SendMessage 发送订阅消息
func SendMessage(accessToken, toUserOpenid, templateId string, data interface{}, page, miniProgramState string) (
	sendMessageRsp *Response, err error) {
	url := fmt.Sprintf("%s%s", WxSubscribeMessage, accessToken)

	body := SendMessageReq{
		TemplateId:       templateId,
		Page:             page,
		Touser:           toUserOpenid,
		Data:             data,
		MiniprogramState: miniProgramState,
		Lang:             "zh_CN",
	}

	respRaw, err := HttpRequest(http.MethodPost, url, body)

	rsp := Response{}

	if err = json.Unmarshal(respRaw, &rsp); err != nil {
		return nil, err
	}
	if rsp.Errcode != 0 {
		return nil, errors.New(rsp.Errmsg)
	}
	return &rsp, err
}

func HttpRequest(method, url string, reqBody interface{}) ([]byte, error) {
	client := http.Client{}
	reqBodyBytes, err := json.Marshal(reqBody)
	if err != nil {
		return nil, err
	}
	reqBodyReader := bytes.NewReader(reqBodyBytes)
	req, err := http.NewRequest(method, url, reqBodyReader)
	if err != nil {
		return nil, err
	}

	rsp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer rsp.Body.Close()
	if rsp.StatusCode != 200 {
		return nil, errors.New(fmt.Sprintf("response Status err:%d", rsp.StatusCode))
	}
	rspBody, err := ioutil.ReadAll(rsp.Body)
	if err != nil {
		return nil, err
	}
	return rspBody, nil
}

// GetUserCouponIdsByErpCouponId 通过erp的优惠券id查找用户的优惠券id列表
func GetUserCouponIdsByErpCouponId(erpCouponId uint32) ([]uint32, error) {
	// 先查询 Coupon 表，根据 ErpCouponId 获取 coupon_id
	var coupon Coupon
	err := orm.Eloquent.Where("erp_coupon_id = ?", erpCouponId).First(&coupon).Error
	if err != nil {
		// 如果未找到对应优惠券ID，返回错误
		return nil, fmt.Errorf("优惠券ID不存在或查询失败")
	}

	// 使用 coupon_id 查找 UserCoupon 表中的记录，获取所有符合条件的记录
	var userCoupons []UserCoupon
	err = orm.Eloquent.Where("coupon_id = ?", coupon.ID).Find(&userCoupons).Error
	if err != nil {
		// 如果查询失败，返回错误
		return nil, fmt.Errorf("查询 UserCoupon 记录失败")
	}

	// 提取所有找到的 userCoupon 的 ID
	var userCouponIds []uint32
	for _, userCoupon := range userCoupons {
		userCouponIds = append(userCouponIds, userCoupon.ID)
	}

	// 返回所有 UserCoupon ID
	return userCouponIds, nil
}

// WXGenerateScheme 获取小程序跳转链接
func WXGenerateScheme(req *GenerateSchemeReq) (*GenerateSchemeResp, error) {
	var rsp WXGenerateSchemeResponse

	var wxToken WxAccessToken
	err := orm.Eloquent.Table("wx_access_token").Where("appid = ?", WXAppID).First(&wxToken).Error
	if err != nil {
		logger.Error("query wx_access_token err:", logger.Field("err", err))
	}

	if wxToken.ID == 0 || wxToken.ExpiresTime.Before(time.Now()) {
		CheckAccessToken()

		err = orm.Eloquent.Table("wx_access_token").Where("appid = ?", WXAppID).First(&wxToken).Error
		if err != nil {
			logger.Error("query wx_access_token err:", logger.Field("err", err))
		}
	}

	url := WXGenerateSchema + wxToken.AccessToken
	/*
		{
		    "jump_wxa": {
		        "path": "/pages/startPage/index",
		        "query": "",
		        "env_version": "release"

		    },
		    "expire_type": 1,
		    "expire_interval": 30
		}
	*/
	reqScheme := map[string]interface{}{
		"jump_wxa": map[string]string{
			"path":        req.Path,
			"env_version": req.EnvVersion,
		},
		"expire_type":     1,  //小程序 URL Link 失效类型，时间戳：0，间隔天数：1
		"expire_interval": 30, //最长间隔天数为30天。expire_type 为 1 必填
	}

	data, err := HttpRequest(http.MethodPost, url, reqScheme)
	/*
		{
		    "errcode": 0, //成功返回
		    "errmsg": "ok",
		    "url_link": "https://wxaurl.cn/pjKMfcQsULj"
		}
	*/
	if err = json.Unmarshal(data, &rsp); err != nil {
		return nil, err
	}
	if rsp.Errcode != 0 {
		return nil, errors.New(fmt.Sprintf("生成小程序跳转链接失败：errcode %d,errmsg %s", rsp.Errcode, rsp.Errmsg))
	}

	resp := GenerateSchemeResp{
		Openlink: rsp.Openlink,
	}
	return &resp, nil
}

// UpdateErpCouponState 每天凌晨00:45更新营销管理优惠券发放状态
func UpdateErpCouponState() {
	now := time.Now()

	// 更新符合条件的优惠券的状态
	err := orm.Eloquent.Table("erp_coupon").
		Where("state = ? AND start_time IS NOT NULL AND DATE_ADD(start_time, INTERVAL active_date DAY) < ?", 3, now).
		Updates(map[string]interface{}{
			"state":      4,
			"updated_at": now,
		}).Error

	if err != nil {
		logger.Errorf("Failed to update ErpCoupon state: %v", err)
		return
	}

	logger.Info("Successfully updated ErpCoupon state")
}

// UpdateUserCoupon 每天凌晨00:30更新用户优惠券
func UpdateUserCoupon() {
	now := time.Now()
	// 直接更新过期的优惠券状态
	err := orm.Eloquent.Table("user_coupon").Where("state = ? AND active_end < ?", 1, now).
		Updates(map[string]interface{}{
			"state":      3,
			"updated_at": now,
		}).Error
	if err != nil {
		logger.Errorf("Failed to update expired user coupons: %v", err)
		return
	}
	logger.Info("Successfully updated expired user coupons")
}
