package models

import (
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	orm "go-admin/common/global"
	"go-admin/logger"
	"go-admin/tools"
	"gorm.io/gorm"
	"math/rand"
	"time"
)

// ErpPurchaseChangeOrder 采购换机订单表
type ErpPurchaseChangeOrder struct {
	Model
	SerialNumber    string                       `json:"serial_number" gorm:"index"`   // 单据编号
	StoreId         uint32                       `json:"store_id" gorm:"index"`        // 门店id
	StoreName       string                       `json:"store_name"`                   // 门店名称
	ErpSupplierId   uint32                       `json:"erp_supplier_id" gorm:"index"` // 供应商id
	ErpSupplierName string                       `json:"erp_supplier_name"`            // 供应商名称
	MakerTime       *time.Time                   `json:"maker_time"`                   // 制单时间
	MakerId         uint32                       `json:"maker_id" gorm:"index"`        // 制单人id
	MakerName       string                       `json:"maker_name"`                   // 制单人名称
	AuditTime       *time.Time                   `json:"audit_time"`                   // 审核时间
	AuditorId       uint32                       `json:"auditor_id" gorm:"index"`      // 审核人id
	AuditorName     string                       `json:"auditor_name"`                 // 审核人名称
	State           uint32                       `json:"state"`                        // 1-待审核 2-已完成
	Remark          string                       `json:"remark"`                       // 备注
	Commodities     []ErpPurchaseChangeCommodity `json:"commodities" gorm:"-"`         // 采购换机商品信息
}

// ErpPurchaseChangeCommodity 采购换机订单商品表
type ErpPurchaseChangeCommodity struct {
	Model
	ChangeOrderId         uint32 `json:"change_order_id" gorm:"index"`         // 采购换机订单id
	ErpCommodityId        uint32 `json:"erp_commodity_id" gorm:"index"`        // 商品id
	ErpCommodityName      string `json:"erp_commodity_name"`                   // 商品名称
	CommoditySerialNumber string `json:"commodity_serial_number" gorm:"index"` // 商品编号
	IMEIType              uint32 `json:"imei_type"`                            // 1-无串码 2-串码
	OriginIMEI            string `json:"origin_imei"`                          // 原机身串码
	NewIMEI               string `json:"new_imei"`                             // 新机身串码
	Count                 uint32 `json:"count"`                                // 数量
	OriginColor           string `json:"origin_color"`                         // 原机身颜色
	NewColor              string `json:"new_color"`                            // 新机身颜色
	Remark                string `json:"remark"`                               // 备注
}

// ErpPurchaseChangeCreateReq 新建采购换机订单入参
type ErpPurchaseChangeCreateReq struct {
	StoreId       uint32                       `json:"store_id"`                       // 门店id:入库必传
	ErpSupplierId uint32                       `json:"erp_supplier_id"`                // 供应商id:入库必传
	Remark        string                       `json:"remark"`                         // 备注
	Commodities   []ErpPurchaseChangeCommodity `json:"commodities" binding:"required"` // 采购换机商品信息
}

// ErpPurchaseChangeEditReq 编辑采购换机订单入参
type ErpPurchaseChangeEditReq struct {
	ChangeOrderId uint32                       `json:"change_order_id" gorm:"index"`   // 采购换机订单id
	StoreId       uint32                       `json:"store_id"`                       // 门店id:入库必传
	ErpSupplierId uint32                       `json:"erp_supplier_id"`                // 供应商id:入库必传
	Remark        string                       `json:"remark"`                         // 备注
	Commodities   []ErpPurchaseChangeCommodity `json:"Commodities" binding:"required"` // 采购商品信息
}

// ErpPurchaseChangeOrderListReq 查询采购换机订单列表入参
type ErpPurchaseChangeOrderListReq struct {
	SerialNumber   string   `json:"serial_number"`    // 单据编号
	StoreId        uint32   `json:"store_id"`         // 门店id
	ErpSupplierId  uint32   `json:"erp_supplier_id"`  // 供应商id
	MakerTimeStart string   `json:"make_time_start"`  // 制单开始时间
	MakerTimeEnd   string   `json:"make_time_end"`    // 制单结束时间
	AuditTimeStart string   `json:"audit_time_start"` // 审核开始时间
	AuditTimeEnd   string   `json:"audit_time_end"`   // 审核结束时间
	State          []uint32 `json:"state"`            // 状态：1-待审核 2-已完成
	HandlerId      uint32   `json:"handler_id"`       // 经手人id
	PageIndex      int      `json:"pageIndex"`        // 页码
	PageSize       int      `json:"pageSize"`         // 页面条数
}

