package com.sw.mes.yb.turnstore.controller;

import com.alibaba.fastjson.JSONObject;
import com.sw.mes.base.workinprocess.service.WipStorageService;
import com.sw.mes.core.api.system.FbFeignClients;
import com.sw.mes.core.entity.FbCheckOutData;
import com.sw.mes.core.entity.SearchFilter;
import com.sw.mes.core.enums.EnumValuesFactory;
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.DynamicSpecifications;
import com.sw.mes.core.utils.NumberUtil;
import com.sw.mes.core.utils.PageUtil;
import com.sw.mes.core.utils.RequestPage;
import com.sw.mes.inspect.entity.YbInspectData;
import com.sw.mes.inspect.service.YbInspectDataService;
import com.sw.mes.yb.turnstore.dto.TurnstoreInDto;
import com.sw.mes.yb.turnstore.dto.TurnstoreInItemDto;
import com.sw.mes.yb.turnstore.dto.TurnstoreInPostDto;
import com.sw.mes.yb.turnstore.entity.TurnstoreIn;
import com.sw.mes.yb.turnstore.entity.TurnstoreInItem;
import com.sw.mes.yb.turnstore.service.TurnstoreInItemService;
import com.sw.mes.yb.turnstore.service.TurnstoreInService;
import com.sw.mes.yb.turnstore.statics.EnumValues;
import com.sw.mes.yb.turnstore.statics.Utlis;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.ServletRequest;
import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @Author
 * @Description：
 * @Date: Create in
 * @Modified By:
 */
@RestController
@RequestMapping("/turnstoreIn")
@Slf4j
@Api(description = "周转库入库申请主表接口")
public class TurnstoreInController {
    @Autowired
    private ModelMapper modelMapper;

    @Autowired
    private TurnstoreInService turnstoreInService;

    @Autowired
    private TurnstoreInItemService turnstoreInItemService;

    @Autowired
    private YbInspectDataService inspectDataBaseService;

    @Autowired
    private WipStorageService wipStorageService;

    @Autowired
    private FbFeignClients fbFeignClients;

    @ApiOperation(value = "分页查询周转库入库申请主表列表")
    @ApiImplicitParams({@ApiImplicitParam(name = "rows", value = "行数", dataType = "integer", paramType = "query"), @ApiImplicitParam(name = "page", value = "页码", dataType = "integer", paramType = "query"),})
    @GetMapping("/listByPage")
    public Result<ResponsePage<TurnstoreInDto>> listByPage(ServletRequest request, @ApiIgnore RequestPage requestPage) {
        Set<SearchFilter> searchSet = new HashSet<>();
        String sectionNo = NumberUtil.object2String(request.getParameter("sectionNo"), null);
        if (StringUtils.isNotBlank(sectionNo)) {
            TurnstoreInItem turnstoreInItem = turnstoreInItemService.findOneBySectionNo(sectionNo);
            if (turnstoreInItem != null) {
                searchSet.add(new SearchFilter("id", SearchFilter.Operator.EQ, turnstoreInItem.getInId()));
            } else {
                return ResultGenerator.success(new ResponsePage(new ArrayList(), 0L));
            }
        }
        Specification<TurnstoreIn> specification = DynamicSpecifications.bySearchFilter(request, TurnstoreIn.class, searchSet);
        Page<TurnstoreIn> page = turnstoreInService.findByExample(specification, PageUtil.createPageable(requestPage));
        List<TurnstoreInDto> dtos = page.getContent().stream().map(entity -> toLazyDto(entity)).collect(Collectors.toList());
        ResponsePage responsePage = new ResponsePage(dtos, page.getTotalElements());
        return ResultGenerator.success(responsePage);
    }

