package svc

import (
	"applet/app/db"
	"applet/app/db/model"
	"applet/app/e"
	"applet/app/md"
	"applet/app/svc"
	"applet/app/utils"
	"applet/app/utils/logx"
	"encoding/json"
	"github.com/gin-gonic/gin"
	"github.com/jinzhu/copier"
	"github.com/shopspring/decimal"
	"strings"
	"time"
)

func GoodsCate(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 := svc.GetUser(c)
	arg["uid"] = utils.IntToStr(user.Info.Uid)
	arg["store_type"] = "2"
	cate, total := db.GetGoodsCate(svc.MasterDb(c), arg)
	list := make([]map[string]string, 0)
	if cate != nil {
		for _, v := range *cate {
			tmp := map[string]string{
				"id":      utils.IntToStr(v.Id),
				"sort":    utils.IntToStr(v.Sort),
				"is_show": utils.IntToStr(v.IsShow),
				"title":   v.Title,
			}
			list = append(list, tmp)
		}
	}
	res := map[string]interface{}{
		"list": list, "total": total,
	}
	e.OutSuc(c, res, nil)
	return
}
func GoodsCateSave(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 := svc.GetUser(c)
	var data = &model.CommunityTeamCate{}

	if utils.StrToInt(arg["id"]) > 0 {
		cate := db.GetGoodsCateById(svc.MasterDb(c), arg["id"])
		if cate == nil {
			e.OutErr(c, 400, e.NewErr(400, "分类不存在"))
			return
		}
		data = cate
	} else {
		data = &model.CommunityTeamCate{
			IsShow: utils.StrToInt(arg["is_show"]),
		}
		svc.MasterDb(c).Insert(data)
	}
	data.StoreType = 2
	data.Uid = user.Info.Uid
	data.Sort = utils.StrToInt(arg["sort"])
	data.IsShow = utils.StrToInt(arg["is_show"])
	data.Title = arg["title"]
	svc.MasterDb(c).Where("id=?", data.Id).Update(data)
	e.OutSuc(c, "success", nil)
	return

}
func GoodsCateShow(c *gin.Context) {
	var arg map[string]string
	if err := c.ShouldBindJSON(&arg); err != nil {
		e.OutErr(c, e.ERR_INVALID_ARGS, err)
		return
	}
	cate := db.GetGoodsCateById(svc.MasterDb(c), arg["id"])
	if cate == nil {
		e.OutErr(c, 400, e.NewErr(400, "分类不存在"))
		return
	}
	cate.IsShow = utils.StrToInt(arg["is_show"])
	svc.MasterDb(c).Where("id=?", cate.Id).Cols("is_show").Update(cate)
	e.OutSuc(c, "success", nil)
	return

}
func GoodsCateDel(c *gin.Context) {
	var arg map[string]string
	if err := c.ShouldBindJSON(&arg); err != nil {
		e.OutErr(c, e.ERR_INVALID_ARGS, err)
		return
	}
	svc.MasterDb(c).In("id", strings.Split(arg["ids"], ",")).Delete(&model.CommunityTeamCate{})
	e.OutSuc(c, "success", nil)
	return
}

