package implments

import (
	baseDal "LAPP_ACURA_MOM_BACKEND/dao/base"
	jitDal "LAPP_ACURA_MOM_BACKEND/dao/jit"
	meDal "LAPP_ACURA_MOM_BACKEND/dao/me"
	dal "LAPP_ACURA_MOM_BACKEND/dao/pln"
	"LAPP_ACURA_MOM_BACKEND/db"
	"LAPP_ACURA_MOM_BACKEND/global"
	"LAPP_ACURA_MOM_BACKEND/grmi"
	baseMeta "LAPP_ACURA_MOM_BACKEND/meta/base"
	jitMeta "LAPP_ACURA_MOM_BACKEND/meta/jit"
	meMeta "LAPP_ACURA_MOM_BACKEND/meta/me"
	meta "LAPP_ACURA_MOM_BACKEND/meta/pln"
	jitModel "LAPP_ACURA_MOM_BACKEND/models/jit"
	model "LAPP_ACURA_MOM_BACKEND/models/pln"
	"LAPP_ACURA_MOM_BACKEND/utils"
	"fmt"
	"reflect"
	"strconv"
	"time"
)

// Check 南沙发运校验
func (impl *ToyotaCalloffServiceImplement) Check(user *global.User, barcode string) error {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	callOffDao := dal.NewToyotaCalloffDAO(session, user.PlantNr, user.UserId)
	// 按recordTime正序 查询已发运校验的callOff
	callOffData, err := callOffDao.SelectTopDesc([]grmi.Predicate{
		meta.ToyotaCalloff_CtrlPara1.NewPredicate(grmi.Equal, model.CALLOFF_STATUS_CHECKED),
	}, []grmi.Field{meta.ToyotaCalloff_RecordId})
	if err != nil {
		return grmi.NewBusinessError("查询已处理的顺引数据失败, 错误:" + err.Error())
	}
	var nextCallOff *model.ToyotaCalloff
	// 如果没有已发运校验的callOff 则直接按CheckSeq正序使用第一个
	if callOffData == nil {
		nextCallOff, err = callOffDao.SelectTopOne([]grmi.Predicate{
			meta.ToyotaCalloff_CtrlPara1.NewPredicate(grmi.Equal, model.CALLOFF_STATUS_UNCHECK),
			meta.ToyotaCalloff_Parsed.NewPredicate(grmi.GreaterOrEqual, model.CALLOFF_STATUS_PARSED),
		}, []grmi.Field{meta.ToyotaCalloff_RecordId})
	} else { // 根据callOff 查询下一个扫描的callOff

		nextSortNr := callOffData.CheckSequence + 1
		if nextSortNr > 999 {
			nextSortNr = 0
		}
		nextCallOff, err = callOffDao.SelectTopOne([]grmi.Predicate{
			meta.ToyotaCalloff_CtrlPara1.NewPredicate(grmi.Equal, model.CALLOFF_STATUS_UNCHECK),
			meta.ToyotaCalloff_Parsed.NewPredicate(grmi.GreaterOrEqual, model.CALLOFF_STATUS_PARSED),
			meta.ToyotaCalloff_CheckSequence.NewPredicate(grmi.Equal, nextSortNr),
		}, []grmi.Field{meta.ToyotaCalloff_CheckSequence})
		if err != nil {
			return grmi.NewBusinessError("查询待处理顺引数据失败, 错误:" + err.Error())
		}
	}

	if nextCallOff == nil {
		return grmi.NewBusinessError("不存在待校验的顺引数据")
	}
	// 如果条码长度=14 且前8位是时间 则是樱泰条码
	isAdient := true
	var checkBarcode string
	if len(barcode) == 14 {
		str := barcode[:8]
		_, err = time.Parse("20060102", str)
		if err == nil {
			isAdient = false
		}
	}
	// 如果是樱泰 取后三位是配置 校验
	if !isAdient {
		checkBarcode = barcode
		productFamilyId := barcode[len(barcode)-3:]
		if productFamilyId != nextCallOff.ProductFamilyId {
			return grmi.NewBusinessError(fmt.Sprintf("当前条码配置%s和顺引配置%s不符", productFamilyId, nextCallOff.ProductFamilyId))
		}
		if err = session.Begin(); err != nil {
			return grmi.NewBusinessError("开启事务失败, 错误:" + err.Error())
		}
	} else { // 如果是安道拓的 则校验包装单中所有座椅的配置 校验通过记录 校验状态和时间到包装单上
		productFamilyRelateDao := meDal.NewProductFamilyRelateDAO(session, user.PlantNr, user.UserId)
		packOrderItemDao := jitDal.NewPackOrderItemLstDAO(session, user.PlantNr, user.UserId)
		packOrderStatusDao := jitDal.NewPackOrderStatusDAO(session, user.PlantNr, user.UserId)
		packOrderDao := jitDal.NewPackOrderDAO(session, user.PlantNr, user.UserId)
		itemLi, err := packOrderItemDao.Select([]grmi.Predicate{
			jitMeta.PackOrderItemLst_SerialOrderId.NewPredicate(grmi.Equal, barcode),
			jitMeta.PackOrderItemLst_Status.NewPredicate(grmi.Equal, jitModel.PACK_STATUS_CLOSED),
		}, nil)
		if err != nil {
			return grmi.NewBusinessError("查询包装单数据失败， 错误:" + err.Error())
		}
		if len(itemLi) == 0 {
			return grmi.NewBusinessError("该条码不存在于包装单中")
		}
		packOrderId := itemLi[0].PackOrderId
		checkBarcode = packOrderId
		packOrderStatus, err := packOrderStatusDao.SelectOne(packOrderId)
		if err != nil {
			return grmi.NewBusinessError("查询包装单数据失败, 错误:" + err.Error())
		}
		if packOrderStatus == nil {
			return grmi.NewBusinessError("该条码的打包数据不存在, 包装单条码:" + packOrderId)
		}
		if packOrderStatus.ShipStatus == jitModel.SHIP_STATUS_CLOSED {
			return grmi.NewBusinessError("当前座椅归属包装单已发运")
		}
		if packOrderStatus.Status1 == jitModel.PACK_STATUS_CLOSED {
			return grmi.NewBusinessError("该包装单已校验过， 包装单条码:" + packOrderId)
		}
		packOrder, err := packOrderDao.SelectOne(packOrderId)
		if err != nil {
			return grmi.NewBusinessError("查询包装单数据失败, 错误:" + err.Error())
		}
		if packOrder == nil {
			return grmi.NewBusinessError("该条码的打包数据不存在, 包装单条码:" + packOrderId)
		}
		packOrderItemLi, err := packOrderItemDao.Select([]grmi.Predicate{
			jitMeta.PackOrderItemLst_PackOrderId.NewPredicate(grmi.Equal, packOrderId),
			jitMeta.PackOrderItemLst_Status.NewPredicate(grmi.Equal, jitModel.PACK_STATUS_CLOSED),
		}, nil)
		if err != nil {
			return grmi.NewBusinessError("查询包装单数据失败, 错误:" + err.Error())
		}
		productLi, err := productFamilyRelateDao.Select([]grmi.Predicate{
			meMeta.ProductFamilyRelate_ProductFamilyId.NewPredicate(grmi.Equal, nextCallOff.ProductFamilyId),
		}, nil)
		if err != nil {
			return grmi.NewBusinessError("查询派生配置数据失败, 错误:" + err.Error())
		}
		productMap := make(map[string]interface{})
		orderProductMap := make(map[string]interface{})
		for _, product := range productLi {
			productMap[product.ProductId] = nil
		}
		for _, packOrderItem := range packOrderItemLi {
			orderProductMap[packOrderItem.PartId] = nil
		}
		if len(productMap) != len(orderProductMap) {
			return grmi.NewBusinessError("包装配置与顺引配置不符")
		}
		for productId := range productMap {
			_, exist := orderProductMap[productId]
			if !exist {
				return grmi.NewBusinessError("包装配置与顺引配置不符")
			}
		}
		if err = session.Begin(); err != nil {
			return grmi.NewBusinessError("开启事务失败, 错误:" + err.Error())
		}
		packOrderStatus.Status1 = jitModel.PACK_STATUS_CLOSED
		err = packOrderStatusDao.UpdateOne(packOrderStatus)
		if err != nil {
			_ = session.Rollback()
			return err
		}
		packOrder.CtrlTime2 = grmi.DateTime(time.Now())
		err = packOrderDao.UpdateOne(packOrder)
		if err != nil {
			_ = session.Rollback()
			return err
		}
	}
	nextCallOff.CtrlPara1 = model.CALLOFF_STATUS_CHECKED
	nextCallOff.CtrlTime1 = grmi.DateTime(time.Now())
	nextCallOff.CheckBarcode = checkBarcode
	err = callOffDao.UpdateOne(nextCallOff)
	if err != nil {
		_ = session.Rollback()
		return err
	}
	_ = session.Commit()
	return err
}