    @ApiOperation(value = "获取所有周转库入库申请主表")
    @GetMapping("/listAll")
    public Result<List<TurnstoreInDto>> listAll(ServletRequest request) {
        Specification<TurnstoreIn> specification = DynamicSpecifications.bySearchFilter(request, TurnstoreIn.class);
        List<TurnstoreIn> turnstoreIns = turnstoreInService.findByExampleSort(specification, null);
        List<TurnstoreInDto> turnstoreInDtos = turnstoreIns.stream().map(turnstoreIn -> toLazyDto(turnstoreIn)).collect(Collectors.toList());
        return ResultGenerator.success(turnstoreInDtos);
    }

    @ApiOperation(value = "pda获取所有周转库入库申请主表")
    @GetMapping("/pda/listAll")
    public Result<List<TurnstoreInDto>> listAllPda(ServletRequest request) {
        Specification<TurnstoreIn> specification = DynamicSpecifications.bySearchFilter(request, TurnstoreIn.class, new SearchFilter("state", SearchFilter.Operator.NOT, EnumValues.InState.已入库.getValue()));
        List<TurnstoreIn> turnstoreIns = turnstoreInService.findByExampleSort(specification, null);
        List<TurnstoreInDto> turnstoreInDtos = turnstoreIns.stream().map(turnstoreIn -> toLazyDto(turnstoreIn)).collect(Collectors.toList());
        return ResultGenerator.success(turnstoreInDtos);
    }

    @ApiOperation(value = "周转库入库申请主表详细信息")
    @GetMapping("/{id}")
    public Result<TurnstoreInPostDto> get(@PathVariable @ApiParam(value = "周转库入库申请主表id") Integer id) {
        TurnstoreIn turnstoreIn = turnstoreInService.get(id);
        if (null == turnstoreIn) {
            return ResultGenerator.fail("该周转库入库申请主表不存在");
        }
        TurnstoreInPostDto entity = fromDto(turnstoreIn);
        List<TurnstoreInItem> items = turnstoreInItemService.getItemsByInId(id);
        entity.setItems(toDto(items));
        return ResultGenerator.success(entity);
    }

    @ApiOperation(value = "周转库圆棒入库申请获取最新批次号")
    @GetMapping("/getMaxBatchNo")
    public Result getMaxBatchNo() {
        Long maxBatchNo = turnstoreInService.getMaxBatchNo();
        if (maxBatchNo == null) {
            maxBatchNo = new Long(0);
        }
        if (maxBatchNo != 0) {
            maxBatchNo = maxBatchNo + 1;
        }
        return ResultGenerator.success(maxBatchNo);
    }

    @ApiOperation(value = "创建方棒退库申请")
    @PostMapping("/create")
    public Result create(@RequestBody @Valid @ApiParam(value = "方棒退库申请对象") TurnstoreInPostDto turnstoreInPostDto, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        if (turnstoreInPostDto == null) {
            return ResultGenerator.fail("方棒退库申请错误");
        }
        if (turnstoreInPostDto.getItems() == null || turnstoreInPostDto.getItems().size() == 0) {
            return ResultGenerator.fail("方棒退库申请明细错误");
        }
        //查看批次号是否存在
        List<TurnstoreIn> checkList = turnstoreInService.getItemsByBatchNo(turnstoreInPostDto.getBatchNo());
        if (checkList != null) {
            if (checkList.size() > 0) {
                //存在批次号 返回最新的批次号
                Long maxBatchNo = turnstoreInService.getMaxBatchNo();
                maxBatchNo = maxBatchNo + 1;
                return ResultGenerator.success(maxBatchNo);
            }
        }
        TurnstoreIn turnstoreIn = fromDto(turnstoreInPostDto);
        List<TurnstoreInItem> items = fromDto(turnstoreInPostDto.getItems());
        try {
            //添加判断，退回料修改需要判断是否存在申请入库和已入库的
            handleIsReturnRecordBySectionNoList(items, turnstoreInPostDto.getPurpose());
            turnstoreInService.createIn(turnstoreIn, items);
        } catch (Exception e) {
            return ResultGenerator.fail(e.getMessage());
        }
        return ResultGenerator.success();
    }