// ErpPurchaseChangeOrderListResp 查询采购换机订单列表出参
type ErpPurchaseChangeOrderListResp struct {
	List      []ErpPurchaseChangeOrder `json:"list"`
	Total     int                      `json:"total"`     // 总条数
	PageIndex int                      `json:"pageIndex"` // 页码
	PageSize  int                      `json:"pageSize"`  // 页面条数
}

// ErpPurchaseChangeDeleteReq 删除采购换机订单入参
type ErpPurchaseChangeDeleteReq struct {
	SerialNumber string `json:"serial_number" binding:"required"` // 单据编号
}

// ErpPurchaseChangeAuditReq 审核采购换机订单入参
type ErpPurchaseChangeAuditReq struct {
	SerialNumber string `json:"serial_number" binding:"required"` // 单据编号
	State        int    `json:"state"  binding:"required"`        // 审核操作: 1-审核 2-取消审核
}

// newErpPurchaseChangeSn 生成采购换机订单号
func newErpPurchaseChangeSn() string {
	var prefix string
	prefix = "cgh"

	nowTime := time.Now()
	rand.Seed(nowTime.UnixNano())
	max := 1
	for {
		if max > 5 {
			logger.Error("create sn err")
			return ""
		}
		random := rand.Intn(9000) + 1000
		sn := fmt.Sprintf("%s%d", nowTime.Format("060102"), random)
		exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_purchase_change_order WHERE "+
			"serial_number='%s'", prefix+sn))
		if err != nil {
			logger.Error("exist sn err")
		}
		if !exist {
			return prefix + sn
		}

		max++
	}
}

// IdInit 添加商户和供应商信息
func (m *ErpPurchaseChangeOrder) IdInit() error {
	if m.StoreId != 0 {
		store, err := GetStore(m.StoreId)
		if err != nil {
			logger.Error("get store err:", logger.Field("err", err))
			return err
		}
		m.StoreName = store.Name
	}

	if m.ErpSupplierId != 0 {
		supplier, err := GetErpSupplier(m.ErpSupplierId)
		if err != nil {
			logger.Error("get supplier err:", logger.Field("err", err))
			return err
		}
		m.ErpSupplierName = supplier.Name
	}

	return nil
}

// CheckCreateErpPurchaseChangeOrderParam 新增采购换机订单-检查参数
func CheckCreateErpPurchaseChangeOrderParam(req *ErpPurchaseChangeCreateReq) error {
	if req.StoreId == 0 {
		return errors.New("操作失败:门店id为空")
	}
	if req.ErpSupplierId == 0 {
		return errors.New("操作失败:供应商id为空")
	}
	for _, item := range req.Commodities {
		if item.Count <= 0 {
			return errors.New("操作失败:采购换机数量需大于0")
		}

		// 判断是否是串码商品，非串码商品不支持
		if item.IMEIType == 1 {
			return errors.New("操作失败:采购换机不支持非串码商品")
		}

		var imeiStockCommodity ErpStockCommodity
		err := orm.Eloquent.Table("erp_stock_commodity").Where("imei = ? and state = ?",
			item.OriginIMEI, InStock).Find(&imeiStockCommodity).Error
		if err != nil {
			return err
		}

		if imeiStockCommodity.ID == 0 {
			return errors.New("商品" + "[" + item.OriginIMEI + "]不在库")
		}

		if imeiStockCommodity.StoreId != req.StoreId {
			return errors.New("商品" + "[" + item.OriginIMEI + "]非所选门店库存，请检查")
		}

		// 判断新商品串码是否已录入或者使用过
		var newImeiStockCommodity ErpStockCommodity
		err = orm.Eloquent.Table("erp_stock_commodity").Where("imei = ?",
			item.NewIMEI).Find(&newImeiStockCommodity).Error
		if err != nil {
			return err
		}

		if newImeiStockCommodity.ID != 0 {
			return errors.New("串码" + "[" + item.NewIMEI + "]重复")
		}
	}

	return nil
}

