package com.foreverwin.mesnac.dispatch.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.foreverwin.mesnac.common.constant.Constants;
import com.foreverwin.mesnac.common.dto.SfcDispatchDto;
import com.foreverwin.mesnac.common.enums.DispatchStatusEnum;
import com.foreverwin.mesnac.common.enums.HandleEnum;
import com.foreverwin.mesnac.common.util.ExcelUtils;
import com.foreverwin.mesnac.common.util.StringUtil;
import com.foreverwin.mesnac.dispatch.model.ShopOrderRelease;
import com.foreverwin.mesnac.dispatch.model.UserResource;
import com.foreverwin.mesnac.dispatch.service.CallItemService;
import com.foreverwin.mesnac.dispatch.mapper.SfcDispatchMapper;
import com.foreverwin.mesnac.dispatch.model.SfcDispatch;
import com.foreverwin.mesnac.dispatch.service.SfcDispatchService;
import com.foreverwin.mesnac.dispatch.service.UserResourceService;
import com.foreverwin.mesnac.meapi.service.ResrceService;
import com.foreverwin.mesnac.meapi.util.StringUtils;
import com.foreverwin.modular.core.exception.BusinessException;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Leon.L
 * @since 2021-06-02
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class SfcDispatchServiceImpl extends ServiceImpl<SfcDispatchMapper, SfcDispatch> implements SfcDispatchService {


    @Autowired
    private ResrceService resourceService;
    @Autowired
    private CallItemService callItemService;
    @Autowired
    private SfcDispatchMapper sfcDispatchMapper;
    @Autowired
    private UserResourceService userResourceService;

    @Override
    public List<SfcDispatch> findSfcDispatch(String site, String sfc, String operation, String stepId) {
        return sfcDispatchMapper.findSfcDispatch(site, sfc, operation, stepId);
    }

    @Override
    public List<ShopOrderRelease> findSfcDispatchList(ShopOrderRelease shopOrderRelease) {
        return sfcDispatchMapper.findSfcDispatchList(shopOrderRelease);
    }

    @Override
    public Boolean saveDispatch(String site, String user, StringBuffer message, List<SfcDispatchDto> sfcDispatchList) {
        return this.sfcDispatch(site, user, DispatchStatusEnum.SAVE.getCode(), message, sfcDispatchList);
    }

    @Override
    public Boolean releaseDispatch(String site, String user, StringBuffer message, List<SfcDispatchDto> sfcDispatchList) {
        Boolean flag = this.sfcDispatch(site, user, DispatchStatusEnum.RELEASE.getCode(), message, sfcDispatchList);

        //保存叫料数据
        callItemService.saveCallItem(site, user, sfcDispatchList);
        return flag;
    }

    @Override
    public void returnToNew(String user, List<SfcDispatchDto> sfcDispatchList) {
        if (sfcDispatchList == null || sfcDispatchList.size() <= 0) {
            return;
        }

        LocalDateTime nowDate = LocalDateTime.now();
        SfcDispatch sfcDispatch = null;
        List<SfcDispatch> list = new ArrayList<>();
        for (SfcDispatchDto sfcDispatchDto : sfcDispatchList) {
            String shopOrder = sfcDispatchDto.getShopOrder();
            String dispatchNo = sfcDispatchDto.getDispatchNo();
            String status = sfcDispatchDto.getDispatchStatus();
            if (!DispatchStatusEnum.PAUSE.getCode().equals(status) && !DispatchStatusEnum.CANCEL.getCode().equals(status)) {
                throw BusinessException.build("工单[" + shopOrder + "]的派工单号[" + dispatchNo + "]派工状态不是暂挂或取消状态，不能返回新建状态");
            }
            //TODO 需校验不允许存在领料信息

            sfcDispatch = new SfcDispatch();
            sfcDispatch.setHandle(sfcDispatchDto.getHandle());
            sfcDispatch.setDispatchStatus(DispatchStatusEnum.NEW.getCode());
            sfcDispatch.setModifyUser(user);
            sfcDispatch.setModifiedDateTime(nowDate);
            list.add(sfcDispatch);
        }

        if (list != null && list.size() > 0) {
            this.updateBatchById(list);
        }
    }

    @Override
    public void pause(String user, List<SfcDispatchDto> sfcDispatchList) {
        if (sfcDispatchList == null || sfcDispatchList.size() <= 0) {
            return;
        }

        LocalDateTime nowDate = LocalDateTime.now();
        SfcDispatch sfcDispatch = null;
        List<SfcDispatch> list = new ArrayList<>();
        for (SfcDispatchDto sfcDispatchDto : sfcDispatchList) {
            String shopOrder = sfcDispatchDto.getShopOrder();
            String dispatchNo = sfcDispatchDto.getDispatchNo();
            String status = sfcDispatchDto.getDispatchStatus();
            if (!DispatchStatusEnum.NEW.getCode().equals(status) && !DispatchStatusEnum.RELEASE.getCode().equals(status)) {
                throw BusinessException.build("工单[" + shopOrder + "]的派工单号[" + dispatchNo + "]派工状态不是新建或发布状态，不能变更为暂挂");
            }

            sfcDispatch = new SfcDispatch();
            sfcDispatch.setHandle(sfcDispatchDto.getHandle());
            sfcDispatch.setDispatchStatus(DispatchStatusEnum.PAUSE.getCode());
            sfcDispatch.setModifyUser(user);
            sfcDispatch.setModifiedDateTime(nowDate);
            list.add(sfcDispatch);
        }

        if (list != null && list.size() > 0) {
            this.updateBatchById(list);
        }
    }

    @Override
    public void cancel(String user, List<SfcDispatchDto> sfcDispatchList) {
        if (sfcDispatchList == null || sfcDispatchList.size() <= 0) {
            return;
        }

        LocalDateTime nowDate = LocalDateTime.now();
        SfcDispatch sfcDispatch = null;
        List<SfcDispatch> list = new ArrayList<>();
        for (SfcDispatchDto sfcDispatchDto : sfcDispatchList) {
            String shopOrder = sfcDispatchDto.getShopOrder();
            String dispatchNo = sfcDispatchDto.getDispatchNo();
            String status = sfcDispatchDto.getDispatchStatus();
            if (!DispatchStatusEnum.NEW.getCode().equals(status) && !DispatchStatusEnum.RELEASE.getCode().equals(status) && !DispatchStatusEnum.PAUSE.getCode().equals(status)) {
                throw BusinessException.build("工单[" + shopOrder + "]的派工单号[" + dispatchNo + "]派工状态不是新建、发布或暂挂状态，不能变更为取消");
            }
            //TODO 需校验派工单领料状态为无需领料或未领料

            sfcDispatch = new SfcDispatch();
            sfcDispatch.setHandle(sfcDispatchDto.getHandle());
            sfcDispatch.setDispatchStatus(DispatchStatusEnum.CANCEL.getCode());
            sfcDispatch.setModifyUser(user);
            sfcDispatch.setModifiedDateTime(nowDate);
            list.add(sfcDispatch);
        }

        if (list != null && list.size() > 0) {
            this.updateBatchById(list);
        }
    }

    @Override
    public Boolean importDispatch(String site, String user, String fileType, StringBuffer message, MultipartFile multipartFile) {
        InputStream inputStream = null;
        List<SfcDispatchDto> sfcDispatchList;
        try {
            sfcDispatchList = ExcelUtils.readExcel(fileType, SfcDispatchDto.class, multipartFile);
        } finally {
            if (inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        if (sfcDispatchList == null || sfcDispatchList.size() <= 0) {
            throw BusinessException.build("上传的Excel没有数据，或者数据格式不正确");
        }

        return this.sfcDispatch(site, user, DispatchStatusEnum.IMPORT.getCode(), message, sfcDispatchList);
    }



    /**
     * 派工数据保存
     *
     * @param site
     * @param user
     * @param type
     * @param message
     * @param sfcDispatchList
     * @return
     */
    Boolean  sfcDispatch(String site, String user, String type, StringBuffer message, List<SfcDispatchDto> sfcDispatchList) {
        if (sfcDispatchList == null || sfcDispatchList.size() <= 0) {
            throw BusinessException.build("请选择至少一笔工单数据进行操作");
        }

        //查询所有资源类型与资源关系
        List<Map<String, Object>> resourceList = resourceService.getResourceTypeResourceList(site);
        if (resourceList == null || resourceList.size() <= 0) {
            throw BusinessException.build("资源与资源类型关系数据未维护");
        }
        Map<String, List<Map<String, Object>>> map = resourceList.stream().collect(Collectors.groupingBy(item -> (String)item.get("RESRCE")));

        //员工资源对应关系
        List<UserResource> userResourceList = userResourceService.findEnableList(site, null, null);
        if (userResourceList == null || userResourceList.size() <= 0) {
            throw BusinessException.build("员工与资源关系没有维护");
        }
        Map<String, List<UserResource>> usMap = userResourceList.stream().collect(Collectors.groupingBy(UserResource::getUserId));

        //派工更新清单
        List<SfcDispatch> list = new ArrayList<>();

        int seq = 0;
        //状态标识，表示本次派工成功或是失败
        Boolean flag = true;
        LocalDateTime nowDate = LocalDateTime.now();
        for (SfcDispatchDto sfcDispatchDto : sfcDispatchList) {
            SfcDispatch sfcDispatch = new SfcDispatch();
            sfcDispatch.setHandle(sfcDispatchDto.getHandle());
            sfcDispatch.setModifyUser(user);
            sfcDispatch.setModifiedDateTime(nowDate);

            String resource = sfcDispatchDto.getResrce();
            String dispatchNo = sfcDispatchDto.getDispatchNo();
            String resourceType = sfcDispatchDto.getResourceType();

            //派工保存
            if (DispatchStatusEnum.SAVE.getCode().equals(type)) {
                //校验派工状态
                String originalStatus = sfcDispatchDto.getDispatchStatus();
                if (!DispatchStatusEnum.NEW.getCode().equals(originalStatus)) {
                    flag = false;
                    message.append(seq++ % 3 == 0 ? "\n" : "|   |");
                    message.append("派工单[" + dispatchNo + "]的派工状态不是新建，不允许保存");
                    continue;
                }
            }

            //派工导入
            if (DispatchStatusEnum.IMPORT.getCode().equals(type)) {
                //TODO  派工单已经开始或完成的不修改

                String handle = HandleEnum.SFC_DISPATCH.getHandle(site, dispatchNo);
                SfcDispatch sfcDispatchModel = this.getById(handle);
                if (sfcDispatchModel == null) {
                    flag = false;
                    message.append(seq++ % 3 == 0 ? "\n" : "|   |");
                    message.append("派工单[" + dispatchNo + "]不存在，请确认数据是导出的原始数据");
                    continue;
                }
                resourceType = sfcDispatchModel.getResourceType();

                //资源、计划时间必输
                if (StringUtils.isBlank(resource) || sfcDispatchDto.getPlannedStartDate() == null || sfcDispatchDto.getPlannedCompDate() == null) {
                    flag = false;
                    message.append(seq++%3 == 0 ? "\n" : "|   |");
                    message.append("派工单[" + dispatchNo + "]的资源、计划开始或完成时间没维护，不允许发布");
                    continue;
                }

                sfcDispatch.setHandle(handle);
                //是否导入
                sfcDispatch.setIsImport(Constants.BOOL_TRUE);
            }

            //派工发布
            if (DispatchStatusEnum.RELEASE.getCode().equals(type)) {
                //校验派工状态
                String originalStatus = sfcDispatchDto.getDispatchStatus();
                if (!DispatchStatusEnum.NEW.getCode().equals(originalStatus) && !DispatchStatusEnum.PAUSE.getCode().equals(originalStatus)) {
                    flag = false;
                    message.append(seq++ % 3 == 0 ? "\n" : "|   |");
                    message.append("派工单[" + dispatchNo + "]的派工状态不是新建或暂挂，不允许发布");
                    continue;
                }

                //资源、计划时间必输
                if (StringUtils.isBlank(resource) || sfcDispatchDto.getPlannedStartDate() == null || sfcDispatchDto.getPlannedCompDate() == null) {
                    flag = false;
                    message.append(seq++%3 == 0 ? "\n" : "|   |");
                    message.append("派工单[" + dispatchNo + "]的资源、计划开始或完成时间没维护，不允许发布");
                    continue;
                }


                sfcDispatch.setSfcReleasedDate(nowDate);
                //发布状态更新
                sfcDispatch.setDispatchStatus(DispatchStatusEnum.RELEASE.getCode());
            }


            //校验资源与累心是否匹配
            if (StringUtil.notBlank(resource)) {
                List<Map<String, Object>> resourceTypeList = map.get(resource);
                if (resourceTypeList == null || resourceTypeList.size() <= 0) {
                    flag = false;
                    message.append(seq++ % 3 == 0 ? "\n" : "|   |");
                    message.append("派工单[" + dispatchNo + "]分配的资源[" + resource + "]不存在或没有维护资源类型");
                    continue;
                }
                String _resourceType = (String) resourceTypeList.get(0).get("RESOURCE_TYPE");
                if (!resourceType.equals(_resourceType)) {
                    flag = false;
                    message.append(seq++ % 3 == 0 ? "\n" : "|   |");
                    message.append("派工单[" + dispatchNo + "]分配的资源[" + resource + "]类型与需要的资源类型[" + resourceType + "]不匹配");
                    continue;
                }
            }

            //校验操作者与资源是否匹配
            String employee = sfcDispatchDto.getUserName();
            if (StringUtil.notBlank(employee)) {
                //资源、计划时间必输
                if (StringUtils.isBlank(resource)) {
                    flag = false;
                    message.append(seq++%3 == 0 ? "\n" : "|   |");
                    message.append("派工单[" + dispatchNo + "]还未分配资源，请先分配资源");
                    continue;
                }

                List<UserResource> singleUserResourceList = usMap.get(employee);
                if (singleUserResourceList == null || singleUserResourceList.size() <= 0) {
                    flag = false;
                    message.append(seq++ % 3 == 0 ? "\n" : "|   |");
                    message.append("派工单[" + dispatchNo + "]分配的操作者[" + employee + "]没有维护资源关系");
                    continue;
                }

                Boolean isMatch = false;
                for (int i = 0; i < singleUserResourceList.size(); i++) {
                    UserResource userResource = singleUserResourceList.get(i);
                    if (resource.equals(userResource.getResrce())) {
                        isMatch = true; break;
                    }
                }
                if (!isMatch) {
                    flag = false;
                    message.append(seq++%3 == 0 ? "\n" : "|   |");
                    message.append("派工单[" + dispatchNo + "]分配的操作员[" + employee + "]与资源[" + resource +"]不匹配");
                    continue;
                }
            }

            sfcDispatch.setResrce(resource);
            sfcDispatch.setEmployee(employee);
            sfcDispatch.setRemark(sfcDispatchDto.getRemark());
            sfcDispatch.setBlankingSize(sfcDispatchDto.getBlankingSize());
            sfcDispatch.setPlannedStartDate(sfcDispatchDto.getPlannedStartDate());
            sfcDispatch.setPlannedCompDate(sfcDispatchDto.getPlannedCompDate());
            list.add(sfcDispatch);
        }

        //执行更新
        if (flag && list != null && list.size() > 0) {
            this.updateBatchById(list);
        }

        return flag;
    }
}