package cn.estsh.i3plus.ext.mes.pcn.apiservice.serviceimpl.busi;

import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesConfigService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesEmergencyLocationLogService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesEmergencyLocationService;
import cn.estsh.i3plus.ext.mes.pcn.api.busi.IMesWorkOrderExtService;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.util.MesPcnException;
import cn.estsh.i3plus.ext.mes.pcn.apiservice.util.StringUtilExt;
import cn.estsh.i3plus.ext.mes.pcn.pojo.model.MesEmergencyLocationModel;
import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtConstWords;
import cn.estsh.i3plus.mes.pcn.util.DateUtil;
import cn.estsh.i3plus.platform.common.convert.ConvertBean;
import cn.estsh.i3plus.platform.common.tool.TimeTool;
import cn.estsh.i3plus.pojo.base.bean.DdlPackBean;
import cn.estsh.i3plus.pojo.base.enumutil.CommonEnumUtil;
import cn.estsh.i3plus.pojo.base.tool.DdlPreparedPack;
import cn.estsh.i3plus.pojo.base.util.StringUtil;
import cn.estsh.i3plus.pojo.mes.bean.MesConfig;
import cn.estsh.i3plus.pojo.mes.bean.MesEmergencyLocation;
import cn.estsh.i3plus.pojo.mes.bean.MesWorkOrder;
import cn.estsh.i3plus.pojo.mes.repository.MesConfigRepository;
import cn.estsh.i3plus.pojo.mes.repository.MesEmergencyLocationRepository;
import cn.estsh.i3plus.pojo.mes.util.MesExtEnumUtil;
import cn.estsh.impp.framework.boot.util.ValidatorBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

/**
 * @Description : 应急件库位管理
 * @Reference :
 * @Author : junsheng.li
 * @CreateDate 2024/10/17 16:23
 * @Modify:
 **/
@Slf4j
@Service
public class MesEmergencyLocationServiceImpl implements IMesEmergencyLocationService {

    @Autowired
    private MesEmergencyLocationRepository mesEmergencyLocationRepository;

    @Autowired
    private IMesEmergencyLocationLogService mesEmergencyLocationLogService;

    @Autowired
    private IMesWorkOrderExtService mesWorkOrderExtService;

    @Autowired
    private IMesConfigService mesConfigService;

    @Autowired
    private MesConfigRepository mesConfigRepository;

    @Override
    public List<MesEmergencyLocation> findMesEmergencyLocationList(String organizeCode, String workCenterCode) {
        if (StringUtil.isEmptyAndNull(organizeCode) || StringUtil.isEmptyAndNull(workCenterCode)) {
            return null;
        }
        List<MesEmergencyLocation> emergencyLocationList = findMesEmergencyLocationList(organizeCode, CommonEnumUtil.VALID, workCenterCode);
        if(CollectionUtils.isEmpty(emergencyLocationList)){
            return emergencyLocationList;
        }
        int remindDay = Integer.parseInt(mesConfigService.getCfgValue(organizeCode, MesPcnExtConstWords.REMIND_DAY));
        //超过提醒天数标记黄色
        emergencyLocationList.forEach(location -> {
            if (!StringUtil.isEmpty(location.getInDate()) && new Date().compareTo(DateUtil.addDays(location.getInDate(), remindDay)) > MesPcnExtConstWords.ZERO) {
                location.setColor(MesExtEnumUtil.COLOR.YELLOW.getValue());
            }
        });
        return emergencyLocationList;
    }

    @Override
    public void doAction(MesEmergencyLocationModel model) {
        switch (model.getType()) {
            //入库
            case 10: doStockInOnline(model);break;
            //出库
            case 20: doStockOutOnline(model);break;
            //GP12
            case 30: doGpInspectionOnline(model);break;
            //设置
            case 40: doEmergencySinkLocationSettingOnline(model);break;
            default: MesPcnException.throwMesBusiException("扫描类型【%s】不存在", model.getType());break;
        }
    }