// CheckEditErpPurchaseChangeOrderParam 编辑采购换机订单-检查参数
func CheckEditErpPurchaseChangeOrderParam(req *ErpPurchaseChangeEditReq) error {
	if req.StoreId == 0 {
		return errors.New("操作失败:门店id为空")
	}
	if req.ErpSupplierId == 0 {
		return errors.New("操作失败:供应商id为空")
	}
	for _, item := range req.Commodities {
		if item.Count <= 0 {
			return errors.New("操作失败:采购换机数量需大于0")
		}

		// 判断是否是串码商品，非串码商品不支持
		if item.IMEIType == 1 {
			return errors.New("操作失败:采购换机不支持非串码商品")
		}

		var imeiStockCommodity ErpStockCommodity
		err := orm.Eloquent.Table("erp_stock_commodity").Where("imei = ? and state = ?",
			item.OriginIMEI, InStock).Find(&imeiStockCommodity).Error
		if err != nil {
			return err
		}

		if imeiStockCommodity.ID == 0 {
			return errors.New("商品" + "[" + item.OriginIMEI + "]不在库")
		}

		if imeiStockCommodity.StoreId != req.StoreId {
			return errors.New("商品" + "[" + item.OriginIMEI + "]非所选门店库存，请检查")
		}

		// 判断新商品串码是否已录入或者使用过
		var newImeiStockCommodity ErpStockCommodity
		err = orm.Eloquent.Table("erp_stock_commodity").Where("imei = ?",
			item.NewIMEI).Find(&newImeiStockCommodity).Error
		if err != nil {
			return err
		}

		if newImeiStockCommodity.ID != 0 {
			return errors.New("串码" + "[" + item.OriginIMEI + "]重复")
		}
	}

	return nil
}

// CreateErpPurchaseChangeOrder 新增采购换机订单
func CreateErpPurchaseChangeOrder(req *ErpPurchaseChangeCreateReq, sysUser *SysUser) (*ErpPurchaseChangeOrder, error) {
	var err error
	nowTime := time.Now()

	purchaseOrder := &ErpPurchaseChangeOrder{}
	purchaseOrder = &ErpPurchaseChangeOrder{
		SerialNumber:  newErpPurchaseChangeSn(),
		StoreId:       req.StoreId,
		ErpSupplierId: req.ErpSupplierId,
		MakerTime:     &nowTime,
		MakerId:       uint32(sysUser.UserId),
		MakerName:     sysUser.NickName,
		State:         ErpPurchaseChangeOrderUnAudit, // 1-待审核
		Remark:        req.Remark,
	}
	err = purchaseOrder.IdInit()
	if err != nil {
		logger.Error("info err:", logger.Field("err", err))
		return nil, err
	}

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

	for i, _ := range req.Commodities {
		req.Commodities[i].ChangeOrderId = purchaseOrder.ID
		err = begin.Create(&req.Commodities[i]).Error
		if err != nil {
			begin.Rollback()
			logger.Error("create purchase commodity err:", logger.Field("err", err))
			return nil, err
		}
	}
	err = begin.Commit().Error
	if err != nil {
		begin.Rollback()
		logger.Error("commit purchase commodity err:", logger.Field("err", err))
		return nil, err
	}

	return purchaseOrder, nil
}

// EditErpPurchaseChangeOrder 编辑采购订单
func EditErpPurchaseChangeOrder(req *ErpPurchaseChangeEditReq, sysUser *SysUser) (*ErpPurchaseChangeOrder, error) {
	// 查询订单信息
	var purchaseChangeOrder ErpPurchaseChangeOrder
	err := orm.Eloquent.Table("erp_purchase_change_order").Where("id=?", req.ChangeOrderId).Find(&purchaseChangeOrder).Error
	if err != nil {
		logger.Error("purchase change order err:", logger.Field("err", err))
		return nil, err
	}

	if purchaseChangeOrder.State != ErpPurchaseChangeOrderUnAudit { // 只有待审核的订单才能编辑
		return nil, errors.New("订单不是待审核状态")
	}

	if req.StoreId == 0 {
		return nil, errors.New("操作失败:门店id为空")
	}

	begin := orm.Eloquent.Begin()
	// 1-更新采购订单信息
	purchaseChangeOrder.StoreId = req.StoreId
	purchaseChangeOrder.ErpSupplierId = req.ErpSupplierId
	purchaseChangeOrder.MakerId = uint32(sysUser.UserId)
	purchaseChangeOrder.MakerName = sysUser.NickName
	purchaseChangeOrder.Remark = req.Remark
	err = purchaseChangeOrder.IdInit()
	if err != nil {
		logger.Error("purchase change IdInit err:", logger.Field("err", err))
		return nil, err
	}

	err = begin.Model(&ErpPurchaseChangeOrder{}).Where("id = ?", req.ChangeOrderId).
		Omit("created_at").Save(purchaseChangeOrder).Error
	if err != nil {
		begin.Rollback()
		logger.Error("update erp_order err:", logger.Field("err", err))
		return nil, err
	}

	// 2-更新采购订单商品表
	err = updatePurchaseChangeCommodityData(begin, req.ChangeOrderId, req)
	if err != nil {
		begin.Rollback()
		logger.Error("update erp_purchase_commodity err:", logger.Field("err", err))
		return nil, err
	}

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

	return &purchaseChangeOrder, nil
}