    private void handleIsReturnRecordBySectionNoList(List<TurnstoreInItem> items, String purpose) {
        List<String> sectionNoList = Optional.ofNullable(items).orElse(new ArrayList<>()).stream().map(TurnstoreInItem::getSectionNo).collect(Collectors.toList());
        //添加判断非拒收单晶不能重复退料
        if (turnstoreInItemService.getIsReturnRecordBySectionNoList(sectionNoList, purpose)) {
            throw new RuntimeException("退库中，已申请或已入库的托号不可重复退料！");
        }
    }

    @ApiOperation(value = "更新周转库入库申请")
    @PostMapping("/update")
    public Result update(@RequestBody @Valid @ApiParam(value = "周转库入库申请") TurnstoreInPostDto turnstoreInPostDto, BindingResult bindingResult) {
        if (turnstoreInPostDto == null) {
            return ResultGenerator.fail("入库申请错误");
        }
        if (turnstoreInPostDto.getItems() == null || turnstoreInPostDto.getItems().size() == 0) {
            return ResultGenerator.fail("入库申请明细错误");
        }
        TurnstoreIn entity = turnstoreInService.get(turnstoreInPostDto.getId());
        if (entity == null) {
            return ResultGenerator.fail("原信息不存在");
        }
        if (entity.getState().equals(EnumValues.InState.已入库.getValue())) {
            return ResultGenerator.fail("已入库申请不能编辑");
        }
        try {
            TurnstoreIn turnstoreIn = fromDto(turnstoreInPostDto);
            List<TurnstoreInItem> items = fromDto(turnstoreInPostDto.getItems());
            //添加判断，退回料修改需要判断是否存在申请入库和已入库的
            handleIsReturnRecordBySectionNoList(items, turnstoreInPostDto.getPurpose());
            turnstoreInService.updateIn(turnstoreIn, items);
            return ResultGenerator.success();
        } catch (Exception e) {
            return ResultGenerator.fail(e.getMessage());
        }

    }

    @ApiOperation(value = "删除周转库入库申请主表")
    @PostMapping("/delete")
    public Result remove(@ApiParam(value = "id集合,逗号分隔,如2,4", type = "query") @RequestParam Integer[] ids) {
        for (Integer id : ids) {
            turnstoreInService.deleteIn(id);
        }
        return ResultGenerator.success();
    }

    //周转库退回申请单
    @ApiOperation(value = "周转库退回申请单")
    @PostMapping("/backIn")
    public Result backIn(@ApiParam(value = "id集合,逗号分隔,如2,4", type = "query") @RequestParam Integer[] ids, @ApiParam(value = "操作人", type = "query") @RequestParam String user) {
        for (Integer id : ids) {
            turnstoreInService.backIn(id, user);
        }
        return ResultGenerator.success();
    }

    //周转库退回申请单
    @ApiOperation(value = "周转库退回申请单")
    @PostMapping("/backInPda")
    public Result backInPda(@ApiParam(value = "id集合,逗号分隔,如2,4", type = "query") @RequestParam Integer[] ids, @ApiParam(value = "操作人", type = "query") @RequestParam String user) {
        for (Integer id : ids) {
            turnstoreInService.backIn(id, user);
        }
        return ResultGenerator.success();
    }

    //周转库操作确认入库
    @ApiOperation(value = "周转库操作确认入库")
    @PostMapping("/confirmIn")
    public Result confirmIn(@ApiParam(value = "id集合,逗号分隔,如2,4", type = "query") @RequestParam Integer[] ids, @ApiParam(value = "操作人", type = "query") @RequestParam String user) {
        for (Integer id : ids) {
            turnstoreInService.confirmIn(id, user);
        }
        return ResultGenerator.success();
    }

