// Copyright (c) Shenyang Leading Edge Intelligent Technology Co., Ltd. All rights reserved.

package implments

import (
	dal "LAPP_LF_MOM_BACKEND/dao/om"
	"LAPP_LF_MOM_BACKEND/db"
	"LAPP_LF_MOM_BACKEND/grmi"
	"LAPP_LF_MOM_BACKEND/infra/logger"
	meta "LAPP_LF_MOM_BACKEND/meta/om"
	baseModel "LAPP_LF_MOM_BACKEND/models/base"
	model "LAPP_LF_MOM_BACKEND/models/om"
	"LAPP_LF_MOM_BACKEND/web/models"
	"strconv"
	"strings"
	"time"
)

/******************************************************************************
 *
 * @Description              : SerialOrder的默认查询条件
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-04-20 13:07:32
 *
 ******************************************************************************/
var DefaultConditionOfSerialOrder = grmi.NewCondition(
	map[string]grmi.ConditionItem{
		meta.SerialOrder_WorkOrderId.UrlParameterName:    grmi.NewConditionItem(meta.SerialOrder_WorkOrderId, grmi.Equal, true),
		meta.SerialOrder_SerialOrderId.UrlParameterName:  grmi.NewConditionItem(meta.SerialOrder_SerialOrderId, grmi.Equal, true),
		meta.SerialOrder_ArtId.UrlParameterName:          grmi.NewConditionItem(meta.SerialOrder_ArtId, grmi.Equal, false),
		meta.SerialOrder_OrderType.UrlParameterName:      grmi.NewConditionItem(meta.SerialOrder_OrderType, grmi.Equal, false),
		meta.SerialOrder_OrderType1.UrlParameterName:     grmi.NewConditionItem(meta.SerialOrder_OrderType1, grmi.Equal, false),
		meta.SerialOrder_OrderType2.UrlParameterName:     grmi.NewConditionItem(meta.SerialOrder_OrderType2, grmi.Equal, false),
		meta.SerialOrder_PlanResourceId.UrlParameterName: grmi.NewConditionItem(meta.SerialOrder_PlanResourceId, grmi.Equal, false),
		meta.SerialOrder_UsedResourceId.UrlParameterName: grmi.NewConditionItem(meta.SerialOrder_UsedResourceId, grmi.Equal, false),
		meta.SerialOrder_PlanQty.UrlParameterName:        grmi.NewConditionItem(meta.SerialOrder_PlanQty, grmi.Equal, false),
		meta.SerialOrder_QtyUomId.UrlParameterName:       grmi.NewConditionItem(meta.SerialOrder_QtyUomId, grmi.Equal, false),
		meta.SerialOrder_OpTimePerItem.UrlParameterName:  grmi.NewConditionItem(meta.SerialOrder_OpTimePerItem, grmi.Equal, false),
		meta.SerialOrder_TimeUomId.UrlParameterName:      grmi.NewConditionItem(meta.SerialOrder_TimeUomId, grmi.Equal, false),
		meta.SerialOrder_PlanStartDate.UrlParameterName:  grmi.NewConditionItem(meta.SerialOrder_PlanStartDate, grmi.Approximate, false),
		meta.SerialOrder_PlanEndDate.UrlParameterName:    grmi.NewConditionItem(meta.SerialOrder_PlanEndDate, grmi.Approximate, false),
		meta.SerialOrder_SetupStartTime.UrlParameterName: grmi.NewConditionItem(meta.SerialOrder_SetupStartTime, grmi.Approximate, false),
		meta.SerialOrder_SetupEndTime.UrlParameterName:   grmi.NewConditionItem(meta.SerialOrder_SetupEndTime, grmi.Approximate, false),
		meta.SerialOrder_PlanStartTime.UrlParameterName:  grmi.NewConditionItem(meta.SerialOrder_PlanStartTime, grmi.Approximate, false),
		meta.SerialOrder_PlanEndTime.UrlParameterName:    grmi.NewConditionItem(meta.SerialOrder_PlanEndTime, grmi.Approximate, false),
		meta.SerialOrder_ActStartTime.UrlParameterName:   grmi.NewConditionItem(meta.SerialOrder_ActStartTime, grmi.Approximate, false),
		meta.SerialOrder_ActEndTime.UrlParameterName:     grmi.NewConditionItem(meta.SerialOrder_ActEndTime, grmi.Approximate, false),
		meta.SerialOrder_ProjectId.UrlParameterName:      grmi.NewConditionItem(meta.SerialOrder_ProjectId, grmi.Equal, false),
		meta.SerialOrder_LastModify.UrlParameterName:     grmi.NewConditionItem(meta.SerialOrder_LastModify, grmi.Approximate, false),
		meta.SerialOrder_LastUser.UrlParameterName:       grmi.NewConditionItem(meta.SerialOrder_LastUser, grmi.Equal, false),
		meta.SerialOrder_CreateTime.UrlParameterName:     grmi.NewConditionItem(meta.SerialOrder_CreateTime, grmi.Approximate, false),
	},
	nil,
)