func Goods(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 := svc.GetUser(c)
	arg["uid"] = utils.IntToStr(user.Info.Uid)
	arg["store_type"] = "2"
	cate, total := db.GetStoreGoods(svc.MasterDb(c), arg)
	list := make([]map[string]string, 0)
	cateData := db.GetGoodsCateAll(svc.MasterDb(c))
	cateList := make([]map[string]string, 0)
	cateMap := make(map[int]string)
	if cateData != nil {
		for _, v := range *cateData {
			tmp := map[string]string{
				"name": v.Title, "value": utils.IntToStr(v.Id),
			}
			cateList = append(cateList, tmp)
			cateMap[v.Id] = v.Title
		}
	}
	if cate != nil {
		stateMap := []string{"上架", "下架"}
		scheme, host := svc.ImageBucket(c)
		for _, v := range *cate {
			tmp := map[string]string{
				"id":        utils.IntToStr(v.Id),
				"title":     v.Title,
				"price":     v.Price,
				"info":      v.Info,
				"img_url":   svc.ImageFormatWithBucket(scheme, host, v.Img),
				"create_at": v.CreateAt.Format("2006-01-02 15:04:05"),
				"cate":      cateMap[v.Cid],
				"state":     stateMap[v.State],
			}
			list = append(list, tmp)
		}
	}
	res := map[string]interface{}{
		"list": list, "total": total, "cate_list": cateList,
	}
	e.OutSuc(c, res, nil)
	return
}
func GoodsSave(c *gin.Context) {
	var args md.AddGoodsReq
	if err := c.ShouldBindJSON(&args); err != nil {
		e.OutErr(c, e.ERR_INVALID_ARGS, err)
		return
	}
	saleCount := 0
	eg := svc.MasterDb(c)
	user := svc.GetUser(c)
	if utils.StrToInt(args.Base.Id) != 0 {
		oldGoods := db.GetGoodsById(eg, args.Base.Id)
		if oldGoods == nil {
			e.OutErr(c, 400, e.NewErr(400, "商品不存在"))
			return
		}
		saleCount = oldGoods.SaleCount
	}
	sess := eg.NewSession()
	defer func() {
		_ = sess.Close()
	}()
	err := sess.Begin()
	if err != nil {
		e.OutErr(c, 400, e.NewErr(400, err.Error()))
		return
	}
	// 商品基本信息保存
	var goods model.CommunityTeamGoods
	err = copier.Copy(&goods, args.Base)
	goods.StoreType = 2
	goods.Uid = user.Info.Uid
	goods.Id = utils.StrToInt(args.Base.Id)
	goods.Stock = utils.StrToInt(args.Base.Stock)
	goods.State = utils.StrToInt(args.Base.State)
	goods.Cid = utils.StrToInt(args.Base.Cid)
	goods.IsSingleSku = utils.StrToInt(args.Base.IsSingleSku)
	goods.Sort = utils.StrToInt(args.Base.Sort)
	if err != nil {
		_ = sess.Rollback()
		e.OutErr(c, 400, e.NewErr(400, err.Error()))
		return
	}
	goods.SaleCount = saleCount
	goods.Img = args.Base.Img
	goods.ImageList = utils.SerializeStr([]string{args.Base.Img})
	goods.Spe = utils.SerializeStr(args.Base.Spe)
	// 商品价格处理
	if goods.IsSingleSku == 1 { // 单规格 计算折扣价
		args.SkuList = []md.MallGoodsSku{
			{
				Price:   args.Base.Price,
				Stock:   args.Base.Stock,
				Indexes: "",
				Sku:     []map[string]string{},
			},
		}
	} else { // 多规格
		var totalStock = 0
		minPriceD, err := decimal.NewFromString(args.SkuList[0].Price)
		if err != nil {
			_ = sess.Rollback()
			e.OutErr(c, 400, e.NewErr(400, "规格价格格式有误"))
			return
		}
		for _, item := range args.SkuList {
			tempPrice, err := decimal.NewFromString(item.Price)
			totalStock += utils.StrToInt(item.Stock)
			if err != nil {
				_ = sess.Rollback()
				logx.Warn("", err)
				e.OutErr(c, 400, e.NewErr(400, "规格价格格式有误"))
				return
			}
			if tempPrice.LessThan(minPriceD) {
				minPriceD = tempPrice
			}
		}
		goods.Price = minPriceD.String()
		goods.Stock = totalStock
	}
	goods.UpdateAt = time.Now()
	if utils.StrToInt(args.Base.Id) == 0 { // 新增goods
		goods.CreateAt = time.Now()
		_, err = sess.Insert(&goods)
		if err != nil {
			logx.Warn(err)
			_ = sess.Rollback()
			e.OutErr(c, 400, e.NewErr(400, "插入商品数据失败"))
			return
		}
	} else { // 更新数据
		oldGoods := db.GetGoodsByIdSess(sess, args.Base.Id)
		goods.CreateAt = oldGoods.CreateAt
		_, err = sess.Where(" id = ?", args.Base.Id).
			AllCols().Update(&goods)
		if err != nil {
			_ = sess.Rollback()
			logx.Warn(err)
			e.OutErr(c, 400, e.NewErr(400, "更新商品失败"))
			return
		}
	}
	skuModelList := make([]*model.CommunityTeamSku, 0, len(args.SkuList))
	for _, item := range args.SkuList {
		skuModelList = append(skuModelList, &model.CommunityTeamSku{
			GoodsId:  goods.Id,
			Price:    item.Price,
			Stock:    utils.StrToInt(item.Stock),
			Indexes:  GetIndexesStr(&args.Base, item),
			Sku:      utils.SerializeStr(&item.Sku),
			Discount: "10",
		})
	}
	// 插入sku信息
	if len(skuModelList) != 0 {
		insert, err := sess.Insert(skuModelList)
		if err != nil || insert < 1 {
			_ = sess.Rollback()
			e.OutErr(c, 400, e.NewErr(400, "商品规格插入失败"))
			return
		}
	}

	sess.Commit()
	e.OutSuc(c, "success", nil)
	return

}
func GetIndexesStr(baseGoods *md.BaseGoods, goodsSku md.MallGoodsSku) string {
	spe := baseGoods.Spe
	sku := goodsSku.Sku
	result := ""

	for index, item := range sku {
		for _, itm := range spe {
			if item["name"] == itm.Name {
				for i, v := range spe[index].Values {
					if v == item["value"] {
						result = result + utils.IntToStr(i) + "-"
					}
				}
			}
		}
	}
	return strings.Trim(result, "-")
}

