package svc

import (
	"applet/app/db"
	"applet/app/db/model"
	"applet/app/e"
	"applet/app/enum"
	"applet/app/md"
	"applet/app/utils"
	"applet/app/utils/cache"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/shopspring/decimal"
	"time"
	"xorm.io/xorm"
)

func OrderCate(c *gin.Context) {
	var cate = []map[string]string{
		{"name": "全部", "value": ""},
		{"name": "待付款", "value": "0"},
		{"name": "待提货", "value": "1"},
		{"name": "已完成", "value": "2"},
		{"name": "已取消", "value": "3"},
	}
	e.OutSuc(c, cate, nil)
	return
}
func OrderList(c *gin.Context) {
	var arg map[string]string
	if err := c.ShouldBindJSON(&arg); err != nil {
		e.OutErr(c, e.ERR_INVALID_ARGS, err)
		return
	}
	user := GetUser(c)
	arg["uid"] = utils.IntToStr(user.Info.Uid)
	data := db.GetOrderList(c, MasterDb(c), arg)
	var state = []string{"待付款", "待提货", "已完成", "已取消"}
	list := make([]map[string]interface{}, 0)
	scheme, host := ImageBucket(c)

	if data != nil {
		now := time.Now().Unix()
		for _, v := range *data {
			store := db.GetStoreIdEg(MasterDb(c), utils.IntToStr(v.StoreUid))
			info := db.GetOrderInfoAllEg(MasterDb(c), utils.Int64ToStr(v.Oid))
			goodsInfo := make([]map[string]string, 0)
			if info != nil {
				for _, v1 := range *info {
					tmp := map[string]string{
						"img":     ImageFormatWithBucket(scheme, host, v1.Img),
						"title":   v1.Title,
						"sku_str": "",
					}
					skuData := make([]md.Sku, 0)
					json.Unmarshal([]byte(v1.SkuInfo), &skuData)
					skuStr := ""
					for _, v2 := range skuData {
						if skuStr != "" {
							skuStr += ";"
						}
						skuStr += v2.Value
					}
					tmp["sku_str"] = skuStr
					goodsInfo = append(goodsInfo, tmp)
				}
			}
			downTime := "0"
			if v.State == 0 {
				downTime = utils.IntToStr(int(v.CreateAt.Unix() + 15*60 - now))
				if now > v.CreateAt.Unix()+15*60 {
					v.State = 3
				}
				if utils.StrToInt(downTime) < 0 {
					downTime = "0"
				}
			}
			storeName := ""
			if store != nil {
				storeName = store.Name
			}
			tmp := map[string]interface{}{
				"oid":        utils.Int64ToStr(v.Oid),
				"label":      "自提",
				"state":      utils.IntToStr(v.State),
				"state_str":  state[v.State],
				"store_name": storeName,
				"goods_info": goodsInfo,
				"amount":     v.Amount,
				"table_num":  v.TableNum,
				"num":        utils.IntToStr(v.Num),
				"timer":      "",
				"code":       v.Code,
				"down_time":  downTime,
			}
			if v.Type == 1 {
				tmp["label"] = "外卖"
			}
			if v.IsNow == 1 {
				tmp["timer"] = "立即提货"
			} else if v.Timer != "" {
				tmp["timer"] = "提货时间:" + v.Timer
			}
			list = append(list, tmp)
		}
	}
	e.OutSuc(c, list, nil)
	return
}
func OrderDetail(c *gin.Context) {
	var arg map[string]string
	if err := c.ShouldBindJSON(&arg); err != nil {
		e.OutErr(c, e.ERR_INVALID_ARGS, err)
		return
	}
	data := db.GetOrderEg(MasterDb(c), arg["oid"])
	var state = []string{"待付款", "待提货", "已完成", "已取消"}
	now := time.Now().Unix()
	store := db.GetStoreIdEg(MasterDb(c), utils.IntToStr(data.StoreUid))
	downTime := "0"
	if data.State == 0 {
		downTime = utils.IntToStr(int(data.CreateAt.Unix() + 15*60 - now))
		if now > data.CreateAt.Unix()+15*60 {
			data.State = 3
		}
		if utils.StrToInt(downTime) < 0 {
			downTime = "0"
		}
	}
	storeName := ""
	storeAddress := ""
	lat := ""
	lng := ""
	km := ""
	if store != nil {
		storeName = store.Name
		storeAddress = store.Address
		lat = store.Lat
		lng = store.Lng
		km = ""
		if arg["lat"] != "" && arg["lng"] != "" {
			km1 := utils.CalculateDistance(utils.StrToFloat64(lat), utils.StrToFloat64(lng), utils.StrToFloat64(arg["lat"]), utils.StrToFloat64(arg["lng"]))
			if km1 < 1 {
				km = utils.Float64ToStr(km1*1000) + "m"
			} else {
				km = utils.Float64ToStr(km1) + "km"
			}
		}
	}
	confirmAt := ""
	if data.ConfirmAt.IsZero() == false {
		confirmAt = data.ConfirmAt.Format("2006-01-02 15:04:05")
	}
	payMethod := "-"
	if data.PayMethod > 0 {
		payMethod = md.PayMethodIdToName[data.PayMethod]
	}
	orderInfo := []map[string]string{
		{"title": "订单编号", "content": utils.Int64ToStr(data.Oid)},
		{"title": "下单时间", "content": data.CreateAt.Format("2006-01-02 15:04:05")},
		{"title": "提货时间", "content": confirmAt},
		{"title": "预留电话", "content": data.Phone},
		{"title": "支付方式", "content": payMethod},
		{"title": "备注信息", "content": data.Memo},
	}
	goodsInfo := make([]map[string]string, 0)
	info := db.GetOrderInfoAllEg(MasterDb(c), utils.Int64ToStr(data.Oid))
	if info != nil {
		scheme, host := ImageBucket(c)

		for _, v := range *info {
			tmp := map[string]string{
				"img":     ImageFormatWithBucket(scheme, host, v.Img),
				"title":   v.Title,
				"price":   v.Price,
				"num":     utils.IntToStr(v.Num),
				"sku_str": "",
			}
			skuData := make([]md.Sku, 0)
			json.Unmarshal([]byte(v.SkuInfo), &skuData)
			skuStr := ""
			for _, v1 := range skuData {
				if skuStr != "" {
					skuStr += ";"
				}
				skuStr += v1.Value
			}
			tmp["sku_str"] = skuStr
			goodsInfo = append(goodsInfo, tmp)
		}
	}
	tmp := map[string]interface{}{
		"oid":           utils.Int64ToStr(data.Oid),
		"label":         "自提",
		"state":         utils.IntToStr(data.State),
		"state_str":     state[data.State],
		"store_name":    storeName,
		"store_address": storeAddress,
		"lat":           lat,
		"lng":           lng,
		"km":            km,
		"amount":        data.Amount,
		"num":           utils.IntToStr(data.Num),
		"table_num":     data.TableNum,
		"timer":         "",
		"code":          data.Code,
		"down_time":     downTime,
		"order_info":    orderInfo,
		"goods_info":    goodsInfo,
		"goods_count":   utils.IntToStr(len(goodsInfo)),
	}
	if data.Type == 1 {
		tmp["label"] = "外卖"
	}
	if data.IsNow == 1 {
		tmp["timer"] = "立即提货"
	} else if data.Timer != "" {
		tmp["timer"] = data.Timer
	}
	e.OutSuc(c, tmp, nil)
	return
}
func OrderCoupon(c *gin.Context) {
	var arg md.OrderTotal
	if err := c.ShouldBindJSON(&arg); err != nil {
		e.OutErr(c, e.ERR_INVALID_ARGS, err)
		return
	}
	totalPrice := commGoods(c, arg)
	returnData := CommCoupon(c, totalPrice)
	e.OutSuc(c, returnData, nil)
	return
}
func CommCoupon(c *gin.Context, totalPrice string) map[string]interface{} {
	couponList := make([]md.CouponList, 0)
	storeId := GetStoreId(c)

	if utils.StrToInt(storeId) > 0 {
		storeData := db.GetStoreIdEg(MasterDb(c), storeId)
		if storeData != nil && storeData.StoreType > 0 {
			returnData := map[string]interface{}{
				"total":       "0",
				"coupon_list": couponList,
			}
			return returnData
		}
	}
	var err error
	engine := MasterDb(c)
	user := GetUser(c)
	now := time.Now().Format("2006-01-02 15:04:05")
	var ActCouponUserList []*model.CommunityTeamCouponUser
	sess := engine.
		Where("store_type=? and uid = ? AND is_use = ? AND (valid_time_start < ? AND valid_time_end > ?)", 0,
			user.Info.Uid, 1, now, now)
	err = sess.Limit(100).OrderBy("valid_time_end asc,id asc").Find(&ActCouponUserList)
	if err != nil {
		return map[string]interface{}{}
	}
	var ids = make([]int, 0)
	for _, v := range ActCouponUserList {
		ids = append(ids, v.MerchantSchemeId)
	}
	var merchantScheme []model.CommunityTeamCoupon
	engine.In("id", ids).Find(&merchantScheme)
	var merchantSchemeMap = make(map[int]model.CommunityTeamCoupon)
	for _, v := range merchantScheme {
		merchantSchemeMap[v.Id] = v
	}

	notCouponList := make([]md.CouponList, 0)
	count := 0
	for _, item := range ActCouponUserList {
		var coupon = md.CouponList{
			Id:        utils.Int64ToStr(item.Id),
			Title:     item.Name,
			Timer:     item.ValidTimeStart.Format("2006.01.02") + "-" + item.ValidTimeEnd.Format("2006.01.02"),
			Label:     "全部商品可用",
			Img:       item.Img,
			Content:   item.Info,
			Info:      item.Info,
			IsCanUse:  "0",
			NotUseStr: "",
		}
		var cal struct {
			Reach  string `json:"reach"`
			Reduce string `json:"reduce"`
		}
		err = json.Unmarshal([]byte(item.Cal), &cal)
		if err != nil {
			return map[string]interface{}{}
		}
		switch item.Kind {
		case int(enum.ActCouponTypeImmediate):
			if utils.AnyToFloat64(totalPrice) >= utils.AnyToFloat64(cal.Reduce) {
				coupon.IsCanUse = "1"
			}
		case int(enum.ActCouponTypeReachReduce):
			if utils.AnyToFloat64(totalPrice) >= utils.AnyToFloat64(cal.Reduce) {
				coupon.IsCanUse = "1"
			}
		case int(enum.ActCouponTypeReachDiscount):
			if utils.AnyToFloat64(totalPrice) >= utils.AnyToFloat64(cal.Reduce) && utils.AnyToFloat64(cal.Reduce) > 0 {
				coupon.IsCanUse = "1"
			}
			if utils.AnyToFloat64(cal.Reduce) == 0 {
				coupon.IsCanUse = "1"
			}
		}
		if coupon.IsCanUse != "1" {
			coupon.NotUseStr = "订单金额未满" + cal.Reduce + "元"
		}
		if coupon.IsCanUse == "1" {
			count++
			couponList = append(couponList, coupon)
		} else {
			notCouponList = append(notCouponList, coupon)
		}
	}
	for _, v := range notCouponList {
		couponList = append(couponList, v)
	}
	returnData := map[string]interface{}{
		"total":       utils.IntToStr(count),
		"coupon_list": couponList,
	}

	return returnData
}
func OrderCancel(c *gin.Context) {
	var arg map[string]string
	if err := c.ShouldBindJSON(&arg); err != nil {
		e.OutErr(c, e.ERR_INVALID_ARGS, err)
		return
	}
	// 加锁 防止并发提取
	mutexKey := fmt.Sprintf("%s:team.OrderCancel:%s", c.GetString("mid"), arg["oid"])
	withdrawAvailable, err := cache.Do("SET", mutexKey, 1, "EX", 5, "NX")
	if err != nil {
		e.OutErr(c, e.ERR, err)
		return
	}
	if withdrawAvailable != "OK" {
		e.OutErr(c, e.ERR, e.NewErr(400000, "请求过于频繁，请稍后再试"))
		return
	}
	sess := MasterDb(c).NewSession()
	defer sess.Close()
	sess.Begin()
	order := db.GetOrder(sess, arg["oid"])
	if order == nil {
		sess.Rollback()
		e.OutErr(c, 400, e.NewErr(400, "订单不存在"))
		return
	}
	if order.State == 0 {
		now := time.Now().Unix()
		if now > order.CreateAt.Unix()+15*60 {
			order.State = 3
		}
	}
	if order.State > 0 {
		sess.Rollback()
		e.OutErr(c, 400, e.NewErr(400, "订单不能取消"))
		return
	}
	orderInfo := db.GetOrderInfo(sess, arg["oid"])
	if orderInfo != nil {
		goodsMap := make(map[int]int)
		skuMap := make(map[int]int)
		for _, v := range *orderInfo {
			goodsMap[v.GoodsId] += v.Num
			skuMap[v.SkuId] += v.Num
		}
		for k, v := range goodsMap {
			sql := `update community_team_goods set stock=stock+%d where id=%d`
			sql = fmt.Sprintf(sql, v, k)
			_, err := db.QueryNativeStringWithSess(sess, sql)
			if err != nil {
				sess.Rollback()
				e.OutErr(c, 400, e.NewErr(400, "订单取消失败"))
				return
			}
		}
		for k, v := range skuMap {
			sql := `update community_team_sku set stock=stock+%d where sku_id=%d`
			sql = fmt.Sprintf(sql, v, k)
			_, err := db.QueryNativeStringWithSess(sess, sql)
			if err != nil {
				sess.Rollback()
				e.OutErr(c, 400, e.NewErr(400, "订单取消失败"))
				return
			}
		}
	}
	order.State = 3
	order.UpdateAt = time.Now()
	order.CancelAt = time.Now()
	update, err := sess.Where("id=?", order.Id).Cols("state,update_at,cancel_at").Update(order)
	if update == 0 || err != nil {
		sess.Rollback()
		e.OutErr(c, 400, e.NewErr(400, "订单取消失败"))
		return
	}
	if order.CouponId > 0 {
		update, err = sess.Where("id=?", order.CouponId).Cols("is_use").Update(&model.CommunityTeamCouponUser{IsUse: 0})
		if update == 0 || err != nil {
			sess.Rollback()
			e.OutErr(c, 400, e.NewErr(400, "订单取消失败"))
			return
		}
	}
	sess.Commit()
	e.OutSuc(c, "success", nil)
	return
}
func OrderConfirm(c *gin.Context) {
	var arg map[string]string
	if err := c.ShouldBindJSON(&arg); err != nil {
		e.OutErr(c, e.ERR_INVALID_ARGS, err)
		return
	}
	// 加锁 防止并发提取
	mutexKey := fmt.Sprintf("%s:team.OrderConfirm:%s", c.GetString("mid"), arg["oid"])
	withdrawAvailable, err := cache.Do("SET", mutexKey, 1, "EX", 5, "NX")
	if err != nil {
		e.OutErr(c, e.ERR, err)
		return
	}
	if withdrawAvailable != "OK" {
		e.OutErr(c, e.ERR, e.NewErr(400000, "请求过于频繁，请稍后再试"))
		return
	}
	sess := MasterDb(c).NewSession()
	defer sess.Close()
	sess.Begin()
	order := db.GetOrder(sess, arg["oid"])
	if order == nil {
		sess.Rollback()
		e.OutErr(c, 400, e.NewErr(400, "订单不存在"))
		return
	}
	if order.State != 1 {
		sess.Rollback()
		e.OutErr(c, 400, e.NewErr(400, "订单不能确认收货"))
		return
	}
	order.State = 2
	order.UpdateAt = time.Now()
	order.ConfirmAt = time.Now()
	order.StoreSettleAt = int(time.Now().Unix())
	update, err := sess.Where("id=?", order.Id).Cols("state,confirm_at,update_at").Update(order)
	if update == 0 || err != nil {
		sess.Rollback()
		e.OutErr(c, 400, e.NewErr(400, "订单确认失败"))
		return
	}
	money := utils.StrToFloat64(order.Commission)
	if order.ParentUid > 0 {
		money = utils.StrToFloat64(order.Amount) - utils.StrToFloat64(order.AgentCommission)
	}
	if order.StoreType == 1 {
		money = utils.StrToFloat64(order.Amount) - utils.StrToFloat64(order.PlatformCommission)
	}
	bools := MoneyCheck(c, sess, order.StoreUid, order.ParentUid, order.StoreType, 0, 1, money, "订单核销", order.Oid)
	if bools == false {
		sess.Rollback()
		e.OutErr(c, 400, e.NewErr(400, "订单确认失败"))
		return
	}
	sess.Commit()
	e.OutSuc(c, "success", nil)
	return
}
func PayOrderList(c *gin.Context) {
	var arg map[string]string
	if err := c.ShouldBindJSON(&arg); err != nil {
		e.OutErr(c, e.ERR_INVALID_ARGS, err)
		return
	}
	sql := `select ctpo.pay_at,ctpo.oid,cts.name,ctpo.amount from community_team_pay_order ctpo 
		LEFT JOIN community_team_store cts on cts.uid=ctpo.store_uid
		where ctpo.uid=%d and ctpo.state=1 order by ctpo.pay_at desc %s`
	size := 10
	start := (utils.StrToInt(arg["p"]) - 1) * size
	user := GetUser(c)
	sql = fmt.Sprintf(sql, user.Info.Uid, "limit "+utils.IntToStr(start)+","+utils.IntToStr(size))
	nativeString, _ := db.QueryNativeString(MasterDb(c), sql)
	list := make([]map[string]string, 0)
	for _, v := range nativeString {
		tmp := map[string]string{
			"time":   v["pay_at"],
			"name":   v["name"],
			"amount": v["amount"],
			"oid":    v["oid"],
		}
		list = append(list, tmp)
	}
	e.OutSuc(c, list, nil)
	return
}
func PayOrderCreate(c *gin.Context) {
	var arg map[string]string
	if err := c.ShouldBindJSON(&arg); err != nil {
		e.OutErr(c, e.ERR_INVALID_ARGS, err)
		return
	}
	user := GetUser(c)
	if utils.StrToFloat64(arg["amount"]) <= 0 {
		e.OutErr(c, e.ERR, e.NewErr(400000, "金额不正确"))
		return
	}
	// 加锁 防止并发提取
	mutexKey := fmt.Sprintf("%s:team.OrderCreate:%s", c.GetString("mid"), utils.IntToStr(user.Info.Uid))
	withdrawAvailable, err := cache.Do("SET", mutexKey, 1, "EX", 5, "NX")
	if err != nil {
		e.OutErr(c, e.ERR, err)
		return
	}
	if withdrawAvailable != "OK" {
		e.OutErr(c, e.ERR, e.NewErr(400000, "请求过于频繁，请稍后再试"))
		return
	}
	sess := MasterDb(c).NewSession()
	defer sess.Close()
	err = sess.Begin()
	if err != nil {
		e.OutErr(c, 400, err.Error())
		return
	}
	ordId := utils.OrderUUID(user.Info.Uid)
	// 获取店铺信息
	store := db.GetStoreId(sess, arg["store_id"])
	totalPrice := arg["amount"]
	var order = &model.CommunityTeamPayOrder{
		Uid:        user.Info.Uid,
		StoreUid:   utils.StrToInt(arg["store_id"]),
		Commission: utils.Float64ToStr(utils.FloatFormat(utils.AnyToFloat64(totalPrice)*(utils.AnyToFloat64(store.Commission)/100), 2)),
		CreateAt:   time.Now(),
		UpdateAt:   time.Now(),
		Oid:        utils.StrToInt64(ordId),
		Amount:     totalPrice,
	}
	if store.ParentUid > 0 { //代理下门店
		order.StoreType = 2
		order.Commission = "0"
		order.ParentUid = store.ParentUid
		order.AgentCommission = utils.Float64ToStr(utils.FloatFormat(utils.AnyToFloat64(totalPrice)*(utils.AnyToFloat64(store.AgentCommission)/100), 2))
	}
	if store.StoreType == 1 {
		order.StoreType = 1
		order.Commission = "0"
		order.PlatformCommission = utils.Float64ToStr(utils.FloatFormat(utils.AnyToFloat64(totalPrice)*(utils.AnyToFloat64(store.PlatformCommission)/100), 2))
	}
	insert, err := sess.Insert(order)
	if insert == 0 || err != nil {
		sess.Rollback()
		e.OutErr(c, 400, e.NewErr(400, "下单失败"))
		return
	}
	err = sess.Commit()
	if err != nil {
		sess.Rollback()
		e.OutErr(c, 400, err.Error())
		return
	}
	sess.Commit()
	e.OutSuc(c, map[string]string{"oid": ordId}, nil)
	return
}
func OrderCreate(c *gin.Context) {
	var arg md.OrderTotal
	if err := c.ShouldBindJSON(&arg); err != nil {
		e.OutErr(c, e.ERR_INVALID_ARGS, err)
		return
	}
	user := GetUser(c)
	// 加锁 防止并发提取
	mutexKey := fmt.Sprintf("%s:team.OrderCreate:%s", c.GetString("mid"), utils.IntToStr(user.Info.Uid))
	withdrawAvailable, err := cache.Do("SET", mutexKey, 1, "EX", 5, "NX")
	if err != nil {
		e.OutErr(c, e.ERR, err)
		return
	}
	if withdrawAvailable != "OK" {
		e.OutErr(c, e.ERR, e.NewErr(400000, "请求过于频繁，请稍后再试"))
		return
	}
	sess := MasterDb(c).NewSession()
	defer sess.Close()
	err = sess.Begin()
	if err != nil {
		e.OutErr(c, 400, err.Error())
		return
	}
	totalPrice := commGoods(c, arg)
	coupon := "0"
	totalPrice, coupon, err = CouponProcess(c, sess, totalPrice, arg)
	if err != nil {
		sess.Rollback()
		e.OutErr(c, 400, err.Error())
		return
	}
	ordId := utils.OrderUUID(user.Info.Uid)
	// 获取店铺信息
	store := db.GetStoreId(sess, arg.StoreId)
	num := 0
	for _, item := range arg.GoodsInfo {
		num += utils.StrToInt(item.Num)
	}
	var order = &model.CommunityTeamOrder{
		Uid:        user.Info.Uid,
		StoreUid:   utils.StrToInt(arg.StoreId),
		Commission: utils.Float64ToStr(utils.FloatFormat(utils.AnyToFloat64(totalPrice)*(utils.AnyToFloat64(store.Commission)/100), 2)),
		CreateAt:   time.Now(),
		UpdateAt:   time.Now(),
		BuyPhone:   arg.BuyPhone,
		Coupon:     coupon,
		Num:        num,
		IsNow:      utils.StrToInt(arg.IsNow),
		Timer:      arg.Timer,
		Memo:       arg.Memo,
		Oid:        utils.StrToInt64(ordId),
		Amount:     totalPrice,
		MealNum:    utils.StrToInt(arg.MealNum),
		TableNum:   arg.TableNum,
	}
	if store.ParentUid > 0 { //代理下门店
		order.StoreType = 2
		order.Commission = "0"
		order.ParentUid = store.ParentUid
		order.AgentCommission = utils.Float64ToStr(utils.FloatFormat(utils.AnyToFloat64(totalPrice)*(utils.AnyToFloat64(store.AgentCommission)/100), 2))
	}
	if store.StoreType == 1 {
		order.StoreType = 1
		order.Commission = "0"
		order.PlatformCommission = utils.Float64ToStr(utils.FloatFormat(utils.AnyToFloat64(totalPrice)*(utils.AnyToFloat64(store.PlatformCommission)/100), 2))
	}
	if utils.StrToFloat64(coupon) > 0 {
		order.CouponId = utils.StrToInt(arg.CouponId)
	}
	insert, err := sess.Insert(order)
	if insert == 0 || err != nil {
		sess.Rollback()
		e.OutErr(c, 400, e.NewErr(400, "下单失败"))
		return
	}
	for _, item := range arg.GoodsInfo {
		// 获取详细信息
		goodsInterface, has, err := db.GetComm(MasterDb(c), &model.CommunityTeamGoods{Id: utils.StrToInt(item.GoodsId)})
		if err != nil || !has {
			sess.Rollback()
			e.OutErr(c, 400, e.NewErr(400, "商品不存在"))
			return
		}
		goodsModel := goodsInterface.(*model.CommunityTeamGoods)
		var skuInterface interface{}
		if item.SkuId != "-1" {
			skuInterface, _, _ = db.GetComm(MasterDb(c), &model.CommunityTeamSku{GoodsId: utils.StrToInt(item.GoodsId), SkuId: utils.StrToInt64(item.SkuId)})
		} else {
			skuInterface, _, _ = db.GetComm(MasterDb(c), &model.CommunityTeamSku{GoodsId: utils.StrToInt(item.GoodsId)})
		}
		if err != nil || !has {
			sess.Rollback()
			e.OutErr(c, 400, e.NewErr(400, "商品不存在"))
			return
		}
		skuModel := skuInterface.(*model.CommunityTeamSku)
		var goodsSaleCount int
		// 走普通逻辑
		stock := skuModel.Stock - utils.StrToInt(item.Num)
		saleCount := skuModel.SaleCount + utils.StrToInt(item.Num)
		goodsSaleCount = goodsModel.SaleCount + utils.StrToInt(item.Num)
		if stock < 0 {
			sess.Rollback()
			e.OutErr(c, 400, e.NewErr(400, "库存不足"))
			return
		}
		update, err := sess.Where("sku_id=?", skuModel.SkuId).Cols("stock", "sale_count").Update(&model.CommunityTeamSku{Stock: stock, SaleCount: saleCount})
		if err != nil {
			sess.Rollback()
			e.OutErr(c, 400, e.NewErr(400, "商品不存在"))
			return
		}
		if update != 1 {
			sess.Rollback()
			e.OutErr(c, 400, e.NewErr(400, "商品不存在"))
			return
		}
		// 更新销量
		goodsModel.SaleCount = goodsSaleCount
		goodsModel.Stock = goodsModel.Stock - utils.StrToInt(item.Num)
		_, err = sess.Where("id = ?", goodsModel.Id).Cols("sale_count,stock").Update(goodsModel)
		if err != nil {
			sess.Rollback()
			e.OutErr(c, 400, e.NewErr(400, "商品不存在"))
			return
		}

		// 插入订单
		insert, err := sess.Insert(&model.CommunityTeamOrderInfo{
			Oid:     utils.StrToInt64(ordId),
			Title:   goodsModel.Title,
			Img:     goodsModel.Img,
			Price:   skuModel.Price,
			Num:     utils.StrToInt(item.Num),
			SkuInfo: skuModel.Sku,
			GoodsId: skuModel.GoodsId,
			SkuId:   int(skuModel.SkuId),
		})

		if err != nil {
			sess.Rollback()
			e.OutErr(c, 400, e.NewErr(400, "下单失败"))
			return
		}
		if insert != 1 {
			sess.Rollback()
			e.OutErr(c, 400, e.NewErr(400, "下单失败"))
			return
		}
	}
	// 更新优惠券使用状态
	if utils.StrToInt(arg.CouponId) > 0 {
		affect, err := sess.Where("id = ?", arg.CouponId).
			Update(&model.CommunityTeamCouponUser{IsUse: 1})
		if err != nil {
			e.OutErr(c, 400, e.NewErr(400, "下单失败"))
			return
		}
		if affect != 1 {
			e.OutErr(c, 400, e.NewErr(400, "下单失败"))
			return
		}
	}

	err = sess.Commit()
	if err != nil {
		sess.Rollback()
		e.OutErr(c, 400, err.Error())
		return
	}
	sess.Commit()
	e.OutSuc(c, map[string]string{"oid": ordId}, nil)
	return
}
func OrderTotal(c *gin.Context) {
	var arg md.OrderTotal
	if err := c.ShouldBindJSON(&arg); err != nil {
		e.OutErr(c, e.ERR_INVALID_ARGS, err)
		return
	}
	sess := MasterDb(c).NewSession()
	defer sess.Close()
	err := sess.Begin()
	if err != nil {
		e.OutErr(c, 400, err.Error())
		return
	}
	totalPrice := commGoods(c, arg)
	oldTotalPrice := totalPrice
	coupon := "0"
	totalPrice, coupon, err = CouponProcess(c, sess, totalPrice, arg)
	if err != nil {
		sess.Rollback()
		e.OutErr(c, 400, err.Error())
		return
	}
	user := GetUser(c)
	result := map[string]interface{}{
		"balance_money": GetCommissionPrec(c, user.Profile.FinValid, SysCfgGet(c, "commission_prec"), SysCfgGet(c, "is_show_point")),
		"small_amount":  GetCommissionPrec(c, oldTotalPrice, SysCfgGet(c, "commission_prec"), SysCfgGet(c, "is_show_point")),
		"all_amount":    GetCommissionPrec(c, totalPrice, SysCfgGet(c, "commission_prec"), SysCfgGet(c, "is_show_point")),
		"coupon":        GetCommissionPrec(c, coupon, SysCfgGet(c, "commission_prec"), SysCfgGet(c, "is_show_point")),
	}
	sess.Commit()
	e.OutSuc(c, result, nil)
	return
}
func CouponProcess(c *gin.Context, sess *xorm.Session, total string, args md.OrderTotal) (string, string, error) {
	if utils.StrToInt(args.CouponId) == 0 {
		return total, "0", nil
	}
	now := time.Now().Format("2006-01-02 15:04:05")
	user := GetUser(c)
	var goodsIds []int
	var skuIds []string
	for _, item := range args.GoodsInfo {
		goodsIds = append(goodsIds, utils.StrToInt(item.GoodsId))
		skuIds = append(skuIds, utils.AnyToString(item.SkuId))
	}
	// 获取优惠券信息
	var mallUserCoupon model.CommunityTeamCouponUser
	isExist, err := sess.
		Where("id = ? AND uid = ? AND is_use = ? AND (valid_time_start < ? AND valid_time_end > ?)", args.CouponId, user.Info.Uid, 1, now, now).
		Get(&mallUserCoupon)
	if err != nil {
		return "", "", err
	}
	if !isExist {
		return "", "", errors.New("无相关优惠券信息")
	}

	var cal struct {
		Reach  string `json:"reach"`
		Reduce string `json:"reduce"`
	}
	_ = json.Unmarshal([]byte(mallUserCoupon.Cal), &cal)
	reach, err := decimal.NewFromString(cal.Reach)
	reduce, err := decimal.NewFromString(cal.Reduce)
	if err != nil {
		return "", "", err
	}

	var specialTotal = total
	// 是否满足优惠条件
	if !reach.IsZero() { // 满减及有门槛折扣
		if utils.StrToFloat64(specialTotal) < utils.StrToFloat64(reach.String()) {
			return "", "", errors.New("不满足优惠条件")
		}
	} else {
		if mallUserCoupon.Kind == 1 { //立减
			if utils.StrToFloat64(specialTotal) < utils.StrToFloat64(reduce.String()) {
				return "", "", errors.New("不满足优惠条件")
			}
		}
	}
	// 计算优惠后支付金额
	couponTotal := "0"
	if mallUserCoupon.Kind == int(enum.ActCouponTypeImmediate) ||
		mallUserCoupon.Kind == int(enum.ActCouponTypeReachReduce) { // 立减 || 满减
		couponTotal = reduce.String()
		total = utils.Float64ToStr(utils.StrToFloat64(total) - utils.StrToFloat64(reduce.String()))
	} else { // 折扣
		couponTotal = utils.Float64ToStr(utils.StrToFloat64(total) - utils.StrToFloat64(total)*utils.StrToFloat64(reduce.String())/10)
		total = utils.Float64ToStr(utils.StrToFloat64(total) * utils.StrToFloat64(reduce.String()) / 10)
	}
	return total, couponTotal, nil
}

func commGoods(c *gin.Context, arg md.OrderTotal) (totalPrice string) {
	engine := MasterDb(c)
	var totalPriceAmt float64 = 0
	for _, item := range arg.GoodsInfo {
		goodsInterface, _, _ := db.GetComm(engine, &model.CommunityTeamGoods{Id: utils.StrToInt(item.GoodsId)})
		goodsModel := goodsInterface.(*model.CommunityTeamGoods)
		var skuInterface interface{}
		if item.SkuId != "-1" {
			skuInterface, _, _ = db.GetComm(engine, &model.CommunityTeamSku{GoodsId: utils.StrToInt(item.GoodsId), SkuId: utils.StrToInt64(item.SkuId)})
		} else {
			skuInterface, _, _ = db.GetComm(engine, &model.CommunityTeamSku{GoodsId: utils.StrToInt(item.GoodsId)})
		}
		skuModel := skuInterface.(*model.CommunityTeamSku)
		priceOne := goodsModel.Price
		if item.SkuId != "-1" {
			priceOne = skuModel.Price
		}
		totalPriceAmt += utils.StrToFloat64(priceOne) * utils.StrToFloat64(item.Num)
	}
	return utils.Float64ToStr(totalPriceAmt)

}