// SelectAndPagingCheck 发运校验分页查询页面
func (impl *ToyotaCalloffServiceImplement) SelectAndPagingCheck(user *global.User, urlParameters map[string]string) (grmi.PagingResult, error) {

	grmi.Log(user, "/services/pln/implments/ToyotaCalloff.service.impl.go", "SelectToyotaCalloff", "查询ToyotaCalloff")

	condition := DefaultConditionOfToyotaCalloffAndPaging
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	_, exist := urlParameters["CtrlPara1"]
	if !exist {
		urlParameters["CtrlPara1"] = strconv.Itoa(model.CALLOFF_STATUS_UNCHECK)
	}
	predicates, err := condition.BuildPredicates(urlParameters)
	if err != nil {
		return grmi.EmptyPagingResult, err
	}
	start, exist := urlParameters["start"]
	if exist {
		p := grmi.Predicate{
			ColumnName: meta.ToyotaCalloff_CtrlTime1.ColumnName,
			PredicateType: func(predicate grmi.Predicate) (string, error) {
				return fmt.Sprintf(" and %s >= ?", predicate.ColumnName), nil
			},
			Values: []interface{}{start},
		}
		predicates = append(predicates, p)
	}
	end, exist := urlParameters["end"]
	if exist {
		p := grmi.Predicate{
			ColumnName: meta.ToyotaCalloff_CtrlTime1.ColumnName,
			PredicateType: func(predicate grmi.Predicate) (string, error) {
				return fmt.Sprintf(" and %s <= ?", predicate.ColumnName), nil
			},
			Values: []interface{}{end},
		}
		predicates = append(predicates, p)
	}

	checkBarcode, exist := urlParameters["checkBarcode"]
	if exist {
		// 如果条码长度=14 且前8位是时间 则是樱泰条码
		isAdient := true
		if len(checkBarcode) == 14 {
			str := checkBarcode[:8]
			_, err = time.Parse("20060102", str)
			if err == nil {
				isAdient = false
			}
		}
		if isAdient {
			packOrderItemDao := jitDal.NewPackOrderDAO(session, user.PlantNr, user.UserId)
			packOrderItemLi, err := packOrderItemDao.Select([]grmi.Predicate{
				jitMeta.PackOrderItemLst_SerialOrderId.NewPredicate(grmi.Equal, checkBarcode),
				jitMeta.PackOrderItemLst_Status.NewPredicate(grmi.Equal, jitModel.PACK_STATUS_CLOSED),
			}, nil)
			if err != nil {
				return grmi.EmptyPagingResult, err
			}
			packOrderId := packOrderItemLi[0].PackOrderId
			checkBarcode = packOrderId
		}
		p := grmi.Predicate{
			ColumnName: meta.ToyotaCalloff_CheckBarcode.ColumnName,
			PredicateType: func(predicate grmi.Predicate) (string, error) {
				return fmt.Sprintf(" and %s = ?", predicate.ColumnName), nil
			},
			Values: []interface{}{checkBarcode},
		}
		predicates = append(predicates, p)
	}
	p := grmi.Predicate{
		ColumnName: meta.ToyotaCalloff_Parsed.ColumnName,
		PredicateType: func(predicate grmi.Predicate) (string, error) {
			return fmt.Sprintf(" and %s >= ?", predicate.ColumnName), nil
		},
		Values: []interface{}{model.CALLOFF_STATUS_PARSED},
	}
	predicates = append(predicates, p)
	dao := dal.NewToyotaCalloffDAO(session, user.PlantNr, user.UserId)
	condition.Fill(urlParameters)
	result, err := dao.SelectAndPagingCheck(condition.Paging, predicates, []grmi.Field{meta.ToyotaCalloff_RecordId})
	if err != nil {
		return grmi.EmptyPagingResult, err
	}
	return result, nil
}