func GoodsDel(c *gin.Context) {
	var arg map[string]string
	if err := c.ShouldBindJSON(&arg); err != nil {
		e.OutErr(c, e.ERR_INVALID_ARGS, err)
		return
	}
	svc.MasterDb(c).In("id", strings.Split(arg["ids"], ",")).Delete(&model.CommunityTeamGoods{})
	svc.MasterDb(c).In("goods_id", strings.Split(arg["ids"], ",")).Delete(&model.CommunityTeamSku{})
	e.OutSuc(c, "success", nil)
	return
}
func GoodsDetail(c *gin.Context) {
	var arg map[string]string
	if err := c.ShouldBindJSON(&arg); err != nil {
		e.OutErr(c, e.ERR_INVALID_ARGS, err)
		return
	}
	goods := db.GetGoodsById(svc.MasterDb(c), arg["id"])
	if goods == nil {
		e.OutErr(c, 400, e.NewErr(400, "商品不存在"))
		return
	}
	cateData := db.GetGoodsCateAll(svc.MasterDb(c))
	cateList := make([]map[string]string, 0)
	cateMap := make(map[int]string)
	if cateData != nil {
		for _, v := range *cateData {
			tmp := map[string]string{
				"name": v.Title, "value": utils.IntToStr(v.Id),
			}
			cateList = append(cateList, tmp)
			cateMap[v.Id] = v.Title
		}
	}
	stateMap := []string{"上架", "下架"}
	scheme, host := svc.ImageBucket(c)
	res := md.BaseGoods{
		Id:           utils.IntToStr(goods.Id),
		Title:        goods.Title,
		Cid:          utils.IntToStr(goods.Cid),
		CategoryName: cateMap[goods.Cid],
		IsSingleSku:  utils.IntToStr(goods.IsSingleSku),
		Price:        goods.Price,
		Stock:        utils.IntToStr(goods.Stock),
		Img:          goods.Img,
		ImgUrl:       svc.ImageFormatWithBucket(scheme, host, goods.Img),
		Spe:          nil,
		Sort:         utils.IntToStr(goods.Sort),
		Info:         goods.Info,
		State:        utils.IntToStr(goods.State),
		StateStr:     stateMap[goods.State],
	}
	GoodsSpe := make([]md.GoodsSpe, 0)
	json.Unmarshal([]byte(goods.Spe), &GoodsSpe)
	for k, v := range GoodsSpe {
		if len(v.Values) == 0 {
			GoodsSpe[k].Values = make([]string, 0)
		}
	}
	res.Spe = GoodsSpe
	sku := db.GetGoodsSkuById(svc.MasterDb(c), goods.Id)
	skuList := make([]md.MallGoodsSku, 0)
	if sku != nil {
		for _, v := range *sku {
			skuMap := make([]map[string]string, 0)
			json.Unmarshal([]byte(v.Sku), &skuMap)
			tmp := md.MallGoodsSku{
				SkuID:   utils.Int64ToStr(v.SkuId),
				GoodsID: utils.IntToStr(v.GoodsId),
				Price:   v.Price,
				Stock:   utils.IntToStr(v.Stock),
				Indexes: v.Indexes,
				Sku:     skuMap,
			}
			skuList = append(skuList, tmp)
		}
	}
	if goods.IsSingleSku == 1 {
		skuList = nil
	}
	re := map[string]interface{}{
		"base":     res,
		"sku_list": skuList,
	}
	e.OutSuc(c, re, nil)
	return
}