    @Override
    public void doShippingStockOutOnline(String organizeCode, String workOrderNo, String userName, boolean isShipping) {
        if (StringUtil.isEmpty(organizeCode) || StringUtil.isEmpty(workOrderNo)) return;
        //校验加工单信息
        MesEmergencyLocation locationWorkOrder = getMesEmergencyLocation(organizeCode, workOrderNo, null, isShipping);
        if (Objects.isNull(locationWorkOrder)) return;

        locationWorkOrder.setOutDate(TimeTool.getNowTime(true));
        locationWorkOrder.setStockType(MesExtEnumUtil.EMERGENCY_LOCATION_STOCK_TYPE.EMERGENCY_LOCATION_STOCK_TYPE_20.getValue());
        ConvertBean.serviceModelUpdate(locationWorkOrder, userName);
        //记录日志
        mesEmergencyLocationLogService.insertMesEmergencyLocationLog(locationWorkOrder);
        //数据解绑
        locationWorkOrder.setWorkOrderNo(MesPcnExtConstWords.EMPTY);
        locationWorkOrder.setOfflineDate(MesPcnExtConstWords.EMPTY);
        locationWorkOrder.setCustPartNo(MesPcnExtConstWords.EMPTY);
        locationWorkOrder.setPartName(MesPcnExtConstWords.EMPTY);
        locationWorkOrder.setInDate(MesPcnExtConstWords.EMPTY);
        locationWorkOrder.setOutDate(MesPcnExtConstWords.EMPTY);
        locationWorkOrder.setVehicleNo(MesPcnExtConstWords.EMPTY);
        locationWorkOrder.setSystemSyncStatus(CommonEnumUtil.FALSE);
        mesEmergencyLocationRepository.update(locationWorkOrder);
    }

