package implments

import (
	"LAPP_ACURA_MOM_BACKEND/common"
	baseDal "LAPP_ACURA_MOM_BACKEND/dao/base"
	meDal "LAPP_ACURA_MOM_BACKEND/dao/me"
	"LAPP_ACURA_MOM_BACKEND/db"
	"LAPP_ACURA_MOM_BACKEND/global"
	"LAPP_ACURA_MOM_BACKEND/grmi"
	"LAPP_ACURA_MOM_BACKEND/infra/logger"
	meMeta "LAPP_ACURA_MOM_BACKEND/meta/me"
	baseModel "LAPP_ACURA_MOM_BACKEND/models/base"
	channelModel "LAPP_ACURA_MOM_BACKEND/models/channel"
	model "LAPP_ACURA_MOM_BACKEND/models/pln"
	"LAPP_ACURA_MOM_BACKEND/utils"
	"fmt"
	"sort"
	"strconv"
	"strings"
	"time"
)

// GenerateCrossPlantTaskData 通过任务创建任务
func (impl *CustOrderServiceImplement) GenerateCrossPlantTaskData(task baseModel.CrossPlanTaskHead) error {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	user := &global.User{
		UserId: "CrossPlant",
		PlantNr: task.ToPlantNr,
	}
	productFamilyRelateDao := meDal.NewProductFamilyRelateDAO(session, user.PlantNr, user.UserId)
	productFamilyDao := meDal.NewProductFamilyDAO(session, user.PlantNr, user.UserId)
	snrDao := baseDal.NewSnrDAO(session, user.PlantNr, user.UserId)
	projectDao := meDal.NewProjectDAO(session, user.PlantNr, user.UserId)

	// 根据任务的物料 获取是哪个CarSet
	// 根据物料id排序 生成key
	productFamilyRelateLi, err := productFamilyRelateDao.Select([]grmi.Predicate{
	}, []grmi.Field{meMeta.ProductFamilyRelate_ProductFamilyId, meMeta.ProductFamilyRelate_ProductId})
	if err != nil {
		return grmi.NewBusinessError("查询派生总成关联关系失败")
	}
	artIdLi := strings.Split(task.ArtId, ";")
	if len(artIdLi) == 0 {
		return grmi.NewBusinessError("未获取需要生成工单的物料")
	}
	sort.Strings(artIdLi)
	var productFamilyKey string
	for index, artId := range artIdLi {
		if index != 0 {
			productFamilyKey += "-"
		}
		productFamilyKey += artId
	}
	productFamilyArtIdMap := make(map[string][]string)
	for _, productFamilyRelate := range productFamilyRelateLi {
		productFamilyArtIdMap[productFamilyRelate.ProductFamilyId] = append(productFamilyArtIdMap[productFamilyRelate.ProductFamilyId], productFamilyRelate.ProductId)
	}
	artProductFamilyMap := make(map[string][]interface{})
	for productFamilyId, artIdLi := range productFamilyArtIdMap {
		var productFamilyKey string
		for index, artId := range artIdLi {
			if index != 0 {
				productFamilyKey += "-"
			}
			productFamilyKey += artId
		}
		artProductFamilyMap[productFamilyKey] = append(artProductFamilyMap[productFamilyKey], productFamilyId)
	}
	productFamilyIdLi, exist := artProductFamilyMap[productFamilyKey]
	if !exist {
		return grmi.NewBusinessError("在该工厂下未获取到对应的派生")
	}
	productFamilyLi, err := productFamilyDao.Select([]grmi.Predicate{
		meMeta.ProductFamily_ProductFamilyId.NewPredicate(grmi.Include, productFamilyIdLi...),
		meMeta.ProductFamily_Enable.NewPredicate(grmi.Equal, true),
		meMeta.ProductFamily_MultiWorkLineToggle.NewPredicate(grmi.Equal, false),
	}, []grmi.Field{meMeta.ProductFamily_ProductFamilyId})
	if err != nil {
		return grmi.NewBusinessError("查询派生数据失败, 错误:" + err.Error())
	}
	if len(productFamilyLi) == 0 {
		return grmi.NewBusinessError("在该工厂下未获取到对应的派生")
	}
	productFamily := productFamilyLi[0]
	// 获取流水号
	project, err := projectDao.SelectOne(productFamily.ProjectId)
	if err != nil {
		return grmi.NewBusinessError("查询车型项目失败, 错误:" + err.Error())
	}
	if project == nil {
		return grmi.NewBusinessError("不存在对应的车型项目, 车型项目ID:" + productFamily.ProjectId)
	}
	if err = session.Begin(); err != nil {
		return grmi.NewBusinessError("开启事务失败, 错误:" + err.Error())
	}
	custOrderId, err := snrDao.GetNextSnr(project.CustOrderSnr)
	if err != nil {
		return grmi.NewBusinessError("生成客户订单流水号失败，错误:" + err.Error())
	}
	// 校验指定的生产产线 派生是否已经关联
	usedWorkLineId := productFamily.WorkLineId
	custOrder := model.CustOrder{
		SourceId: task.BusinessObjId,
		CustOrderId: custOrderId,
		ProductFamilyId: productFamily.ProductFamilyId,
		PartId: productFamily.ProductFamilyId,
		OrderType: baseModel.ORDER_TYPE_CROSS,
		OrderInfo: productFamily.ProductFamilyId,
		OrderTime: grmi.DateTime(time.Now()),
		ProjectId: task.ProjectId,
		ConfigValue: productFamily.ConfigValue,
		ModelValue: productFamily.ModelValue,
		ColorValue:  productFamily.ColorValue,
		PlanQty: task.PlanQty,
		WorkLineId: usedWorkLineId,
		QuantityPerHour: int(productFamily.Jph),
	}
	custOrder.OrderStatus = model.CustOrderStatus{
		CustOrderId: custOrderId,
		Status: baseModel.WO_STATUS_UNPLANNED,
	}
	custOrder.OrderQty = model.CustOrderQty{
		CustOrderId: custOrderId,
		PlanQty: task.PlanQty,
	}
	custOrderLi := []model.CustOrder{custOrder}
	if err = session.Begin(); err != nil {
		return err
	}

	now := time.Now()
	var start time.Time
	if task.PlanStartTime.Restore().Unix() > now.Unix() {
		start = task.PlanStartTime.Restore()
	} else {
		start = now
	}
	startDate, _ := time.ParseInLocation(grmi.DateOutFormat, start.Format(grmi.DateOutFormat), utils.TimezoneLocation)

	end := start.AddDate(0, 0, 7)
	custOrderLi, err = impl.AutoScheduler(user, session, productFamily.WorkLineId, startDate, end, custOrderLi)
	if err != nil {
		return err
	}
	_ = session.Commit()
	plantNr := user.PlantNr
	channel, exist := common.ReleaseTaskChannel[plantNr]
	if !exist {
		fmt.Println("通道不存在, 工厂号:" + strconv.Itoa(plantNr))
		return nil
	}
	mk := fmt.Sprintf("%d-%s", custOrderLi[0].PlantNr, custOrderLi[0].CustOrderId)
	common.ReleasingTaskMap.Store(mk, nil)
	err = channel.SendData(custOrderLi[0])
	if err != nil {
		fmt.Println("跨工厂发送数据出错:" + err.Error())
		return nil
	}
	return nil
}