    //周转库操作确认入库
    @ApiOperation(value = "周转库操作确认入库")
    @PostMapping("/confirmInPda")
    public Result confirmInPda(@ApiParam(value = "id集合,逗号分隔,如2,4", type = "query") @RequestParam Integer[] ids, @ApiParam(value = "操作人", type = "query") @RequestParam String user) {
        for (Integer id : ids) {
            turnstoreInService.confirmIn(id, user);
        }
        return ResultGenerator.success();
    }

    //周转库单条获取晶棒检验信息
    @ApiOperation(value = "周转库单条获取晶棒检验信息")
    @ApiImplicitParams({@ApiImplicitParam(name = "sectionNo", value = "晶段编号", paramType = "query", dataType = "String"), @ApiImplicitParam(name = "purpose", value = "去向", paramType = "query", dataType = "String"),})
    @GetMapping("/turnstoreGetInspect")
    public Result turnstoreGetInspect(@RequestParam String sectionNo, @RequestParam String purpose, @RequestParam String returnStation) {
        if (StringUtils.isBlank(sectionNo)) {
            return ResultGenerator.fail("晶段编号不能为空！");
        }
        if (StringUtils.isBlank(purpose)) {
            return ResultGenerator.fail("去向不能为空！");
        }
        //添加判断非拒收单晶不能重复退料
        if (turnstoreInItemService.getIsReturnRecordBySectionNoList(Arrays.asList(sectionNo), purpose)) {
            return ResultGenerator.fail("已申请或已入库的晶段不可重复退料！");
        }

        String stationKey = "";
        switch (returnStation) {
            case "开方站":
                stationKey = EnumValuesFactory.WipStorageCode.开方.getKey();
                break;
            case "粘圆棒站":
                stationKey = EnumValuesFactory.WipStorageCode.粘圆棒.getKey();
                break;
            case "粘方棒站":
                stationKey = EnumValuesFactory.WipStorageCode.粘方棒.getKey();
                break;
        }
        //非站点单晶，不能退库
        wipStorageService.selectWipStorage(sectionNo, stationKey, null);
        YbInspectData tempInspectDataBase = null;
        TurnstoreInItem resultTurnstoreInItem = null;
        if (StringUtils.equals(purpose, EnumValues.ReturnPurposeType.ROUND_ROD_INSPECTION.getValue())) {
            try {
                tempInspectDataBase = inspectDataBaseService.findBySectionNo(sectionNo);
                if (null == tempInspectDataBase) {
                    return ResultGenerator.fail("周转库获取圆棒棒检验信息失败！");
                }
                //计算入库长度 入库重量
                resultTurnstoreInItem = setEntity(tempInspectDataBase, false, null);
                //入库长度=圆棒长度-细减长-崩晶线
                resultTurnstoreInItem.setInstoreLength(Utlis.getInstoreLength(resultTurnstoreInItem.getActualLength(), resultTurnstoreInItem.getFineCutLength(), resultTurnstoreInItem.getCollapseLine()));
                //入库重量
                resultTurnstoreInItem.setInstoreWeight(Utlis.getInstoreWeight(resultTurnstoreInItem.getProductTypeSecond(), resultTurnstoreInItem.getInstoreLength()));

            } catch (Exception e) {
                e.printStackTrace();
                return ResultGenerator.fail("周转库获取晶棒检验信息失败！");
            }

        } else if (StringUtils.equals(purpose, EnumValues.ReturnPurposeType.SQUARE_ROD_INSPECTION.getValue())) {
            Result<FbCheckOutData> fbCheckOutDataByFbSectionNo = fbFeignClients.findFbCheckOutDataByFbSectionNo(sectionNo);
            if (fbCheckOutDataByFbSectionNo.getCode() == ResultCode.SUCCESS.getCode()) {
                FbCheckOutData fbCheckOutData = fbCheckOutDataByFbSectionNo.getData();
                if (null == fbCheckOutData) {
                    return ResultGenerator.fail("周转库获取方棒检验信息失败！");
                }
                resultTurnstoreInItem = setEntity(null, true, fbCheckOutData);
            } else {
                return fbCheckOutDataByFbSectionNo;
            }
        } else {
            return ResultGenerator.fail("方棒退料去向存在问题！");
        }

        return ResultGenerator.success(resultTurnstoreInItem);
    }