/******************************************************************************
 *
 * @Description              : SerialOrder的默认分页查询条件
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-04-20 13:07:32
 *
 ******************************************************************************/
var DefaultConditionOfSerialOrderAndPaging = grmi.NewCondition(
	DefaultConditionOfSerialOrder.Items,
	grmi.NewPaging(),
)

/******************************************************************************
 *
 * @Struct Name              : SerialOrderServiceImplement
 *-----------------------------------------------------------------------------
 *
 * @Description              : SerialOrder的服务实现
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-04-20 13:07:32
 *
 ******************************************************************************/
type SerialOrderServiceImplement struct {
}

/******************************************************************************
 *
 * @Function Name            : NewSerialOrderDAOImplement
 *-----------------------------------------------------------------------------
 *
 * @Description              : 创建一个SerialOrderDAOImplement实例
 *
 * @Return Value             : SerialOrderDAOImplement实例
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-04-20 13:07:32
 *
 ******************************************************************************/
func NewSerialOrderServiceImplement() *SerialOrderServiceImplement {
	return &SerialOrderServiceImplement{}
}

/******************************************************************************
 *
 * @Reference LAPP_LF_MOM_BACKEND/services/om/SerialOrderService.InsertOne
 *
 ******************************************************************************/
func (impl *SerialOrderServiceImplement) InsertOne(user *models.Usertab, entity *model.SerialOrder) error {

	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "InsertOneSerialOrder", "插入一个SerialOrder")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewSerialOrderDAO(session, user.Pid, user.Userid)
	record, err := dao.SelectOne(entity.WorkOrderId, entity.SerialOrderId)
	if err != nil {
		return err
	}
	if record != nil {
		return grmi.NewBusinessError("已经存在相同主键的记录!")
	}
	err = dao.InsertOne(entity)
	if err != nil {
		return err
	}
	return nil
}

/******************************************************************************
 *
 * @Reference LAPP_LF_MOM_BACKEND/services/om/SerialOrderService.DeleteOne
 *
 ******************************************************************************/
func (impl *SerialOrderServiceImplement) DeleteOne(user *models.Usertab, workOrderId string, serialOrderId string) error {

	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "DeleteOneSerialOrder", "删除一个SerialOrder")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewSerialOrderDAO(session, user.Pid, user.Userid)
	record, err := dao.SelectOne(workOrderId, serialOrderId)
	if err != nil {
		return err
	}
	if record == nil {
		return grmi.NewBusinessError("不存在指定记录!")
	}
	err = dao.DeleteOne(workOrderId, serialOrderId)
	if err != nil {
		return err
	}
	return nil
}

/******************************************************************************
 *
 * @Reference LAPP_LF_MOM_BACKEND/services/om/SerialOrderService.SelectOne
 *
 ******************************************************************************/
func (impl *SerialOrderServiceImplement) SelectOne(user *models.Usertab, workOrderId string, serialOrderId string) (*model.SerialOrder, error) {

	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "SelectOneSerialOrder", "查询一个SerialOrder")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewSerialOrderDAO(session, user.Pid, user.Userid)
	result, err := dao.SelectOne(workOrderId, serialOrderId)
	if err != nil {
		return nil, err
	}
	return result, nil
}