// CrossPlantTask 跨工厂任务
func (impl *CustOrderServiceImplement) CrossPlantTask() error {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	userId := "scheduler"
	plantDao := baseDal.NewPlantDAO(session, userId)
	plantLi, err := plantDao.Select(nil, nil)
	if err != nil {
		return err
	}
	for _, plant := range plantLi {
		user := &global.User{
			PlantNr: plant.PlantNr,
			UserId:  userId,
		}
		taskHeadDao := baseDal.NewCrossPlanTaskHeadDAO(session, user.UserId)
		taskHeadLi, err := taskHeadDao.SelectUnAccomplishTask(plant.PlantNr)
		if err != nil {
			return err
		}
		channel, exist := common.CrossPlantTaskCustOrderChannel[plant.PlantNr]
		if !exist {
			channel = channelModel.NewTaskChannel("CrossPlantTask-Plant:" + strconv.Itoa(plant.PlantNr))
			common.CrossPlantTaskCustOrderChannel[plant.PlantNr] = channel
		}
		for _, taskHead := range taskHeadLi {
			err = channel.SendData(taskHead)
			if err != nil {
				return err
			}
		}
		go func(user *global.User) {
			impl.ExecuteCrossPlantTask(user)
		}(user)
	}
	return nil
}

// ExecuteCrossPlantTask 具体工厂里面的任务执行和数据生成
func (impl *CustOrderServiceImplement) ExecuteCrossPlantTask(user *global.User) {
	log, _ := logger.NewLogger("派工任务", "PLN")
	plantNr := user.PlantNr
	channel, exist := common.CrossPlantTaskCustOrderChannel[plantNr]
	if !exist {
		return
	}

	for {
		taskHeadInterface, ok, err := channel.Read()
		if err != nil {
			return
		}
		if !ok {
			continue
		}
		taskHead := taskHeadInterface.(baseModel.CrossPlanTaskHead)
		err = impl.GenerateCrossPlantTaskData(taskHead)
		engine := db.Eloquent.Master()
		session := engine.NewSession()
		taskHeadDao := baseDal.NewCrossPlanTaskHeadDAO(session, user.UserId)
		if err != nil {
			log.Error("派工异常, 错误:" + err.Error() + "，任务ID:" + strconv.Itoa(taskHead.TaskNr))
			taskHead.Status = baseModel.CROSS_TASK_STATUS_ERROR
			taskHead.ErrorMsg = err.Error()
			_ = taskHeadDao.UpdateOne(&taskHead)
			channel.Close()
			return
		} else {
			taskHead.Status = baseModel.CROSS_TASK_STATUS_ACCOMPLISHED
			_ = taskHeadDao.UpdateOne(&taskHead)
		}
	}
}