    //圆棒确认接收方棒退料
    @ApiOperation(value = "圆棒确认接收方棒退料")
    @PostMapping("/confirmOut")
    public Result confirmOut(@RequestBody String params) {
        if (StringUtils.isBlank(params)) {
            return ResultGenerator.fail("传入参数为空！");
        }
        JSONObject parseObject = JSONObject.parseObject(params);
        List<TurnstoreInItem> turnstoreInItems = JSONObject.parseArray(parseObject.getString("items").toString(), TurnstoreInItem.class);
        TurnstoreIn turnstoreIn = JSONObject.parseObject(params, TurnstoreIn.class);
        try {
            turnstoreInService.confirmOut(turnstoreIn, turnstoreInItems);
        } catch (Exception e) {
            return ResultGenerator.fail(e.getMessage());
        }

        return ResultGenerator.success();
    }

    @ApiOperation(value = "取消方棒退料")
    @PostMapping("/cancelTurnstore")
    public Result cancelTurnstore(@ApiParam(value = "id集合,逗号分隔,如2,4", type = "query") @RequestParam Integer[] ids, String confirmUser) {
        for (Integer id : ids) {
            turnstoreInService.cancelTurnstore(id, confirmUser);
        }
        return ResultGenerator.success();
    }

    //PDA确认接收方棒退料
    @ApiOperation(value = "PDA确认接收方棒退料")
    @PostMapping("/confirmOutPda")
    public Result confirmOutPda(@RequestBody TurnstoreInItem turnstoreInItem) {
        if (null == turnstoreInItem) {
            return ResultGenerator.fail("传入参数为空！");
        }
        if (null == turnstoreInItem.getId() || StringUtils.isBlank(turnstoreInItem.getWithdrawingType())) {
            return ResultGenerator.fail("接收Id或类型为空！");
        }
        TurnstoreInItem turnstoreInItem1 = turnstoreInItemService.get(turnstoreInItem.getId());
        if (null == turnstoreInItem1) {
            return ResultGenerator.fail("接收Id查询不到数据！");
        }
        TurnstoreIn turnstoreIn1 = turnstoreInService.get(turnstoreInItem1.getInId());
        if (null == turnstoreInItem1) {
            return ResultGenerator.fail("接收单查询不到数据！");
        }
        List<TurnstoreInItem> itemsByInIds = turnstoreInItemService.getItemsByInId(turnstoreIn1.getId());
        try {
            turnstoreInService.confirmOut(turnstoreIn1, itemsByInIds);
        } catch (Exception e) {
            return ResultGenerator.fail(e.getMessage());
        }
        return ResultGenerator.success();
    }

    @ApiOperation(value = "圆棒退回方棒退料")
    @PostMapping("/returnTurnstore")
    public Result returnTurnstore(@ApiParam(value = "id集合,逗号分隔,如2,4", type = "query") @RequestParam Integer[] ids, @RequestParam String confirmUser, @RequestParam String reason, @RequestParam(required = false) String remark) {
        for (Integer id : ids) {
            turnstoreInService.returnTurnstore(id, confirmUser, reason, remark);
        }
        return ResultGenerator.success();
    }