/******************************************************************************
 *
 * @Reference LAPP_LF_MOM_BACKEND/services/om/SerialOrderService.UpdateOne
 *
 ******************************************************************************/
func (impl *SerialOrderServiceImplement) UpdateOne(user *models.Usertab, entity *model.SerialOrder) error {

	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "UpdateOneSerialOrder", "修改一个SerialOrder")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewSerialOrderDAO(session, user.Pid, user.Userid)
	record, err := dao.SelectOne(entity.WorkOrderId, entity.SerialOrderId)
	if err != nil {
		return err
	}
	if record == nil {
		return grmi.NewBusinessError("不存在指定记录!")
	}
	err = dao.UpdateOne(entity)
	if err != nil {
		return err
	}
	return nil
}

/******************************************************************************
 *
 * @Reference LAPP_LF_MOM_BACKEND/services/om/SerialOrderService.Insert
 *
 ******************************************************************************/
func (impl *SerialOrderServiceImplement) Insert(user *models.Usertab, entities *[]model.SerialOrder) error {

	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "InsertSerialOrder", "插入多个SerialOrder")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewSerialOrderDAO(session, user.Pid, user.Userid)

	for _, entity := range *entities {
		record, err := dao.SelectOne(entity.WorkOrderId, entity.SerialOrderId)
		if err != nil {
			return err
		}
		if record != nil {
			return grmi.NewBusinessError("已经存在相同主键的记录!")
		}
	}

	err := dao.Insert(entities)
	if err != nil {
		return err
	}
	return nil
}

/******************************************************************************
 *
 * @Reference LAPP_LF_MOM_BACKEND/services/om/SerialOrderService.Delete
 *
 ******************************************************************************/
func (impl *SerialOrderServiceImplement) Delete(user *models.Usertab, entities *[]model.SerialOrder) error {

	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "DeleteSerialOrder", "删除多个SerialOrder")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewSerialOrderDAO(session, user.Pid, user.Userid)

	for _, entity := range *entities {
		record, err := dao.SelectOne(entity.WorkOrderId, entity.SerialOrderId)
		if err != nil {
			return err
		}
		if record == nil {
			return grmi.NewBusinessError("不存在指定记录!")
		}
	}

	err := dao.Delete(entities)
	if err != nil {
		return err
	}
	return nil
}

/******************************************************************************
 *
 * @Reference LAPP_LF_MOM_BACKEND/services/om/SerialOrderService.Select
 *
 ******************************************************************************/
func (impl *SerialOrderServiceImplement) Select(user *models.Usertab, urlParameters map[string]string) (interface{}, error) {

	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "SelectSerialOrder", "查询SerialOrder")

	condition := DefaultConditionOfSerialOrderAndPaging
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	predicates, err := condition.BuildPredicates(urlParameters)
	if err != nil {
		return nil, err
	}
	dao := dal.NewSerialOrderDAO(session, user.Pid, user.Userid)
	if condition.Fill(urlParameters) {
		result, err := dao.SelectAndPaging(condition.Paging, predicates, condition.OrderByFields)
		if err != nil {
			return nil, err
		}
		return result, nil
	} else {
		result, err := dao.Select(predicates, condition.OrderByFields)
		if err != nil {
			return nil, err
		}
		return result, nil
	}
}

/******************************************************************************
 *
 * @Reference LAPP_LF_MOM_BACKEND/services/om/SerialOrderService.Update
 *
 ******************************************************************************/
func (impl *SerialOrderServiceImplement) Update(user *models.Usertab, entities *[]model.SerialOrder) error {

	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "UpdateSerialOrder", "修改多个SerialOrder")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewSerialOrderDAO(session, user.Pid, user.Userid)

	for _, entity := range *entities {
		record, err := dao.SelectOne(entity.WorkOrderId, entity.SerialOrderId)
		if err != nil {
			return err
		}
		if record == nil {
			return grmi.NewBusinessError("不存在指定记录!")
		}
	}

	err := dao.Update(entities)
	if err != nil {
		return err
	}
	return nil
}

/******************************************************************************
 *
 * @Reference LAPP_LF_MOM_BACKEND/services/om/SerialOrderService.InsertFromWorkOrder
 *
 ******************************************************************************/
