package com.sw.mes.yb.production.controller;
import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.utils.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Date;

import com.sw.mes.base.factory.material.dto.MaterialModelDto;
import com.sw.mes.base.factory.material.entity.MaterialCleanModel;
import com.sw.mes.base.factory.material.entity.MaterialModel;
import com.sw.mes.base.factory.material.service.MaterialCleanModelService;
import com.sw.mes.base.factory.material.service.MaterialModelService;
import com.sw.mes.base.factory.material.service.MaterialTypeService;
import com.sw.mes.base.system.entity.DictionaryItem;
import com.sw.mes.base.system.service.DictionaryItemService;
import com.sw.mes.core.annotation.Jinko;
import com.sw.mes.core.api.materialclean.MaterialCleanFeignClients;
import com.sw.mes.core.api.system.FbFeignClients;
import com.sw.mes.core.context.BaseContextHandler;
import com.sw.mes.core.dto.mes.pc.fb.FbCheckOutDataDto;
import com.sw.mes.core.dto.sap.ReportSapGoodsmvtDto;
import com.sw.mes.core.entity.SearchFilter;
import com.sw.mes.core.enums.FactoryModelWorkTypeEnum;
import com.sw.mes.core.enums.SectionIndexRangeEnum;
import com.sw.mes.core.exception.BusinessException;
import com.sw.mes.core.response.ResponsePage;
import com.sw.mes.core.response.Result;
import com.sw.mes.core.response.ResultCode;
import com.sw.mes.core.response.ResultGenerator;
import com.sw.mes.core.utils.*;
import com.sw.mes.enumvalue.RecycleTypeEnum;
import com.sw.mes.enumvalue.StockStateEnum;
import com.sw.mes.gread.entity.GradeVersion;
import com.sw.mes.inspect.entity.YbInspectData;
import com.sw.mes.inspect.service.YbInspectDataService;
import com.sw.mes.redis.server.RedissonUtils;
import com.sw.mes.utils.ExcelUtil;
import com.sw.mes.yb.check.entity.CrystallonData;
import com.sw.mes.yb.pad.entity.ProductionPaintingLineDetail;
import com.sw.mes.yb.pad.service.ProductionPaintingLineDetailService;
import com.sw.mes.yb.pc.entity.CarrierConfig;
import com.sw.mes.yb.pc.service.CarrierConfigService;
import com.sw.mes.yb.production.dto.*;
import com.sw.mes.yb.production.entity.*;
import com.sw.mes.yb.production.service.RecycledMaterialManageDetailService;
import com.sw.mes.yb.production.service.RecycledMaterialManageService;
import com.sw.mes.yb.production.service.SurplusInfoService;
import com.sw.mes.yb.production.utils.RecycledBatchGenerator;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Author: xushu
 * @Date: 2022/08/17/16:25
 * @Description:
 */
@RestController
@RequestMapping("/recycledMaterialManage")
@Slf4j
@Api(tags = "回收料管理接口")
public class RecycledMaterialManageController {

    @Autowired
    ModelMapper modelMapper;

    @Autowired
    RecycledMaterialManageService recycledMaterialManageService;

    @Autowired
    RecycledMaterialManageDetailService recycledMaterialManageDetailService;

    @Autowired
    MaterialModelService materialModelService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    MaterialTypeService materialTypeService;

    @Autowired
    private YbInspectDataService ybInspectDataService;

    @Autowired
    private MaterialCleanModelService materialCleanModelService;

    @Autowired
    private ProductionPaintingLineDetailService productionPaintingLineDetailService;

    @Autowired
    private FbFeignClients fbFeignClients;
    @Autowired
    private DictionaryItemService dictionaryItemService;

    @Autowired
    private MaterialCleanFeignClients materialCleanFeignClients;

    @Autowired
    CarrierConfigService carrierConfigService;

    @Autowired
    private RecycledBatchGenerator recycledBatchGenerator;

    @Autowired
    private SurplusInfoService surplusInfoService;