// ExportPageDataCheck 发运校验导出页面数据
func (impl *ToyotaCalloffServiceImplement) ExportPageDataCheck(user *global.User, urlParameters map[string]string) (filepath string, err error) {

	grmi.Log(user, "/services/pln/implments/ToyotaCalloff.service.impl.go", "SelectToyotaCalloff", "查询ToyotaCalloff")

	condition := DefaultConditionOfToyotaCalloffAndPaging
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	tolnameDao := baseDal.NewTabColNameDAO(session, user.UserId)
	_, exist := urlParameters["CtrPara1"]
	if !exist {
		urlParameters["CtrPara1"] = strconv.Itoa(model.CALLOFF_STATUS_UNCHECK)
	}
	predicates, err := condition.BuildPredicates(urlParameters)
	if err != nil {
		return "", err
	}
	start, exist := urlParameters["start"]
	if exist {
		start += " 00:00:00"
		_, err := time.ParseInLocation(grmi.DateTimeOutFormat, start, utils.TimezoneLocation)
		if err != nil {
			return "", grmi.NewBusinessError("开始日期格式错误")
		}
		p := grmi.Predicate{
			ColumnName: meta.ToyotaCalloff_CtrlTime1.ColumnName,
			PredicateType: func(predicate grmi.Predicate) (string, error) {
				return fmt.Sprintf(" and %s >= ?", predicate.ColumnName), nil
			},
			Values: []interface{}{start},
		}
		predicates = append(predicates, p)
	}
	end, exist := urlParameters["end"]
	if exist {
		end += " 23:59:59"
		_, err := time.ParseInLocation(grmi.DateTimeOutFormat, start, utils.TimezoneLocation)
		if err != nil {
			return "", grmi.NewBusinessError("结束日期格式错误")
		}
		p := grmi.Predicate{
			ColumnName: meta.ToyotaCalloff_CtrlTime1.ColumnName,
			PredicateType: func(predicate grmi.Predicate) (string, error) {
				return fmt.Sprintf(" and %s <= ?", predicate.ColumnName), nil
			},
			Values: []interface{}{end},
		}
		predicates = append(predicates, p)
	}

	checkBarcode, exist := urlParameters["checkBarcode"]
	if exist {
		// 如果条码长度=14 且前8位是时间 则是樱泰条码
		isAdient := true
		if len(checkBarcode) == 14 {
			str := checkBarcode[:8]
			_, err = time.Parse("20060102", str)
			if err != nil {
				isAdient = false
			}
		}
		if isAdient {
			packOrderItemDao := jitDal.NewPackOrderDAO(session, user.PlantNr, user.UserId)
			packOrderItemLi, err := packOrderItemDao.Select([]grmi.Predicate{
				jitMeta.PackOrderItemLst_SerialOrderId.NewPredicate(grmi.Equal, checkBarcode),
				jitMeta.PackOrderItemLst_Status.NewPredicate(grmi.Equal, jitModel.PACK_STATUS_CLOSED),
			}, nil)
			if err != nil {
				return "", err
			}
			packOrderId := packOrderItemLi[0].PackOrderId
			checkBarcode = packOrderId
		}
		p := grmi.Predicate{
			ColumnName: meta.ToyotaCalloff_CheckBarcode.ColumnName,
			PredicateType: func(predicate grmi.Predicate) (string, error) {
				return fmt.Sprintf(" and %s = ?", predicate.ColumnName), nil
			},
			Values: []interface{}{checkBarcode},
		}
		predicates = append(predicates, p)
	}
	p := grmi.Predicate{
		ColumnName: meta.ToyotaCalloff_Parsed.ColumnName,
		PredicateType: func(predicate grmi.Predicate) (string, error) {
			return fmt.Sprintf(" and %s >= ?", predicate.ColumnName), nil
		},
		Values: []interface{}{model.CALLOFF_STATUS_PARSED},
	}
	predicates = append(predicates, p)
	dao := dal.NewToyotaCalloffDAO(session, user.PlantNr, user.UserId)
	condition.Fill(urlParameters)
	result, err := dao.SelectAndPaging(condition.Paging, predicates, []grmi.Field{meta.ToyotaCalloff_RecordId})
	if err != nil {
		return "", err
	}
	data := result.Records.([]model.ToyotaCalloff)
	tabNameLi, err := tolnameDao.OriginSelect([]grmi.Predicate{
		baseMeta.TabColName_TabName.NewPredicate(grmi.Equal, "ToyotaCalloff"),
	}, nil)
	if err != nil {
		return "", grmi.NewBusinessError("查询翻译数据失败, 错误:" + err.Error())
	}
	tabNameMap := make(map[string]string)
	for _, item := range tabNameLi {
		tabNameMap[item.ColName] = item.TextLabel
	}
	stdefDao := baseDal.NewStdefDAO(session, user.UserId)
	stdefLi, err := stdefDao.Select([]grmi.Predicate{
		baseMeta.Stdef_StatId.NewPredicate(grmi.Equal, "PLN_ToyotaCalloff-Parsed"),
	}, nil)
	if err != nil {
		return "", grmi.NewBusinessError("查询翻译数据失败, 错误:" + err.Error())
	}
	stdefMap := make(map[string]string)
	for _, item := range stdefLi {
		stdefMap[item.StdefTyp] = item.Bez
	}
	li := make([]interface{}, 0, len(data))
	for _, item := range data {
		parsed, exist := stdefMap[strconv.Itoa(item.Parsed)]
		if !exist {
			parsed = strconv.Itoa(item.Parsed)
		}
		exportItem := model.ToyotaCalloffExcel{
			PlantNr:         item.PlantNr,
			DemandId:        item.DemandId,
			SupplierCode:    item.SupplierCode,
			ProjectId:       item.ProjectId,
			ProductFamilyId: item.ProductFamilyId,
			TotalQty:        item.TotalQty,
			CheckSequence:   item.CheckSequence,
			Parsed:          parsed,
			OrderTime:       item.OrderTime.Restore().Format(grmi.DateTimeOutFormat),
			OrderShift:      item.OrderShift,
		}
		li = append(li, exportItem)
	}
	head := make([]string, 0)
	var exportItem model.ToyotaCalloffExcel
	typeOf := reflect.TypeOf(exportItem)
	for i := 0; i < typeOf.NumField(); i++ {
		name, exist := tabNameMap[typeOf.Field(i).Name]
		if !exist {
			head = append(head, typeOf.Field(i).Name)
		} else {
			head = append(head, name)
		}
	}
	filepath, err = grmi.SaveExcelFile(li, head, "Sheet1", "顺引")
	return
}
