package goods

import (
	"errors"
	"spaceofcheng/services/models"
	"spaceofcheng/services/models/model"
	"spaceofcheng/services/utils"
	"time"

	"github.com/yl10/kit/guid"

	"github.com/go-xorm/xorm"
)

// GoodsDAO 当前数据库操作对象
type GoodsDAO struct {
	ctx *utils.Context
	db  *xorm.Session
}

// NewGoodsDAO New Inst
func NewGoodsDAO(ctx *utils.Context) *GoodsDAO {
	return &GoodsDAO{
		ctx: ctx,
		db:  ctx.DB,
	}
}

// GetGoodsListPageNavi 获取商品列表
// 管理端接口
func (m *GoodsDAO) GetGoodsListPageNavi(name, typeID, caseID string, limit []int) ([]GoodsWithSpec, int64, error) {
	sql := `
		SELECT *
		FROM
			ta_goods t
		WHERE
			t.case_id = ?
	`

	if name != "" {
		sql += `
			AND LOWER(t.goods_name) LIKE '%` + name + `%'
		`
	}

	if typeID != "" {
		sql += `
			AND t.type_id = '` + typeID + `'
		`
	}

	sql += `		
		AND t.status > ?
		ORDER BY
			t.type_id,
			t.create_date
	`

	var goodsList []GoodsWithSpec
	cnt, err := utils.NewPageNaviEngine(m.ctx).GetPageList(&goodsList, sql, limit, caseID, models.STATUS_DEL)
	if err != nil {
		return nil, 0, err
	}

	for inx, goods := range goodsList {
		specs, err := m.GetSpecWithPrice(goods.GoodsId)
		if err != nil {
			return nil, 0, err
		}

		goodsList[inx].Specs = specs
	}

	return goodsList, cnt, nil
}

// GetGoodsListOfCase 获取案场商品列表
// 微信端 暂时没涉及分页
func (m *GoodsDAO) GetGoodsListOfCase(caseID string) ([]GoodsWithSpec, error) {
	var goodsList []GoodsWithSpec

	sql := "select * from ta_goods where case_id = ? and status = ? order by t.type_id, t.create_date"
	if err := m.db.SQL(sql, caseID, models.STATUS_NORMAL).Find(&goodsList); err != nil {
		return nil, err
	}

	for inx, goods := range goodsList {
		specs, err := m.GetSpecWithPrice(goods.GoodsId)
		if err != nil {
			return nil, err
		}

		goodsList[inx].Specs = specs
	}

	return goodsList, nil
}

// GetSpecWithPrice 获取商品规格 含 金额
func (m *GoodsDAO) GetSpecWithPrice(goodsID string) ([]SpecWithPrice, error) {
	sql := `SELECT * FROM td_spec t
		JOIN ta_goods_spec s ON t.spec_id = s.spec_id
		WHERE t.status = ? AND s.goods_id = ?
	`

	var specs []SpecWithPrice
	err := m.db.SQL(sql, models.STATUS_DEL, goodsID).Find(&specs)

	return specs, err
}

// GetGoodsByID 依据ID 获取商品
func (m *GoodsDAO) GetGoodsByID(id string) (*model.TaGoods, error) {
	goods := new(model.TaGoods)
	if _, err := m.db.Where("goods_id=?", id).Get(goods); err != nil {
		return nil, err
	}

	return goods, nil
}

// GetGoodsWithPriceByID 依据ID 获取商品
func (m *GoodsDAO) GetGoodsWithPriceByID(id, spec, caseID string) (*GoodsWithPrice, error) {
	goods := new(GoodsWithPrice)
	query := `
		SELECT *
		FROM
			ta_goods t
		JOIN ta_goods_spec s ON t.goods_id = s.goods_id
		WHERE
			t.goods_id = ?
		AND t.case_id = ?
		AND s.spec_id = ?
		AND t.status = ?
	`

	if _, err := m.db.SQL(query, id, caseID, spec, models.STATUS_NORMAL).Get(goods); err != nil {
		return nil, err
	}

	return goods, nil
}