    @ApiOperation(value = "分页查询回收料列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "rows", value = "行数", dataType = "integer", paramType = "query"),
            @ApiImplicitParam(name = "page", value = "页码", dataType = "integer", paramType = "query"),
            @ApiImplicitParam(name = "status", value = "状态(1待入库，2取消，3待确定，4已接收，5拒收)", dataType = "integer", paramType = "query"),
            @ApiImplicitParam(name = "search_LIKE_trayNo", value = "托号", dataType = "integer", paramType = "query"),
            @ApiImplicitParam(name = "search_EQ_recycledMaterialType", value = "回收料类型", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_EQ_source", value = "来源", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_EQ_lotNo", value = "炉次号", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_EQ_boxNo", value = "卡板箱号", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_GTE_createTime", value = "组托开始时间", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_LT_createTime", value = "组托结束时间", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_EQ_materialCategory", value = "物料类别(1 余料(默认) 2 废料)", dataType = "string", paramType = "query"),
    })
    @GetMapping("/listByPage")
    public Result<ResponsePage<RecycledMaterialManageDto>> listByPage(ServletRequest request, @ApiIgnore RequestPage requestPage) {
        SearchFilter filter = new SearchFilter("del", SearchFilter.Operator.EQ,0);//查询未删除的列表
        requestPage.setOrderField("createTime");
        requestPage.setOrderDirection(RequestPage.ORDER_DIRECTION_DESC);
        Specification<RecycledMaterialManage> specification = DynamicSpecifications.bySearchFilter(request, RecycledMaterialManage.class,filter);
        Page<RecycledMaterialManage> page = recycledMaterialManageService.findByExample(specification, PageUtil.createPageable(requestPage));
        List<RecycledMaterialManageDto> dtos = page.getContent().stream().map(entity -> toLazyDto(entity))
                .collect(Collectors.toList());
        dtos.forEach(item -> {
            if("2".equals(item.getKostl())){
                //成本中心是 2  拉晶的,不展示工单(因为详情混工单,取得最后一条工单)
                item.setWorkOrderNo("");
            }
        });
        ResponsePage responsePage = new ResponsePage(dtos, page.getTotalElements());
        return ResultGenerator.success(responsePage);
    }

    @Jinko(author = "yyl", value = "硅料加工记录-余料采集-导出")
    @ApiOperation(value = "硅料加工记录-余料采集-导出")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "search_LIKE_trayNo", value = "托号", dataType = "integer", paramType = "query"),
            @ApiImplicitParam(name = "search_EQ_boxNo", value = "卡板箱号", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_GTE_createTime", value = "组托开始时间", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_LT_createTime", value = "组托结束时间", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_EQ_materialCategory", value = "物料类别(1 余料(默认) 2 废料)", dataType = "string", paramType = "query"),
    })
    @GetMapping("/export")
    public void export(ServletRequest request, HttpServletResponse response) {
        try {
            Specification<RecycledMaterialManage> specification = DynamicSpecifications.bySearchFilter(request, RecycledMaterialManage.class, new SearchFilter("del", SearchFilter.Operator.EQ, 0));
            List<RecycledMaterialManage> list = recycledMaterialManageService.findByExampleSort(specification, Sort.by(new Sort.Order(Sort.Direction.DESC, "createTime")));
            List<RecycledMaterialManageDto> dtos = list.stream().map(entity -> toLazyDto(entity))
                    .collect(Collectors.toList());
            ArrayList<RecycledMaterialManageDto> recycledMaterialManageDetailDtos = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(dtos)) {
                for (RecycledMaterialManageDto recycledMaterialManage : dtos) {
                    if ("2".equals(recycledMaterialManage.getKostl())) {
                        //如果是拉晶 ,还需要单独把详情拉出来
                        List<RecycledMaterialManageDetail> recycledMaterialManageDetails = recycledMaterialManageDetailService.getDetailByManageId(recycledMaterialManage.getId());
                        for (RecycledMaterialManageDetail detail : recycledMaterialManageDetails) {
                            RecycledMaterialManageDto recycledMaterialManageDto = new RecycledMaterialManageDto();
                            BeanUtils.copyProperties(recycledMaterialManage, recycledMaterialManageDto);
                            recycledMaterialManageDto.setWorkOrderNo(detail.getWorkOrderNo());
                            recycledMaterialManageDto.setDeviceNo(detail.getDeviceNo());
                            recycledMaterialManageDto.setWeight(detail.getWeight());
                            recycledMaterialManageDetailDtos.add(recycledMaterialManageDto);
                        }
                    } else {
                        recycledMaterialManageDetailDtos.add(recycledMaterialManage);
                    }
                }
            }
            EasyExcelUtils.write(response, RecycledMaterialManageDto.class, "余料采集", "余料采集", recycledMaterialManageDetailDtos);
        } catch (Exception e) {
            throw new RuntimeException("导出余料采集失败，错误信息：" + e.getMessage());
        }
    }

    @ApiOperation(value = "pda分页查询回收料列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "rows", value = "行数", dataType = "integer", paramType = "query"),
            @ApiImplicitParam(name = "page", value = "页码", dataType = "integer", paramType = "query"),
            @ApiImplicitParam(name = "search_EQ_boxNo", value = "卡板箱号", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_EQ_source", value = "来源", dataType = "string", paramType = "query"),
    })
    @GetMapping("/pdaListByPage")
    public Result<ResponsePage<RecycledMaterialManageDto>> pdaListByPage(ServletRequest request, @ApiIgnore RequestPage requestPage) {
        Collection<SearchFilter> searchFilters = new HashSet<>();
        searchFilters.add(new SearchFilter("del", SearchFilter.Operator.EQ,0));
        searchFilters.add(new SearchFilter("status", SearchFilter.Operator.NOT,4));//列表展示待入库,取消,
        searchFilters.add(new SearchFilter("status", SearchFilter.Operator.NOT,5));
        Specification<RecycledMaterialManage> specification = DynamicSpecifications.bySearchFilter(request, RecycledMaterialManage.class,searchFilters);
        Page<RecycledMaterialManage> page = recycledMaterialManageService.findByExample(specification, PageUtil.createPageable(requestPage));
        List<RecycledMaterialManageDto> dtos = page.getContent().stream().map(entity -> toLazyDto(entity))
                .collect(Collectors.toList());
        ResponsePage responsePage = new ResponsePage(dtos, page.getTotalElements());
        return ResultGenerator.success(responsePage);
    }

    @ApiOperation(value = "回收料上报ERP")
    @PostMapping("/reportedErp")
    public Result reportedErp(@RequestBody @Valid @ApiParam(value = "Dto对象") RecycledMaterialManageDto recycledMaterialManageDto) {
        return recycledMaterialManageService.reportedErp(recycledMaterialManageDto);
    }

    @ApiOperation(value = "回收料管理详细信息")
    @GetMapping("/{id}")
    public Result<RecycledMaterialManageDto> get(@PathVariable @ApiParam(value="RecycledMaterialManageId") Long id) {
        RecycledMaterialManage recycledMaterialManage = recycledMaterialManageService.get(id);
        if(null == recycledMaterialManage){
            return ResultGenerator.fail("该回收料管理信息不存在");
        }
        List<RecycledMaterialManageDetail> recycledMaterialManageDetails = recycledMaterialManageDetailService.getDetailByManageId(id);
        RecycledMaterialManageDto recycledMaterialManageDto = toLazyDto(recycledMaterialManage);
        List<RecycledMaterialManageDetailDto>  recycledMaterialManageDetaiDtos= new ArrayList<>();
        if (null != recycledMaterialManageDetails && !recycledMaterialManageDetails.isEmpty()) {
            recycledMaterialManageDetaiDtos = recycledMaterialManageDetails.stream().map(entity -> toTarget(entity))
                    .collect(Collectors.toList());
            recycledMaterialManageDetaiDtos.forEach(recycledMaterialManageDetailDto -> {
                recycledMaterialManageDetailDto.setWorkShop(recycledMaterialManageDto.getWorkShop());
                recycledMaterialManageDetailDto.setSurplusType(recycledMaterialManageDetailDto.getProductionType());
                recycledMaterialManageDetailDto.setSurplusCode(recycledMaterialManageDetailDto.getRecycleNo());
            });
        }
        recycledMaterialManageDto.setRecycledMaterialMangeDetailDtos(recycledMaterialManageDetaiDtos);
        return ResultGenerator.success(recycledMaterialManageDto);
    }

    @ApiOperation(value = "回收料管理详细信息")
    @GetMapping("/boxNo")
    public Result<RecycledMaterialManage> get(@RequestParam String boxNo) {
        RecycledMaterialManage recycledMaterialManage = recycledMaterialManageService.getByBoxNo(boxNo);
        if(null == recycledMaterialManage){
            return ResultGenerator.fail("该回收料管理信息不存在");
        }
        return ResultGenerator.success(recycledMaterialManage);
    }
    @ApiOperation(value = "通过托号查询废料详细信息")
    @GetMapping("/trayNo")
    public Result<RecycledMaterialManage> getRecycleMaterialByTrayNo(@RequestParam String trayNo) {
        RecycledMaterialManage recycledMaterialManage = recycledMaterialManageService.getRecycleMaterialByTrayNo(trayNo);
        if(null == recycledMaterialManage){
            return ResultGenerator.fail("该回收料管理信息不存在");
        }
        return ResultGenerator.success(recycledMaterialManage);
    }
   /* @ApiOperation(value = "新增和更新回收料管理列表详情")
    @PostMapping("/saveOrUpdateRecycledMaterial")
    public Result saveOrUpdateRecycledMaterial(@RequestBody @Valid @ApiParam(value = "新增和更新回收料管理列表详情") RecycledMaterialManageDto recycledMaterialManageDto, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }

        //todo:校验追溯标识是否一致
        String fromMark = recycledMaterialManageDto.getFromMark();
        Long manageId = recycledMaterialManageDto.getId();
        String maker = BaseContextHandler.getUsername();
        Date now = new Date();
        List<RecycledMaterialManageDetailDto>  recycledMaterialManageDetailDtos =  recycledMaterialManageDto.getRecycledMaterialMangeDetailDtos();
//        if(recycledMaterialManageDetailDtos == null || recycledMaterialManageDetailDtos.isEmpty()){
//            return ResultGenerator.fail("未录入回收料");
//        }
        if(null != recycledMaterialManageDetailDtos && !recycledMaterialManageDetailDtos.isEmpty() && recycledMaterialManageDetailDtos.size() > 0){
            List<String> recycleNos = recycledMaterialManageDetailDtos.stream().map(temp -> temp.getRecycleNo()).collect(Collectors.toList());

            //todo 单晶允许重复
//            HashSet<String> hashSet = new HashSet<>(recycleNos);
//            if(!"单晶".equals(recycledMaterialManageDto.getSource())){
//                if(recycleNos.size() != hashSet.size()){
//                    return ResultGenerator.fail("回收料重复");
//                }
//            }
            //校验当前回收料码是否存在其他非取消和拒收的记录中
            //校验子物料产品类型与主物料是否相同
            List<String> usedRecycleNos = recycledMaterialManageDetailService.findUsedRecycleNos(manageId);
            for(RecycledMaterialManageDetailDto temp:recycledMaterialManageDetailDtos){
                if(null == temp.getProductionType()){
//                    return ResultGenerator.fail("物料的产品类别不存在");
                    continue;
                }
//                if(!temp.getProductionType().equals(recycledMaterialManageDto.getProductionCategory())){
//                    return ResultGenerator.fail("产品类别不一致");
//                }
                if (StringUtils.isNotBlank(fromMark) && !fromMark.equals(temp.getFromMark())) {
                    return ResultGenerator.fail("溯源标识不一致");
                }
                if (usedRecycleNos != null && !usedRecycleNos.isEmpty() && null != temp.getRecycleNo()
                        && !temp.getRecycleNo().isEmpty()) {
                    if (usedRecycleNos.contains(temp.getRecycleNo())) {
                        return ResultGenerator.fail(temp.getRecycleNo()+"物料已被组托!");
                    }
                }
            }

        }
        if(manageId != null){//编辑
            Integer status = recycledMaterialManageDto.getStatus();
            if(null == status){
                return ResultGenerator.fail("缺少状态参数");
            }
            if(status.equals(StockStateEnum.REFUSE.getCode()) || status.equals(StockStateEnum.TOBEOUT.getCode()) || status.equals(StockStateEnum.CANCEL.getCode())){
                recycledMaterialManageDetailService.deleteByManageId(manageId);
            }else{
                return ResultGenerator.fail("该状态不可编辑");
            }
            recycledMaterialManageDto.setUpdateBy(maker);
            recycledMaterialManageDto.setUpdateTime(now);
        }else{//新增
            String materialBoxNo = recycledMaterialManageDto.getBoxNo();
            RecycledMaterialManage materialManage = recycledMaterialManageService.getByBoxNoAndStatus(materialBoxNo);
            if (null != materialManage) {
                return ResultGenerator.fail("该箱号: " + materialBoxNo + " 被占用,领料清空后方可使用!");
            }
            //todo 新的托号和生产批次号
            String trayNo = creatTrayNew(recycledMaterialManageDto);
            String produceBatchNo = creatProduceBatchNo(recycledMaterialManageDto);
//            String trayNo = creatTrayNo(recycledMaterialManageDto);
            recycledMaterialManageDto.setTrayNo(trayNo);
            //生产批次号
            recycledMaterialManageDto.setProduceBatchNo(produceBatchNo);
            recycledMaterialManageDto.setCreateBy(maker);
            recycledMaterialManageDto.setCreateTime(now);
            recycledMaterialManageDto.setUpdateBy(maker);
            recycledMaterialManageDto.setUpdateTime(now);
        }
        if("单晶".equals(recycledMaterialManageDto.getSource())){
            if(StringUtils.isBlank(recycledMaterialManageDto.getLotNo())){
                ResultGenerator.fail("未录入炉次号");
            }
        }
        recycledMaterialManageDto.setStatus(StockStateEnum.TOBEOUT.getCode());
        if(recycledMaterialManageDetailDtos == null || recycledMaterialManageDetailDtos.isEmpty()){
            recycledMaterialManageDto.setNum(0);
        } else {
            recycledMaterialManageDto.setNum(recycledMaterialManageDetailDtos.size());
        }
        RecycledMaterialManage recycledMaterialManage = fromDto(recycledMaterialManageDto);
        recycledMaterialManageService.saveOrUpdate(recycledMaterialManage);
        if(null != recycledMaterialManageDetailDtos && !recycledMaterialManageDetailDtos.isEmpty() && recycledMaterialManageDetailDtos.size() > 0){
            List<RecycledMaterialManageDetail> recycledMaterialManageDetails = recycledMaterialManageDetailDtos.stream().map(entity -> fromDetailDto(entity))
                    .collect(Collectors.toList());
            recycledMaterialManageDetails.stream().forEach(temp -> temp.setManageId(recycledMaterialManage.getId()));
            recycledMaterialManageDetailService.saveAll(recycledMaterialManageDetails);
        }
        return ResultGenerator.success();
    }

    */
   @Jinko(author = "yyl", value = "余料新增和更新回收料管理列表详情")
   @ApiOperation(value = "余料新增和更新回收料管理列表详情")
   @PostMapping("/saveOrUpdateRecycledMaterial")
   public Result saveOrUpdateRecycledMaterial(@RequestBody @Valid @ApiParam(value = "新增和更新回收料管理列表详情") RecycledMaterialManageDto recycledMaterialManageDto, BindingResult bindingResult) {
       if (bindingResult.hasErrors()) {
           return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
       }
       return recycledMaterialManageService.saveOrUpdateRecycledMaterial(recycledMaterialManageDto);
   }

    @ApiOperation(value = "测试回收料批次生成")
    @GetMapping("/batchNo")
    public Result getBatch(ServletRequest request) {
        for (int i = 0; i < 1002; i++) {
            String str = recycledBatchGenerator.batchNoGenerator("R", "C", "1");
            System.out.println("测试数据+"+str);
        }
        return ResultGenerator.success();
    }













    @ApiOperation(value = "删除回收料管理信息")
    @GetMapping("/delete")
    public Result delete(@ApiParam(value = "id", type = "query") @RequestParam Long id) {
        RecycledMaterialManage recycledMaterialManage = recycledMaterialManageService.get(id);
        Integer status = recycledMaterialManage.getStatus();
        if(status.equals(StockStateEnum.TOBEOUT.getCode())){
            recycledMaterialManage.setDel(1);
            recycledMaterialManageService.saveOrUpdate(recycledMaterialManage);
            recycledMaterialManageDetailService.deleteByManageId(id);
        }else{
            return ResultGenerator.fail("该状态不可删除");
        }
        return ResultGenerator.success();
    }


    @ApiOperation(value = "取消回收料管理信息")
    @GetMapping("/cancel")
    public Result cancel(@ApiParam(value = "id", type = "query") @RequestParam Long id) {
        RecycledMaterialManage recycledMaterialManage = recycledMaterialManageService.get(id);
        Integer status = recycledMaterialManage.getStatus();
        if(status.equals(StockStateEnum.TOBEOUT.getCode())){
            recycledMaterialManage.setStatus(StockStateEnum.CANCEL.getCode());
            recycledMaterialManageService.saveOrUpdate(recycledMaterialManage);
        }else{
            return ResultGenerator.fail("该状态不可取消");
        }
        return ResultGenerator.success();
    }


    /*@ApiOperation(value = "发起入库")
    @GetMapping("/startWarehousing")
    public Result startWarehousing(@ApiParam(value = "id", type = "query") @RequestParam Long id) {
        RecycledMaterialManage recycledMaterialManage = recycledMaterialManageService.get(id);
        Integer status = recycledMaterialManage.getStatus();
        if(status.equals(StockStateEnum.TOBEOUT.getCode())){
            recycledMaterialManage.setStatus(StockStateEnum.TOBEDETERMINE.getCode());
        }else{
            return ResultGenerator.fail("该状态不可发起入库");
        }
        if(recycledMaterialManage.getWeight() == null){
            return ResultGenerator.fail("重量不可以为空");
        }
        RecycledMaterialManageDto recycledMaterialManageDto = toLazyDto1(recycledMaterialManage);
        try {
            //todo发起入库功能待取消,后期不适用
            recycledMaterialManageService.recycledMaterialIn(recycledMaterialManageDto);
        } catch(BusinessException e){
            return ResultGenerator.fail(e.getMessage());
        }
        recycledMaterialManage.setReceiveTime(new Date());
        recycledMaterialManage.setReceiver("WMS");
        recycledMaterialManage.setStatus(StockStateEnum.RECEIVED.getCode());
        recycledMaterialManageService.saveOrUpdate(recycledMaterialManage);
        return ResultGenerator.success();
    }

*/

    @Jinko(author = "yyl", value = "回收料发起入库")
    @ApiOperation(value = "回收料发起入库")
    @GetMapping("/startWarehousing")
    public Result startWarehousing(@ApiParam(value = "id", type = "query") @RequestParam Long id) {
        RecycledMaterialManage recycledMaterialManage = recycledMaterialManageService.get(id);
        Integer status = recycledMaterialManage.getStatus();
        if (status.equals(StockStateEnum.TOBEOUT.getCode())) {
            recycledMaterialManage.setStatus(StockStateEnum.TOBEDETERMINE.getCode());
        } else {
            return ResultGenerator.fail("该状态不可发起入库");
        }
        if (recycledMaterialManage.getWeight() == null) {
            return ResultGenerator.fail("重量不可以为空");
        }
        recycledMaterialManage.setReceiveTime(new Date());
        recycledMaterialManage.setUpdateTime(new Date());
        recycledMaterialManage.setUpdateBy(BaseContextHandler.getUsername());
        String result = null;
        if (RecycleTypeEnum.余料.getCode() == recycledMaterialManage.getMaterialCategory()) {
            if (("4".equals(recycledMaterialManage.getKostl()) || "3".equals(recycledMaterialManage.getKostl()))
                    && null != recycledMaterialManage.getHasGone() && RecycleTypeEnum.籽晶车间.getCode() == recycledMaterialManage.getHasGone()) {
                //截断成本中心3或者刀剖成本中心4,籽晶去向2,余料自动入库并由线边仓手动调拨
                result = recycledMaterialManageService.startSurplusToSeedWarehousing(recycledMaterialManage, RecycleTypeEnum.余料入库.getDesc());
            } else {
                recycledMaterialManage.setReceiver(RecycleTypeEnum.余料入库.getDesc());
                result = recycledMaterialManageService.startSurplusWarehousing(recycledMaterialManage, RecycleTypeEnum.余料入库.getDesc());
            }
        } else {
            recycledMaterialManage.setReceiver(RecycleTypeEnum.废料入库.getDesc());
            result = recycledMaterialManageService.startSurplusToWMS(recycledMaterialManage, RecycleTypeEnum.废料入库.getDesc());
        }
        if (StringUtils.isNotBlank(result)) {
            recycledMaterialManage.setStatus(StockStateEnum.RECEIVED.getCode());
            recycledMaterialManageService.saveOrUpdate(recycledMaterialManage);
        }
        return ResultGenerator.success();
    }

    @ApiOperation(value = "发起入库到料理车间或wms")
    @PostMapping("/startToWarehousing")
    public Result startWarehousing(@RequestBody @Valid @ApiParam(value = "回收料发起对象") RecycledToWarehousingDto recycledToWarehousingDto) {

        RecycledMaterialManage recycledMaterialManage = recycledMaterialManageService.get(recycledToWarehousingDto.getId());
        Integer status = recycledMaterialManage.getStatus();
        if (status.equals(StockStateEnum.TOBEOUT.getCode())) {
            recycledMaterialManage.setStatus(StockStateEnum.TOBEDETERMINE.getCode());
        } else {
            return ResultGenerator.fail("该状态不可发起入库");
        }
        if (recycledMaterialManage.getWeight() == null) {
            return ResultGenerator.fail("重量不可以为空");
        }
        List<DictionaryItem> dictionaryItems = dictionaryItemService.findItemByThemeValue("update_allow_weight", true);
        if (CollectionUtils.isEmpty(dictionaryItems)) {
            throw new BusinessException("[余料重量正负值允许修改范围]字典不能为空!");
        }else {
            BigDecimal upWeight = new BigDecimal(dictionaryItems.get(0).getName());
            BigDecimal downWeight = new BigDecimal(dictionaryItems.get(0).getValue());
            BigDecimal maxWeight = recycledMaterialManage.getWeight().add(upWeight);
            BigDecimal minWeight = recycledMaterialManage.getWeight().subtract(downWeight);
            if (null != recycledToWarehousingDto.getWeight()) {
                if (recycledToWarehousingDto.getWeight().compareTo(maxWeight) > 0 || recycledToWarehousingDto.getWeight().compareTo(minWeight) < 0) {
                    throw new BusinessException("重量不允许修改超过字典允许范围!");
                }
            }
        }

        if (null != recycledToWarehousingDto.getWeight()) {
            recycledMaterialManage.setWeight(recycledToWarehousingDto.getWeight());
        }
        RecycledMaterialManageDto recycledMaterialManageDto = toLazyDto1(recycledMaterialManage);
        try {
            //todo发起入库功能待取消,后期不适用
            recycledMaterialManageService.recycledMaterialIn(recycledMaterialManageDto,recycledToWarehousingDto.getHasGone());
        } catch (BusinessException e) {
            return ResultGenerator.fail(e.getMessage());
        }
        recycledMaterialManage.setReceiveTime(new Date());
        recycledMaterialManage.setReceiver(recycledToWarehousingDto.getHasGone());
        recycledMaterialManage.setStatus(StockStateEnum.RECEIVED.getCode());
        recycledMaterialManageService.saveOrUpdate(recycledMaterialManage);
        return ResultGenerator.success();
    }

    @ApiOperation(value = "导出Excel")
    @GetMapping("/exportExcel")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "search_LIKE_trayNo", value = "托号", dataType = "integer", paramType = "query"),
            @ApiImplicitParam(name = "status", value = "状态(1待入库，2取消，3待确定，4已接收，5拒收)", dataType = "integer", paramType = "query"),
            @ApiImplicitParam(name = "search_EQ_boxNo", value = "卡板箱号", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_EQ_recycledMaterialType", value = "回收料类型", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_EQ_source", value = "来源", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_EQ_lotNo", value = "炉次号", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_GTE_createTime", value = "组托开始时间", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_LT_createTime", value = "组托结束时间", dataType = "string", paramType = "query"),
    })
    public Result exportExcel(HttpServletRequest request, HttpServletResponse resp)  {
        try {
            recycledMaterialManageService.exportExcel(request, resp);
        }catch (Exception e){
            return ResultGenerator.fail(e.getMessage());
        }
        return ResultGenerator.success();
    }

    @ApiOperation(value = "导入Excel")
    @PostMapping("/importExcel")
    public Result importExcel(MultipartFile file)  {
        String message = recycledMaterialManageService.importExcel(file);
        if (null != message) {
            return ResultGenerator.fail(message);
        } else {
            return ResultGenerator.success();
        }
    }

    @ApiOperation(value = "模板文件下载")
    @PostMapping("/download")
    public void download(HttpServletResponse response) {
        String path = "template/回收料管理导入模板.xlsx";
        ExcelUtil.download1(path, response);
    }

    @ApiOperation(value = "扫码录入")
    @GetMapping("/findByRecycleNo")
    public Result<RecycledMaterialManageDetailDto> findByRecycleNo(@ApiParam(value = "回收料编号", type = "query") @RequestParam String recycleNo) {
        String sectionNo;
        ProductionPaintingLineDetail productionPaintingLineDetail = productionPaintingLineDetailService.findBySegmentNo(recycleNo);
        if(null == productionPaintingLineDetail){
            return ResultGenerator.fail("物料编码不正确");
        }
        if(productionPaintingLineDetail.getType() != 2){
            return ResultGenerator.fail("该物料不是回收料");
        }
        //校验当前回收料码是否存在其他非取消和拒收的记录中
        List<String> usedRecycleNos = recycledMaterialManageDetailService.findUsedRecycleNos(null);
        if (usedRecycleNos != null && !usedRecycleNos.isEmpty()) {
            if (usedRecycleNos.contains(recycleNo)) {
                return ResultGenerator.fail("该物料已被组托");
            }
        }
        String fromMark = recycleNo.substring(SectionIndexRangeEnum.基地追溯产品类型.getBeginIndex(), SectionIndexRangeEnum.基地追溯产品类型.getEndIndex());
        String crystalNo = "";
        String key = "";
        if (fromMark.matches("[A-Z]+")) {

            crystalNo = recycleNo.substring(SectionIndexRangeEnum.毛棒范围.getBeginIndex(), SectionIndexRangeEnum.毛棒范围.getEndIndex());
            key = recycleNo.substring(SectionIndexRangeEnum.截断数.getBeginIndex(), SectionIndexRangeEnum.截断数.getEndIndex());
            //划线产生的
            if (productionPaintingLineDetail.getOperateDrawId() != 0) {
                //头
                if ("T".equals(key)) {
                    List<String> segmentNos = productionPaintingLineDetailService.findDetailByCrystalNo(crystalNo);
                    sectionNo = segmentNos.get(0);
                    //尾
                } else {
                    List<String> segmentNos = productionPaintingLineDetailService.findDetailByCrystalNo(crystalNo);
                    sectionNo = segmentNos.get(segmentNos.size() - 1);

                }
                //晶段反切产生的回收料
            } else {
                sectionNo = recycleNo;
            }
        } else {
            //获取单晶编号 取前11位
            crystalNo = recycleNo.substring(0, 12);
            key = recycleNo.substring(12, 13);
            //划线产生的
            if (productionPaintingLineDetail.getOperateDrawId() != 0) {
                //头
                if (key.equals("T")) {
                    List<String> segmentNos = productionPaintingLineDetailService.findDetailByCrystalNo(crystalNo);
                    sectionNo = segmentNos.get(0);
                    //尾
                } else {
                    List<String> segmentNos = productionPaintingLineDetailService.findDetailByCrystalNo(crystalNo);
                    sectionNo = segmentNos.get(segmentNos.size() - 1);

                }
                //晶段反切产生的回收料
            } else {
                sectionNo = recycleNo.substring(0, recycleNo.length() - 2);
            }
        }
        RecycledMaterialManageDetailDto dto = new RecycledMaterialManageDetailDto();
        if(productionPaintingLineDetail.getCrystalType() == 0){
            if(null != sectionNo){
                YbInspectData ybInspectData = ybInspectDataService.findBySectionNo(sectionNo);
                if(null == ybInspectData){
                    return ResultGenerator.fail("圆棒检验数据库无数据");
                }
                dto.setRecycleNo(recycleNo);
                dto.setProductionType(ybInspectData.getProductType());
                dto.setProductLevel(ybInspectData.getProductLevel());
            }else{
                return ResultGenerator.fail("回收料编号不正确");
            }
        }else{
            if(null != sectionNo){
                Result result = fbFeignClients.findDataByFbSectionNo(sectionNo);
                FbCheckOutDataDto fbInspectData = null;
                if(null != result){
                    fbInspectData = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), FbCheckOutDataDto.class);
                }
                if(null == fbInspectData){
                    return ResultGenerator.fail("方棒检验数据库无数据");
                }
                dto.setRecycleNo(recycleNo);
                dto.setProductionType(fbInspectData.getProductType());
                dto.setProductLevel(fbInspectData.getProductLevelFb());
            }else{
                return ResultGenerator.fail("回收料编号不正确");
            }
        }
        return ResultGenerator.success(dto);
    }

    @ApiOperation(value = "根据箱号(托号)更新为0的重量")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "boxNo", value = "卡板箱号", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "weight", value = "重量", dataType = "BigDecimal", paramType = "query"),
    })
    @GetMapping("/updateRecycledManageWeight")
    public Result updateRecycledManageWeight(String boxNo, BigDecimal weight) {
        RecycledMaterialManage materialManage = recycledMaterialManageService.getByBoxNo(boxNo);
        materialManage.setWeight(weight);
        recycledMaterialManageService.saveOrUpdate(materialManage);

        return ResultGenerator.success();
    }


    @ApiOperation(value = "模糊查询回收料物料主数据")
    @GetMapping("/findMaterialModelByParam")
    public Result<List<MaterialModelDto>> findMaterialModelByParam(@ApiParam(value = "单晶编号", type = "query") @RequestParam String param) {
        List<MaterialModelDto> materialModelDtos = new ArrayList<>();

        //  变更查询逻辑，从清洗模型中查
        List<MaterialCleanModel> materialCleanModels = materialCleanModelService.findByName(param);
        if (null != materialCleanModels && materialCleanModels.size()>0){
            for (MaterialCleanModel materialCleanModel : materialCleanModels) {
                MaterialModelDto materialModelDto = new MaterialModelDto();
                materialModelDto.setId(materialCleanModel.getId());
                materialModelDto.setName(materialCleanModel.getName());
                materialModelDto.setCode(materialCleanModel.getCode());
                materialModelDtos.add(materialModelDto);
            }
        }

//        List<MaterialModel> materialModels = materialModelService.findRecycledMaterialByParam(param);
//        if(null != materialModels && !materialModels.isEmpty()){
//            materialModelDtos = materialModels.stream().map(entity -> modelMapper.map(entity,MaterialModelDto.class)).collect(Collectors.toList());
//        }
        return ResultGenerator.success(materialModelDtos);
    }


    /**
     * 通过卡板箱号确定箱子在回收料中的使用状态
     * @param materialBoxNo
     * @return
     */
    @ApiOperation(value = "通过卡板箱号确定箱子在回收料中的使用状态")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "materialBoxNo", value = "卡板箱号", dataType = "String", paramType = "query"),
    })
    @GetMapping(value = "/findEmptyMaterialBoxNo")
    Result<CarrierConfig> findEmptyMaterialBoxNo(String materialBoxNo) {
        RecycledMaterialManage materialManage = recycledMaterialManageService.getByBoxNoAndStatus(materialBoxNo);
        //查看料箱配置使用状态
        CarrierConfig config = carrierConfigService.checkStatusCarrierNo(materialBoxNo);
        if (null == config) {
            return ResultGenerator.fail("该箱号: " + materialBoxNo + " 配置显示被占用或不存在!");
        }
        Result result = materialCleanFeignClients.findEmptyMaterialBoxNo(materialBoxNo);
        if (!result.getCode().equals(ResultCode.SUCCESS.code)) {
            throw new RuntimeException(result.getMessage());
        }

        if (null == materialManage) {
            return ResultGenerator.success(config);
        } else {
            return ResultGenerator.fail("该箱号: " + materialBoxNo + " 被占用,领料清空后方可使用!");
        }
    }

    @Jinko(author = "yyl", value = "根据箱号查询回收料管理详细信息")
    @ApiOperation(value = "根据箱号查询回收料管理详细信息")
    @GetMapping("/getDetailByBoxNo")
    public Result<RecycledMaterialManageDto> getDetailByBoxNo(@RequestParam String boxNo) {
        //校验硅料是否存在重复未使用的箱号
        Result result = materialCleanFeignClients.checkBox(boxNo);
        if (!result.getCode().equals(ResultCode.SUCCESS.code)) {
            throw new RuntimeException(result.getMessage());
        }
        RecycledMaterialManage materialManage = recycledMaterialManageService.getByBoxNoAndStatus(boxNo);
        RecycledMaterialManageDto dto = null;
        if (null != materialManage) {
            dto = toLazyDto1(materialManage);
            //查询详情,封装返回前端
            Long id = materialManage.getId();
            List<RecycledMaterialManageDetail> recycledMaterialManageDetails = recycledMaterialManageDetailService.getDetailByManageId(id);
            if (null != recycledMaterialManageDetails && !recycledMaterialManageDetails.isEmpty()) {
                List<RecycledMaterialManageDetailDto> recycledMaterialManageDetaiDtos = new ArrayList<>();
                recycledMaterialManageDetaiDtos = recycledMaterialManageDetails.stream().map(entity -> toTarget(entity))
                        .collect(Collectors.toList());
                dto.setRecycledMaterialMangeDetailDtos(recycledMaterialManageDetaiDtos);
            }
        }
        return ResultGenerator.success(dto);
    }

    @Jinko(author = "yyl", value = "根据批次号查询回收料管理详细信息")
    @ApiOperation(value = "根据批次号查询回收料管理详细信息")
    @GetMapping("/getByProduceBatchNo")
    public Result<com.sw.mes.core.dto.RecycledMaterialManageDto> getByProduceBatchNo(@RequestParam String produceBatchNo) {
        RecycledMaterialManage materialManage = recycledMaterialManageService.getByProduceBatchNo(produceBatchNo);
        if (null == materialManage) {
            throw new BusinessException(produceBatchNo + "的回收料信息为空!");
        }
        com.sw.mes.core.dto.RecycledMaterialManageDto recycledMaterialManageDto = toLazyNewDto(materialManage);
        return ResultGenerator.success(recycledMaterialManageDto);
    }

    private RecycledMaterialManageDetail fromDetailDto(RecycledMaterialManageDetailDto entity) {
        return modelMapper.map(entity, RecycledMaterialManageDetail.class);
    }

    private RecycledMaterialManage fromDto(RecycledMaterialManageDto recycledMaterialManageDto) {
        return modelMapper.map(recycledMaterialManageDto, RecycledMaterialManage.class);
    }

    private RecycledMaterialManage fromDto(SurplusRecycledMaterialManageDto recycledMaterialManageDto) {
        return modelMapper.map(recycledMaterialManageDto, RecycledMaterialManage.class);
    }

    private RecycledMaterialManageDetailDto toTarget(RecycledMaterialManageDetail entity) {
        return modelMapper.map(entity, RecycledMaterialManageDetailDto.class);
    }


    private RecycledMaterialManageDto toLazyDto1(RecycledMaterialManage entity) {
        //如果是null装成空字符串
        RecycledMaterialManageDto recycledMaterialManageDto = new RecycledMaterialManageDto();
        recycledMaterialManageDto.setId(Optional.ofNullable(entity.getId()).orElse(1L));
        recycledMaterialManageDto.setTrayNo(Optional.ofNullable(entity.getTrayNo()).orElse(""));
        recycledMaterialManageDto.setProduceBatchNo(Optional.ofNullable(entity.getProduceBatchNo()).orElse(""));
        recycledMaterialManageDto.setRecycledMaterialType(Optional.ofNullable(entity.getRecycledMaterialType()).orElse(""));
        recycledMaterialManageDto.setSource(Optional.ofNullable(entity.getSource()).orElse(""));
        recycledMaterialManageDto.setProductionCategory(Optional.ofNullable(entity.getProductionCategory()).orElse(""));
        recycledMaterialManageDto.setGrade(Optional.ofNullable(entity.getGrade()).orElse(""));
        recycledMaterialManageDto.setMaterialCode(Optional.ofNullable(entity.getMaterialCode()).orElse(""));
        recycledMaterialManageDto.setMaterialName(Optional.ofNullable(entity.getMaterialName()).orElse(""));
        recycledMaterialManageDto.setFactory(Optional.ofNullable(entity.getFactory()).orElse(""));
        recycledMaterialManageDto.setGear(Optional.ofNullable(entity.getGear()).orElse(""));
        recycledMaterialManageDto.setNum(Optional.ofNullable(entity.getNum()).orElse(0));
        recycledMaterialManageDto.setUnitName(Optional.ofNullable(entity.getUnitName()).orElse(""));
        recycledMaterialManageDto.setWeight(Optional.ofNullable(entity.getWeight()).orElse(new BigDecimal("0")));
        recycledMaterialManageDto.setSpecification(Optional.ofNullable(entity.getSpecification()).orElse(""));
        recycledMaterialManageDto.setStatus(Optional.ofNullable(entity.getStatus()).orElse(0));
        recycledMaterialManageDto.setCreateBy(Optional.ofNullable(entity.getCreateBy()).orElse(""));
        recycledMaterialManageDto.setCreateTime(Optional.ofNullable(entity.getCreateTime()).orElse(new Date()));
        recycledMaterialManageDto.setUpdateBy(Optional.ofNullable(entity.getUpdateBy()).orElse(""));
        recycledMaterialManageDto.setUpdateTime(Optional.ofNullable(entity.getUpdateTime()).orElse(new Date()));
        recycledMaterialManageDto.setReceiver(Optional.ofNullable(entity.getReceiver()).orElse(""));
        recycledMaterialManageDto.setReceiveTime(Optional.ofNullable(entity.getReceiveTime()).orElse(new Date()));
        recycledMaterialManageDto.setBoxNo(Optional.ofNullable(entity.getBoxNo()).orElse(""));
        recycledMaterialManageDto.setErpWarehouseCode(Optional.ofNullable(entity.getErpWarehouseCode()).orElse(""));
        recycledMaterialManageDto.setKostl(Optional.ofNullable(entity.getKostl()).orElse(""));
        recycledMaterialManageDto.setWorkOrderNo(Optional.ofNullable(entity.getWorkOrderNo()).orElse(""));
        return recycledMaterialManageDto;
    }

    private RecycledMaterialManageDto toLazyDto(RecycledMaterialManage entity) {
        return modelMapper.map(entity, RecycledMaterialManageDto.class);
    }

    private com.sw.mes.core.dto.RecycledMaterialManageDto toLazyNewDto(RecycledMaterialManage entity) {
        return modelMapper.map(entity, com.sw.mes.core.dto.RecycledMaterialManageDto.class);
    }

}