func (impl *SerialOrderServiceImplement) InsertFromWorkOrder(user *models.Usertab, workOrderIds []string) ([]model.LockedResponseWorkOrder, error) {
	log, _ := logger.NewLogger(user.Userid, "OM")
	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "UpdateSerialOrder", "修改多个SerialOrder")
	result := make([]model.LockedResponseWorkOrder, 0, len(workOrderIds))
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	err := session.Begin()
	if err != nil {
		return nil, err
	}
	defer session.Close()
	dao := dal.NewSerialOrderDAO(session, user.Pid, user.Userid)
	workOrderDao := dal.NewWorkOrderDAO(session, user.Pid, user.Userid)
	workOrderStatusDao := dal.NewWorkOrderStatusDAO(session, user.Pid, user.Userid)
	workOrderStatusRecDao := dal.NewWorkOrderStatusRecLstDAO(session, user.Pid, user.Userid)
	serialOrderStatusDao := dal.NewSerialOrderStatusDAO(session, user.Pid, user.Userid)

	for _, workOrderId := range workOrderIds {
		workOrder, err := workOrderDao.SelectOne(workOrderId)
		if err != nil {
			return nil, err
		}
		if workOrder == nil {
			return nil, grmi.NewBusinessError("不存在对应的workOrder, workOrderId:" + workOrderId)
		}
		workOrderStatus, err := workOrderStatusDao.SelectOne(workOrderId)
		if err != nil {
			return nil, err
		}
		if workOrderStatus == nil {
			return nil, grmi.NewBusinessError("不存在对应的workOrderStatus, workOrderId:" + workOrderId)
		}
		if workOrderStatus.Status != baseModel.WO_STATUS_PLANNED {
			return nil, grmi.NewBusinessError("对应的workOrderStatus 不是 WO_STATUS_PLANNED，workOrderId:" + workOrderId)
		}
		serialOrderLi, err := dao.Select([]grmi.Predicate{meta.SerialOrder_WorkOrderId.NewPredicate(grmi.Equal, workOrderId)}, nil)
		if err != nil {
			return nil, err
		}
		if len(serialOrderLi) > 0 {
			return nil, grmi.NewBusinessError("已存在对应的SerialOrder, workOrderId:" + workOrderId)
		}
		serialOrderLi = make([]model.SerialOrder, 0, int(workOrder.PlanQty))
		serialOrderStatusLi := make([]model.SerialOrderStatus, 0, int(workOrder.PlanQty))
		if workOrder.PlanQty == 0 {
			return nil, grmi.NewBusinessError("订单的计划数量为0,workOrderID:" + workOrderId)
		}
		endTime := workOrder.PlanEndTime.Restore()
		now := time.Now()
		var perDuration float64
		if !now.Before(endTime) {
			perDuration = 0
		} else {
			perDuration = endTime.Sub(now).Seconds() / workOrder.PlanQty
		}
		for i := 0; i < int(workOrder.PlanQty); i++ {
			log.Debug("InsertFromWorkOrder for work order planQty")
			snr := new(models.Snrtab)
			snr.Finr = user.Pid
			serialNum, err := snr.GetNextSnrWithSession(session, "SerialOrder")
			if err != nil {
				_ = session.Rollback()
				log.Error("InsertFromWorkOrder SerialOrder InsertFromWorkOrder generate serial order id failed, error: " + err.Error())
				return nil, err
			}
			planStartDate := workOrder.PlanStartDate.Restore().Format("20060102")
			prefix := workOrder.ArtId + baseModel.PlantName + planStartDate
			serialOrderId := strings.Replace(serialNum, "SO-", prefix, 1)
			var planEndTime time.Time
			if perDuration != 0 {
				planEndTime = now.Add(time.Duration(perDuration*float64(i+1)) * time.Second)
			} else {
				planEndTime = workOrder.PlanEndTime.Restore()
			}
			serialOrder := model.SerialOrder{
				WorkOrderId:    workOrderId,
				SerialOrderId:  serialOrderId,
				ArtId:          workOrder.ArtId,
				OrderType1:     workOrder.OrderType1,
				OrderType2:     workOrder.OrderType2,
				PlanResourceId: workOrder.PlanResourceId,
				UsedResourceId: workOrder.UsedResourceId,
				PlanQty:        1,
				QtyUomId:       workOrder.QtyUomId,
				OpTimePerItem:  workOrder.OpTimePerItem,
				TimeUomId:      workOrder.TimeUomId,
				PlanStartDate:  workOrder.PlanStartDate,
				PlanEndDate:    workOrder.PlanEndDate,
				SetupStartTime: workOrder.SetupStartTime,
				SetupEndTime:   workOrder.SetupEndTime,
				PlanStartTime:  workOrder.PlanStartTime,
				PlanEndTime:    grmi.DateTime(planEndTime),
				ActStartTime:   workOrder.ActStartTime,
				ActEndTime:     workOrder.ActEndTime,
				ProjectId:      workOrder.ProjectId,
			}
			serialOrderLi = append(serialOrderLi, serialOrder)
			serialStatus := model.SerialOrderStatus{
				Status:        baseModel.WO_STATUS_LOCKED,
				SerialOrderId: serialOrderId,
			}
			serialOrderStatusLi = append(serialOrderStatusLi, serialStatus)
		}
		log.Debug("InsertFromWorkOrder SerialOrder insert serial order, workOrderID:"+workOrderId+" length: "+strconv.Itoa(len(serialOrderLi))+" workOrder.PlanQty: ", strconv.Itoa(int(workOrder.PlanQty)))
		for _, serialOrder := range serialOrderLi {
			err = dao.InsertOne(&serialOrder)
			if err != nil {
				log.Error("InsertFromWorkOrder SerialOrder Insert serialOrder failed, error: " + err.Error())
				session.Rollback()
				return nil, err
			}
		}
		for _, serialOrderStatus := range serialOrderStatusLi {
			err = serialOrderStatusDao.InsertOne(&serialOrderStatus)
			if err != nil {
				log.Error("InsertFromWorkOrder SerialOrder Insert serialOrderStatus failed, error: " + err.Error())
				session.Rollback()
				return nil, err
			}
		}

		//err = dao.Insert(&serialOrderLi)
		//if err != nil {
		//	log.Error("InsertFromWorkOrder SerialOrder Insert serialOrderLi failed, error: " + err.Error())
		//	session.Rollback()
		//	return nil, err
		//}

		//err = serialOrderStatusDao.Insert(&serialOrderStatusLi)
		//if err != nil {
		//	log.Error("InsertFromWorkOrder SerialOrder Insert serialOrderStatusLi failed, error: " + err.Error())
		//	session.Rollback()
		//	return nil, err
		//}
		workOrderStatusRec := model.WorkOrderStatusRecLst{
			WorkOrderId:        workOrderId,
			PrevStatus:         workOrderStatus.Status,
			Status:             baseModel.WO_STATUS_LOCKED,
			StartTime:          workOrder.PlanStartTime,
			EndTime:            workOrder.PlanEndTime,
			OutputEvent:        baseModel.BATORD_EVENT_LOCK,
			OutputStatus:       baseModel.OUTPUT_TRIGGER_UNHANDLED,
			TriggerObjectId:    workOrderStatus.TriggerObjectId,
			TriggerSubObjectId: workOrderStatus.TriggerSubObjectId,
		}
		err = workOrderStatusRecDao.InsertOne(&workOrderStatusRec)
		if err != nil {
			log.Error("InsertFromWorkOrder SerialOrder workOrderStatusRecDao InsertOne failed, error: " + err.Error())
			session.Rollback()
			return nil, err
		}
		workOrderStatus.Status = baseModel.WO_STATUS_LOCKED
		err = workOrderStatusDao.UpdateOne(workOrderStatus)
		if err != nil {
			log.Error("InsertFromWorkOrder SerialOrder workOrderStatusDao UpdateOne failed, error: " + err.Error())
			session.Rollback()
			return nil, err
		}
		lockedWorkOrder := model.LockedResponseWorkOrder{WorkOrderId: workOrderId, Status: baseModel.WO_STATUS_LOCKED}
		result = append(result, lockedWorkOrder)
	}
	session.Commit()
	return result, nil
}