    public TurnstoreInItem setEntity(YbInspectData tempInspectDataBase, Boolean isFb, FbCheckOutData fbCheckOutData) {

        TurnstoreInItem entity = new TurnstoreInItem();
        if (isFb) {
            entity.setSectionNo(fbCheckOutData.getFbSectionNo());
            entity.setProductLevelSecond(fbCheckOutData.getExperiLevel());
            entity.setProductLevelExperiment(fbCheckOutData.getFbExperiLevel());
            entity.setProductTypeSecond(fbCheckOutData.getPlanSpecs());
            entity.setActualLength(fbCheckOutData.getLength());
            entity.setInstoreLength(fbCheckOutData.getInstoreLengthFb());
            entity.setActualWeight(fbCheckOutData.getWeight());
            entity.setInstoreWeight(fbCheckOutData.getTheoryWeightFb());
            entity.setSectionType(fbCheckOutData.getSpecification());
            entity.setReCheckType(fbCheckOutData.getReCheckType());
            entity.setBackCutType(null != fbCheckOutData.getRecutLength() && fbCheckOutData.getRecutLength().equals(0) ? "是" : "否");

        } else {
            entity.setSectionNo(tempInspectDataBase.getSectionNo());
            entity.setProductLevelSecond(tempInspectDataBase.getProductLevel());
            entity.setProductLevelExperiment(tempInspectDataBase.getProductLevelExperiment());
            entity.setProductTypeSecond(tempInspectDataBase.getProductTypeSecond());
            entity.setActualLength(tempInspectDataBase.getActualLength());
//            entity.setActualWeight(tempInspectDataBase.getActualWeight());
//            entity.setFineCutLength(tempInspectDataBase.getFineCutLength());
//            entity.setCollapseLine(tempInspectDataBase.getCollapseLine());
            entity.setSectionType(tempInspectDataBase.getSectionType());
            entity.setReCheckType(tempInspectDataBase.getReCheckType());
            entity.setBackCutType(null != tempInspectDataBase.getIsCutBack() && tempInspectDataBase.getIsCutBack().equals(1) ? "是" : "否");

        }
        return entity;
    }


    //退回的申请单重新提交
    public TurnstoreInDto toLazyDto(TurnstoreIn entity) {
        return modelMapper.map(entity, TurnstoreInDto.class);
    }

    public TurnstoreInDto toEagerDto(TurnstoreIn entity) {
        TurnstoreInDto dto = modelMapper.map(entity, TurnstoreInDto.class);
        return dto;
    }

    public TurnstoreIn fromDto(TurnstoreInDto dto) {
        //ModelMapper modelMapper = new ModelMapper();
        modelMapper.getConfiguration().setFullTypeMatchingRequired(true);
        modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
        return modelMapper.map(dto, TurnstoreIn.class);
    }

    public TurnstoreIn fromDto(TurnstoreInPostDto dto) {
        //ModelMapper modelMapper = new ModelMapper();
        modelMapper.getConfiguration().setFullTypeMatchingRequired(true);
        modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
        return modelMapper.map(dto, TurnstoreIn.class);
    }

    public TurnstoreInPostDto fromDto(TurnstoreIn dto) {
        //ModelMapper modelMapper = new ModelMapper();
        modelMapper.getConfiguration().setFullTypeMatchingRequired(true);
        modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
        return modelMapper.map(dto, TurnstoreInPostDto.class);
    }

    public List<TurnstoreInItem> fromDto(List<TurnstoreInItemDto> dto) {
        //ModelMapper modelMapper = new ModelMapper();
        modelMapper.getConfiguration().setFullTypeMatchingRequired(true);
        modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
        List<TurnstoreInItem> listEntity = dto.stream().map(turnstoreInItem -> modelMapper.map(turnstoreInItem, TurnstoreInItem.class)).collect(Collectors.toList());
        return listEntity;
    }

    public List<TurnstoreInItemDto> toDto(List<TurnstoreInItem> dto) {
        //ModelMapper modelMapper = new ModelMapper();
        modelMapper.getConfiguration().setFullTypeMatchingRequired(true);
        modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
        List<TurnstoreInItemDto> listEntity = dto.stream().map(turnstoreInItemDto -> modelMapper.map(turnstoreInItemDto, TurnstoreInItemDto.class)).collect(Collectors.toList());
        return listEntity;
    }
}