// updatePurchaseChangeCommodityData 更新采购订单商品信息
func updatePurchaseChangeCommodityData(gdb *gorm.DB, orderId uint32, req *ErpPurchaseChangeEditReq) error {
	// 查询现有的零售订单信息
	var commodities []ErpPurchaseChangeCommodity
	err := orm.Eloquent.Table("erp_purchase_change_commodity").Where("change_order_id = ?", orderId).Find(&commodities).Error
	if err != nil {
		logger.Error("query erp_purchase_change_commodity err:", logger.Field("err", err))
		return err
	}

	// 1-删除所有的商品信息
	if len(commodities) != 0 {
		err = gdb.Delete(&commodities).Error
		if err != nil {
			logger.Error("更新商品订单信息-删除 error")
			return errors.New("操作失败:" + err.Error())
		}
	}

	for i, _ := range req.Commodities {
		req.Commodities[i].ID = 0
		if req.Commodities[i].ChangeOrderId == 0 { //发现前端有时会没传，后端打补丁
			req.Commodities[i].ChangeOrderId = req.ChangeOrderId
		}
	}

	// 2-更新商品订单信息-新增
	if len(req.Commodities) != 0 {
		err = gdb.Create(&req.Commodities).Error
		if err != nil {
			logger.Error("更新商品订单信息-新增 error")
			return errors.New("操作失败:" + err.Error())
		}
	}

	return nil
}