// GetGoodsWithSpecByID  依据ID 获取商品(含规格)
func (m *GoodsDAO) GetGoodsWithSpecByID(id string) (*GoodsWithSpec, error) {
	goods := new(model.TaGoods)
	if _, err := m.db.Where("goods_id=?", id).Get(goods); err != nil {
		return nil, err
	}

	var specs []SpecWithPrice
	query := `
		SELECT
			t.*, s.goods_price
		FROM
			td_spec t
		JOIN ta_goods_spec s ON t.spec_id = s.spec_id
		WHERE
			s.goods_id = ?
	`
	if err := m.db.SQL(query, id).Find(&specs); err != nil {
		return nil, err
	}

	return &GoodsWithSpec{
		TaGoods: *goods,
		Specs:   specs,
	}, nil
}

// SaveGoods 保存商品
func (m *GoodsDAO) SaveGoods(goods *model.TaGoods, images []string, specs []SpecWithPrice) error {
	userRaw := m.ctx.Get("user")
	if userRaw == nil {
		return errors.New("登录异常, 请登出重试")
	}
	user := userRaw.(model.SysUser)

	goods.GoodsId = guid.NewGUIDString()
	goods.Status = models.STATUS_NORMAL
	goods.CreateDate = time.Now().Local()
	goods.CreateUser = user.UserId
	goods.OrgId = user.OrgId

	// 商品图片
	if images != nil && len(images) > 0 {
		goodsImages := make([]model.TaGoodsImg, 0)

		for _, img := range images {
			goodsImages = append(goodsImages, model.TaGoodsImg{
				ImgId:   guid.NewGUIDString(),
				GoodsId: goods.GoodsId,
				ImgUrl:  img,
				Status:  models.STATUS_NORMAL,
			})
		}

		if _, err := m.db.Insert(&goodsImages); err != nil {
			return err
		}
	}

	// 规格
	if specs != nil && len(specs) > 0 {
		goodsSpecs := make([]model.TaGoodsSpec, 0)

		for _, spec := range specs {
			goodsSpecs = append(goodsSpecs, model.TaGoodsSpec{
				SpecId:     spec.SpecId,
				GoodsId:    goods.GoodsId,
				GoodsPrice: spec.GoodsPrice,
			})
		}

		if _, err := m.db.Insert(&goodsSpecs); err != nil {
			return err
		}
	}

	if _, err := m.db.Insert(goods); err != nil {
		return err
	}

	return nil
}

// UpdateGoods 更新商品
func (m *GoodsDAO) UpdateGoods(goods *model.TaGoods, images []string, specs []SpecWithPrice) error {
	cols := []string{
		"goods_name",
		"type_id",
		"status",
	}

	// 商品图片
	if images != nil && len(images) > 0 {
		// 先清除旧数据
		if _, err := m.db.Delete(&model.TaGoodsImg{GoodsId: goods.GoodsId}); err != nil {
			return err
		}

		goodsImages := make([]model.TaGoodsImg, 0)
		for _, img := range images {
			goodsImages = append(goodsImages, model.TaGoodsImg{
				ImgId:   guid.NewGUIDString(),
				GoodsId: goods.GoodsId,
				ImgUrl:  img,
				Status:  models.STATUS_NORMAL,
			})
		}

		if _, err := m.db.Insert(&goodsImages); err != nil {
			return err
		}
	}

	// 规格
	if specs != nil && len(specs) > 0 {
		// 先清除旧数据
		if _, err := m.db.Delete(&model.TaGoodsSpec{GoodsId: goods.GoodsId}); err != nil {
			return err
		}

		goodsSpecs := make([]model.TaGoodsSpec, 0)
		for _, spec := range specs {
			goodsSpecs = append(goodsSpecs, model.TaGoodsSpec{
				SpecId:     spec.SpecId,
				GoodsId:    goods.GoodsId,
				GoodsPrice: spec.GoodsPrice,
			})
		}

		if _, err := m.db.Insert(&goodsSpecs); err != nil {
			return err
		}
	}

	if _, err := m.db.Where("goods_id=?", goods.GoodsId).Cols(cols...).Update(goods); err != nil {
		return err
	}

	return nil
}

// DeleteGoods 删除商品
func (m *GoodsDAO) DeleteGoods(id string) error {
	goods := new(model.TaGoods)
	goods.Status = models.STATUS_DEL

	if _, err := m.db.Where("goods_id=?", id).Cols("status").Update(goods); err != nil {
		return err
	}

	return nil
}