    private List<MesEmergencyLocation> findMesEmergencyLocationList(String organizeCode, Integer status, String workCenterCode) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(workCenterCode, MesPcnExtConstWords.WORK_CENTER_CODE, packBean);
        DdlPreparedPack.getNumEqualPack(status, MesPcnExtConstWords.STATUS, packBean);
        DdlPreparedPack.getOrderByPack(new Object[]{CommonEnumUtil.ASC_OR_DESC.ASC.getValue()}, new String[]{MesPcnExtConstWords.LOCATION_NUMBER}, packBean);
        return mesEmergencyLocationRepository.findByHqlWhere(packBean);
    }

    private void doStockInOnline(MesEmergencyLocationModel model) {
        ValidatorBean.checkNotNull(model.getLocation(), "库位不能为空");
        ValidatorBean.checkNotNull(model.getWorkOrderNo(), "加工单号不能为空");
        //校验库位信息
        MesEmergencyLocation location = getMesEmergencyLocation(model.getOrganizeCode(), model.getWorkCenterCode(), model.getLocation(), null);
        checkLocation(model, location);
        //校验加工单
        MesWorkOrder workOrder = mesWorkOrderExtService.getWorkOrder(model.getOrganizeCode(), model.getWorkOrderNo());
        checkWorkOrderNo(model, workOrder);
        //数据绑定
        location.setWorkOrderNo(workOrder.getWorkOrderNo());
        location.setOfflineDate(workOrder.getOfflineTime());
        location.setCustPartNo(workOrder.getCustPartNo());
        location.setPartName(workOrder.getPartName());
        location.setInDate(TimeTool.getNowTime(true));
        location.setVehicleNo(workOrder.getCarModelCode());
        location.setStockType(MesExtEnumUtil.EMERGENCY_LOCATION_STOCK_TYPE.EMERGENCY_LOCATION_STOCK_TYPE_10.getValue());
        location.setSystemSyncStatus(CommonEnumUtil.FALSE);
        ConvertBean.serviceModelUpdate(location, model.getUserName());
        //记录日志
        mesEmergencyLocationLogService.insertMesEmergencyLocationLog(location);

        mesEmergencyLocationRepository.update(location);
    }

    private void doStockOutOnline(MesEmergencyLocationModel model) {
        ValidatorBean.checkNotNull(model.getWorkOrderNo(), "加工单号不能为空");
        doShippingStockOutOnline(model.getOrganizeCode(), model.getWorkOrderNo(), model.getUserName(), false);
    }

    private void doGpInspectionOnline(MesEmergencyLocationModel model) {
        ValidatorBean.checkNotNull(model.getWorkOrderNo(), "加工单号不能为空");
        //校验加工单信息
        MesWorkOrder workOrder = mesWorkOrderExtService.getWorkOrder(model.getOrganizeCode(), model.getWorkOrderNo());
        if (Objects.isNull(workOrder)) {
            MesPcnException.throwMesBusiException("加工单【%s】信息不存在", model.getWorkOrderNo());
        }
        MesEmergencyLocation locationWorkOrder = getMesEmergencyLocation(model.getOrganizeCode(), model.getWorkOrderNo(), model.getWorkCenterCode(), false);
        if (MesExtEnumUtil.EMERGENCY_LOCATION_STOCK_TYPE.EMERGENCY_LOCATION_STOCK_TYPE_30.getValue() == locationWorkOrder.getStockType()) {
            locationWorkOrder.setStockType(MesExtEnumUtil.EMERGENCY_LOCATION_STOCK_TYPE.EMERGENCY_LOCATION_STOCK_TYPE_40.getValue());
        } else {
            locationWorkOrder.setStockType(MesExtEnumUtil.EMERGENCY_LOCATION_STOCK_TYPE.EMERGENCY_LOCATION_STOCK_TYPE_30.getValue());
        }
        ConvertBean.serviceModelUpdate(locationWorkOrder, model.getUserName());
        //记录日志
        mesEmergencyLocationLogService.insertMesEmergencyLocationLog(locationWorkOrder);
        //应急件库位管理更新
        mesEmergencyLocationRepository.update(locationWorkOrder);
    }


    private void doEmergencySinkLocationSettingOnline(MesEmergencyLocationModel model) {
        ValidatorBean.checkNotNull(model.getLocationNumber(), "库位数不能为空");
        ValidatorBean.checkNotNull(model.getRemindDay(), "提醒天数不能为空");
        List<MesEmergencyLocation> locationList = findMesEmergencyLocationList(model.getOrganizeCode(), null, model.getWorkCenterCode());
        //更新系统参数
        updateMesConfig(model);

        int lastNumber = 0;
        if (!CollectionUtils.isEmpty(locationList)) {
            lastNumber = locationList.get(locationList.size() - MesPcnExtConstWords.ONE).getLocationNumber();
            if (locationList.size() > model.getLocationNumber()) {
                //禁用多于库位
                DdlPackBean packBean = DdlPackBean.getDdlPackBean(model.getOrganizeCode());
                DdlPreparedPack.getStringEqualPack(model.getWorkCenterCode(), MesPcnExtConstWords.WORK_CENTER_CODE, packBean);
                DdlPreparedPack.getNumEqualPack(CommonEnumUtil.VALID, MesPcnExtConstWords.STATUS, packBean);
                DdlPreparedPack.getNumberBiggerPack(model.getLocationNumber(), MesPcnExtConstWords.LOCATION_NUMBER, packBean);
                mesEmergencyLocationRepository.updateByProperties(new String[]{MesPcnExtConstWords.MODIFY_USER, MesPcnExtConstWords.MODIFY_DATE_TIME, MesPcnExtConstWords.STATUS},
                        new Object[]{model.getUserName(), TimeTool.getNowTime(true), CommonEnumUtil.FALSE}, packBean);
                //解除小于库位
                packBean = DdlPackBean.getDdlPackBean(model.getOrganizeCode());
                DdlPreparedPack.getStringEqualPack(model.getWorkCenterCode(), MesPcnExtConstWords.WORK_CENTER_CODE, packBean);
                DdlPreparedPack.getNumEqualPack(CommonEnumUtil.FALSE, MesPcnExtConstWords.STATUS, packBean);
                DdlPreparedPack.getNumberSmallerEqualPack(model.getLocationNumber(), MesPcnExtConstWords.LOCATION_NUMBER, packBean);
                mesEmergencyLocationRepository.updateByProperties(new String[]{MesPcnExtConstWords.MODIFY_USER, MesPcnExtConstWords.MODIFY_DATE_TIME, MesPcnExtConstWords.STATUS},
                        new Object[]{model.getUserName(), TimeTool.getNowTime(true), CommonEnumUtil.VALID}, packBean);
            }
        }
        //新增加
        while (model.getLocationNumber() > lastNumber) {
            MesEmergencyLocation location = new MesEmergencyLocation();
            location.setFid(UUID.randomUUID().toString());
            location.setOrganizeCode(model.getOrganizeCode());
            location.setWorkCenterCode(model.getWorkCenterCode());
            location.setStatus(CommonEnumUtil.VALID);
            location.setLocationNumber(++lastNumber);
            location.setLocation(model.getWorkCenterCode() + "kw" + StringUtilExt.stringFormat(String.valueOf(lastNumber), 2, false, "0"));
            ConvertBean.serviceModelInitialize(location, model.getUserName());
            mesEmergencyLocationRepository.insert(location);
        }
    }

    private void updateMesConfig(MesEmergencyLocationModel model) {
        MesConfig remindDayCfg = mesConfigService.getMesConfig(model.getOrganizeCode(), MesPcnExtConstWords.REMIND_DAY);
        if(model.getRemindDay() != Integer.parseInt(remindDayCfg.getCfgValue())){
            remindDayCfg.setCfgValue(model.getRemindDay().toString());
            ConvertBean.serviceModelUpdate(remindDayCfg, model.getUserName());
            mesConfigRepository.update(remindDayCfg);
        }
    }

    private MesEmergencyLocation getMesEmergencyLocation(String organizeCode,String workOrderNo,String workCenterCode,boolean isShipping) {
        MesEmergencyLocation locationWorkOrder = getMesEmergencyLocation(organizeCode, null, null, workOrderNo);
        if (!isShipping){
            if (Objects.isNull(locationWorkOrder)) {
                MesPcnException.throwMesBusiException("加工单【%s】应急件库位管理信息不存在", workOrderNo);
            }
            if (!workCenterCode.equals(locationWorkOrder.getWorkCenterCode())) {
                MesPcnException.throwMesBusiException("加工单【%s】所在产线【%s】与当前产线【%s】不匹配", workOrderNo, locationWorkOrder.getWorkCenterCode(), workCenterCode);
            }
        }
        return locationWorkOrder;
    }

    private void checkLocation(MesEmergencyLocationModel model, MesEmergencyLocation location) {
        //校验库位是否存在
        if (Objects.isNull(location)) {
            MesPcnException.throwMesBusiException("产线【%s】库位【%s】信息不存在", model.getWorkCenterCode(), model.getLocation());
        }
        if (!StringUtil.isEmpty(location.getWorkOrderNo())) {
            MesPcnException.throwMesBusiException("产线【%s】库位【%s】已存在加工单【%s】", model.getWorkCenterCode(), model.getLocation(), location.getWorkOrderNo());
        }
    }


    private void checkWorkOrderNo(MesEmergencyLocationModel model, MesWorkOrder workOrder) {
        //校验工单
        if (Objects.isNull(workOrder)) {
            MesPcnException.throwMesBusiException("加工单【%s】信息不存在", model.getWorkOrderNo());
        }
        //已完成状态才能入库
        if (Objects.isNull(workOrder.getWorkOrderStatus()) || MesExtEnumUtil.ORDER_STATUS.COMPLETE.getValue() != workOrder.getWorkOrderStatus()) {
            MesPcnException.throwMesBusiException("加工单【%s】状态为【%s】不为【已完成】", model.getWorkOrderNo(), MesExtEnumUtil.ORDER_STATUS.valueOfDescription(workOrder.getWorkOrderStatus()));
        }
        if (!model.getWorkCenterCode().equals(workOrder.getWorkCenterCode())) {
            MesPcnException.throwMesBusiException("加工单【%s】所在产线【%s】与当前产线【%s】不匹配", model.getWorkOrderNo(), workOrder.getWorkCenterCode(), model.getWorkCenterCode());
        }
        //校验是否已经入库
        MesEmergencyLocation locationWorkOrder = getMesEmergencyLocation(model.getOrganizeCode(), null, null, model.getWorkOrderNo());
        if (!Objects.isNull(locationWorkOrder)) {
            MesPcnException.throwMesBusiException("加工单号已经入库,产线【%s】库位【%s】", locationWorkOrder.getWorkCenterCode(), locationWorkOrder.getLocation());
        }
    }


    public MesEmergencyLocation getMesEmergencyLocation(String organizeCode, String workCenterCode, String location, String workOrderNo) {
        DdlPackBean packBean = DdlPackBean.getDdlPackBean(organizeCode);
        DdlPreparedPack.getStringEqualPack(workCenterCode, MesPcnExtConstWords.WORK_CENTER_CODE, packBean);
        DdlPreparedPack.getStringEqualPack(location, MesPcnExtConstWords.LOCATION, packBean);
        DdlPreparedPack.getStringEqualPack(workOrderNo, MesPcnExtConstWords.WORK_ORDER_NO, packBean);
        DdlPreparedPack.getNumEqualPack(CommonEnumUtil.VALID, MesPcnExtConstWords.STATUS, packBean);
        return mesEmergencyLocationRepository.getByProperty(packBean);
    }
}