// List 查询采购订单列表
func (m *ErpPurchaseChangeOrderListReq) List(c *gin.Context) (*ErpPurchaseChangeOrderListResp, error) {
	resp := &ErpPurchaseChangeOrderListResp{
		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_purchase_change_order")

	if m.SerialNumber != "" {
		qs = qs.Where("serial_number=?", m.SerialNumber)
	} else {
		if m.StoreId != 0 {
			qs = qs.Where("store_id=?", m.StoreId)
		}
		// 非管理员才判断所属门店
		if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
			sysUser, err := GetSysUserByCtx(c)
			if err != nil {
				return nil, errors.New("操作失败:" + err.Error())
			}

			// 返回sysUser未过期的门店id列表
			storeList := GetValidStoreIDs(sysUser.StoreData)
			if len(storeList) > 0 {
				if len(storeList) == 1 {
					qs = qs.Where("store_id = ?", storeList[0])
				} else {
					qs = qs.Where("store_id IN (?)", storeList)
				}
			} else {
				return nil, errors.New("用户未绑定门店")
			}
		}
		if m.ErpSupplierId != 0 {
			qs = qs.Where("erp_supplier_id=?", m.ErpSupplierId)
		}
		if len(m.State) > 0 {
			qs = qs.Where("state IN (?)", m.State)
		}
		if m.MakerTimeStart != "" {
			parse, err := time.Parse(QueryTimeFormat, m.MakerTimeStart)
			if err != nil {
				logger.Errorf("erpPurchaseChangeOrderList err:", err)
				return nil, err
			}
			qs = qs.Where("make_time > ?", parse)
		}
		if m.MakerTimeEnd != "" {
			parse, err := time.Parse(QueryTimeFormat, m.MakerTimeEnd)
			if err != nil {
				logger.Errorf("erpPurchaseChangeOrderList err:", err)
				return nil, err
			}
			//parse = parse.AddDate(0, 0, 1)
			qs = qs.Where("make_time < ?", parse)
		}
		if m.HandlerId != 0 {
			qs = qs.Where("handler_id=?", m.HandlerId)
		}
		if m.AuditTimeStart != "" {
			parse, err := time.Parse(QueryTimeFormat, m.AuditTimeStart)
			if err != nil {
				logger.Errorf("erpPurchaseChangeOrderList err:", err)
				return nil, err
			}
			qs = qs.Where("audit_time > ?", parse)
		}
		if m.AuditTimeEnd != "" {
			parse, err := time.Parse(QueryTimeFormat, m.AuditTimeEnd)
			if err != nil {
				logger.Errorf("erpPurchaseChangeOrderList err:", err)
				return nil, err
			}
			//parse = parse.AddDate(0, 0, 1)
			qs = qs.Where("audit_time < ?", parse)
		}
		if m.HandlerId != 0 {
			qs = qs.Where("handler_id=?", m.HandlerId)
		}
	}

	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 orders []ErpPurchaseChangeOrder
	err = qs.Order("id DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&orders).Error
	if err != nil && err != RecordNotFound {
		logger.Error("erp commodity list err:", logger.Field("err", err))
		return resp, err
	}

	// 校验时间，如果为01-01-01 08:05，则赋值为空
	for i, v := range orders {
		if v.MakerTime != nil && v.MakerTime.IsZero() {
			orders[i].MakerTime = nil
		}

		if v.AuditTime != nil && v.AuditTime.IsZero() {
			orders[i].AuditTime = nil
		}
	}

	changeOrderListSetCommodity(orders)

	resp.List = orders

	return resp, nil
}

// AuditChangeOrder 审核采购换机订单
func AuditChangeOrder(begin *gorm.DB, req ErpPurchaseChangeOrder, state int) error {
	var commodities []ErpPurchaseChangeCommodity
	err := orm.Eloquent.Table("erp_purchase_change_commodity").Where("change_order_id = ?", req.ID).Find(&commodities).Error
	if err != nil {
		logger.Error("check erp_purchase_change_order err:", logger.Field("err", err))
		return err
	}

	if state == 1 { // 审核
		for i, _ := range commodities {
			if commodities[i].IMEIType == 2 || commodities[i].IMEIType == 3 { // 串码商品
				if commodities[i].OriginIMEI == "" {
					return errors.New("串码为空")
				}

				var imeiStockCommodity ErpStockCommodity
				err = orm.Eloquent.Table("erp_stock_commodity").Where("imei = ? and state = ?",
					commodities[i].OriginIMEI, InStock).Find(&imeiStockCommodity).Error
				if err != nil {
					return err
				}

				if imeiStockCommodity.ID == 0 {
					return errors.New("商品" + "[" + commodities[i].ErpCommodityName + "]库存不足")
				}

				if imeiStockCommodity.StoreId != req.StoreId {
					return errors.New("商品" + "[" + commodities[i].OriginIMEI + "]非所选门店库存，请检查")
				}

				err = begin.Table("erp_stock_commodity").Where("imei = ?", commodities[i].OriginIMEI).
					Updates(map[string]interface{}{
						"state":      PurchaseChange,
						"updated_at": time.Now(),
					}).Error // 状态更新为"采购换机"
				if err != nil {
					begin.Rollback()
					logger.Error("commodities err:", logger.Field("err", err))
					return err
				}

				// 新串码商品入库
				newStockCommodity := imeiStockCommodity
				newStockCommodity.ID = 0
				newStockCommodity.IMEI = commodities[i].NewIMEI
				newStockCommodity.StockSn = req.SerialNumber
				err = begin.Create(&newStockCommodity).Error
				if err != nil {
					begin.Rollback()
					logger.Error("create  purchase order err:", logger.Field("err", err))
					return err
				}
			} else {
				return errors.New("非串码商品不支持采购换货")
			}
		}
	} else if state == 2 { // 取消审核
		for i, _ := range commodities {
			// 查询新串码的库存情况
			var imeiStockCommodity ErpStockCommodity
			err = orm.Eloquent.Table("erp_stock_commodity").Where("imei = ? and state = ?",
				commodities[i].NewIMEI, InStock).Find(&imeiStockCommodity).Error
			if err != nil {
				return err
			}

			if imeiStockCommodity.ID == 0 {
				return errors.New("商品" + "[" + commodities[i].NewIMEI + "]不在库")
			}

			err = begin.Delete(imeiStockCommodity).Error // 删除新串码库存
			if err != nil {
				begin.Rollback()
				logger.Error("commodities err:", logger.Field("err", err))
				return err
			}

			// 更新旧串码为在库状态
			err = begin.Table("erp_stock_commodity").Where("imei = ?", commodities[i].OriginIMEI).
				Updates(map[string]interface{}{
					"state":      InStock,
					"updated_at": time.Now(),
				}).Error // 状态更新为"在库"
			if err != nil {
				begin.Rollback()
				logger.Error("commodities err:", logger.Field("err", err))
				return err
			}
		}
	}

	return nil
}

// 添加采购换机订单的商品信息
func changeOrderListSetCommodity(list []ErpPurchaseChangeOrder) {
	for i, _ := range list {
		list[i].SetCommodity()
	}
}

func (m *ErpPurchaseChangeOrder) SetCommodity() {
	var orderCommodities []ErpPurchaseChangeCommodity
	err := orm.Eloquent.Table("erp_purchase_change_commodity").Where("change_order_id = ?", m.ID).Find(&orderCommodities).Error
	if err != nil {
		logger.Error("SetCommodity query erp_purchase_change_commodity err:", logger.Field("err", err))
	}

	m.Commodities = orderCommodities
}
