package com.sw.mes.itemclean.clean.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sw.mes.core.annotation.Jinko;
import com.sw.mes.core.enums.EnumValuesFactory;
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.itemclean.clean.domain.CleaningProcessFlow;
import com.sw.mes.itemclean.clean.domain.MaterialUnpacking;
import com.sw.mes.itemclean.clean.dto.*;
import com.sw.mes.itemclean.clean.service.*;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * @Author
 * @Description：
 * @Date: Create in
 * @Modified By:
 */
@RestController
@RequestMapping("/CleaningProcessFlow")
@Slf4j
@Api(tags = "料理清洗工艺路线接口")
public class CleaningProcessFlowController {
    @Autowired
    ModelMapper modelMapper;

    @Autowired
    private CleaningProcessFlowService cleaningProcessFlowService;

    @Autowired
    private MaterialStoreSignBoxService materialStoreSignBoxService;

    @Autowired
    private MaterialUnpackingService materialUnpackingService;

    @Autowired
    private MaterialCleaningService materialCleaningService;

    @Autowired
    private MaterialBrokenService materialBrokenService;

    @Autowired
    private MaterialGroupService materialGroupService;

    @ApiOperation(value = "分页查询料理清洗工艺路线列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "rows", value = "行数", dataType = "integer", paramType = "query"),
            @ApiImplicitParam(name = "page", value = "页码", dataType = "integer", paramType = "query"),
    })
    @GetMapping("/listByPage")
    public Result<ResponsePage<CleaningProcessFlowDto>> listByPage(ServletRequest request, @ApiIgnore RequestPage requestPage) {
        //分页查询
        QueryWrapper<CleaningProcessFlow> queryWrapper = DynmaicQueryWrapper.searchFilter(request, CleaningProcessFlow.class);
        Page<CleaningProcessFlow> listPage = cleaningProcessFlowService.page(new Page<>(requestPage.getPage(), requestPage.getRows()), queryWrapper);
        List<CleaningProcessFlowDto> dtos = listPage.getRecords().stream()
                .map(entity -> toLazyDto(entity))
                .collect(Collectors.toList());
        ResponsePage responsePage = new ResponsePage(dtos, listPage.getTotal());
        return ResultGenerator.success(responsePage);
    }

    @ApiOperation(value = "获取所有料理清洗工艺路线")
    @GetMapping("/listAll")
    public Result<List<CleaningProcessFlowDto>> listAll(ServletRequest request) {
        QueryWrapper<CleaningProcessFlow> queryWrapper = DynmaicQueryWrapper.searchFilter(request, CleaningProcessFlow.class);
        List<CleaningProcessFlow> materialBrokens = cleaningProcessFlowService.list(queryWrapper);
        List<CleaningProcessFlowDto> materialBrokenDtos = materialBrokens.stream()
                .map(materialBroken -> toLazyDto(materialBroken))
                .collect(Collectors.toList());
        return ResultGenerator.success(materialBrokenDtos);
    }

    @ApiOperation(value = "料理清洗工艺路线详细信息")
    @GetMapping("/{id}")
    public Result<CleaningProcessFlowDto> get(@PathVariable @ApiParam(value = "料理清洗工艺路线id") Integer id) {
        CleaningProcessFlow materialBroken = cleaningProcessFlowService.getById(id);
        if (null == materialBroken) {
            return ResultGenerator.fail("该对象不存在");
        }
        return ResultGenerator.success(toEagerDto(materialBroken));
    }

    @ApiOperation(value = "创建料理清洗工艺路线")
    @PostMapping("/create")
    public Result create(@RequestBody @Valid @ApiParam(value = "料理清洗工艺路线对象") CleaningProcessFlowDto cleaningProcessFlowDto, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        CleaningProcessFlow cleaningProcessFlow = fromDto(cleaningProcessFlowDto);
        cleaningProcessFlowService.saveOrUpdate(cleaningProcessFlow);
        return ResultGenerator.success();
    }

    /**
     * @param workOrder       工单/出站工单号(批次号)
     * @param masterWorkOrder 母工单/出站工单号
     * @param weight          重量
     * @param unusedWeight    未使用重量
     * @param usedWeight      已使用重量
     * @param deviceNo        设备号
     * @param wipStorageCode  站点代码
     * @param flowLineLable   站点路径
     * @param boxNo           载具号
     * @param lastSite        上一站点
     * @param type            0：工序进站，1：工序出站，2：工序待进站
     * @return
     */
    @ApiOperation("料理-出站")
    @GetMapping("/outStation")
    public Result outStation(@RequestParam String workOrder, @RequestParam String masterWorkOrder, @RequestParam BigDecimal weight, @RequestParam BigDecimal unusedWeight, @RequestParam BigDecimal usedWeight, @RequestParam String deviceNo, @RequestParam String wipStorageCode, @RequestParam String flowLineLable, @RequestParam String boxNo, @RequestParam String lastSite, @RequestParam Integer type) {
        Result result = cleaningProcessFlowService.inStation(workOrder, masterWorkOrder, weight, unusedWeight, usedWeight, deviceNo, wipStorageCode, flowLineLable, boxNo, lastSite, type);
        return result;
    }

    @ApiOperation("料理-进站")
    @GetMapping("/inStation")
    public Result inStation(@RequestParam String workOrder, @RequestParam String masterWorkOrder, @RequestParam BigDecimal weight, @RequestParam BigDecimal unusedWeight, @RequestParam BigDecimal usedWeight, @RequestParam String deviceNo, @RequestParam String wipStorageCode, @RequestParam String flowLineLable, @RequestParam String boxNo, @RequestParam String lastSite, @RequestParam Integer type) {
        Result result = cleaningProcessFlowService.outStation(workOrder, masterWorkOrder, weight, unusedWeight, usedWeight, deviceNo, wipStorageCode, flowLineLable, boxNo, lastSite, type);
        return result;
    }

    @Jinko(author = "yyl", value = "查询硅料在制列表及详情列表")
    @ApiOperation(value = "查询硅料在制列表及详情列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "search_LIKE_materialName", value = "物料名称", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_LIKE_materialCode", value = "物料编码", dataType = "string", paramType = "query"),
    })
    @GetMapping("/queryWorkInProcessAndDetailList")
    public Result<ResponsePage<WorkInCleanProgressDto>> queryWorkInProcessAndDetailList(ServletRequest request) {
        WorkInCleanProcessParamQuery query = new WorkInCleanProcessParamQuery();
        query.setMaterialName(request.getParameter("search_LIKE_materialName"))
                .setMaterialCode(request.getParameter("search_LIKE_materialCode"));
        //1 查询外层列表
        List<WorkInCleanProgressDto> records = cleaningProcessFlowService.queryWorkInProcessList(query);
        //2 查询明细详情
        List<WorkInCleanProgressDetailDto> details = cleaningProcessFlowService.findDetailByMaterialCode(query);
        //3 去重物料编码
        Map<String, String> map = records.stream()
                .collect(Collectors.toMap(
                        WorkInCleanProgressDto::getMaterialCode,
                        WorkInCleanProgressDto::getMaterialName,
                        (name1, name2) -> name1 + ", " + name2 // 合并函数
                ));
        //4 准备接收合并数据的集合
        List<WorkInCleanProgressDto> newRecords = new ArrayList<>();
        //5 合并物料编码相同的物料
        for (String materialCode : map.keySet()) {
            //封装新的dto
            WorkInCleanProgressDto workInCleanProgressDto = new WorkInCleanProgressDto();
            List<WorkInCleanProgressDetailDto> progressDetailDtos = details.stream()
                    .collect(Collectors.groupingBy(WorkInCleanProgressDetailDto::getMaterialCode))
                    .get(materialCode);
            //6 赋值明细
            workInCleanProgressDto.setWorkInCleanProgressDetailDtos(progressDetailDtos);
            workInCleanProgressDto.setCleanWeight(BigDecimal.ZERO);
            workInCleanProgressDto.setWaitCleanWeight(BigDecimal.ZERO);
            workInCleanProgressDto.setWaitUnpackingWeight(BigDecimal.ZERO);
            workInCleanProgressDto.setDustFreeWeight(BigDecimal.ZERO);
            workInCleanProgressDto.setWaitDustFreeWeight(BigDecimal.ZERO);
            workInCleanProgressDto.setDustFreeFinishWeight(BigDecimal.ZERO);
            //7 赋值不同重量属性
            for (WorkInCleanProgressDto dto : records) {
                String type = dto.getType();
                BigDecimal weight = dto.getWeight();
                String code = dto.getMaterialCode();
                if (materialCode.equals(code)) {
                    workInCleanProgressDto.setMaterialCode(code);
                    workInCleanProgressDto.setMaterialName(dto.getMaterialName());
                    switch (type) {
                        //待分选重量waitUnpackingWeight
                        case "1":
                            workInCleanProgressDto.setWaitUnpackingWeight(weight);
                            break;
                        //待清洗重量waitCleanWeight
                        case "2":
                            workInCleanProgressDto.setWaitCleanWeight(weight);
                            break;
                        //无尘待收货量waitDustFreeWeight
                        case "3":
                            workInCleanProgressDto.setWaitDustFreeWeight(weight);
                            break;
                        //已清洗重量cleanWeight
                        case "4":
                            workInCleanProgressDto.setCleanWeight(weight);
                            break;
                        //无尘收货重量dustFreeWeight
                        case "5":
                            workInCleanProgressDto.setDustFreeWeight(weight);
                            break;
                        //无尘成品重量dustFreeFinishWeight
                        case "6":
                            workInCleanProgressDto.setDustFreeFinishWeight(weight);
                            break;
                    }
                }
            }
            //8 合并新数据
            newRecords.add(workInCleanProgressDto);
        }
        ResponsePage responsePage = new ResponsePage(newRecords, Long.valueOf(newRecords.size()));
        return ResultGenerator.success(responsePage);
    }

    @Jinko(author = "yyl", value = "分页查询硅料在制列表")
    @ApiOperation(value = "分页查询硅料在制列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "rows", value = "行数", dataType = "integer", paramType = "query"),
            @ApiImplicitParam(name = "page", value = "页码", dataType = "integer", paramType = "query"),
            @ApiImplicitParam(name = "search_LIKE_materialName", value = "物料名称", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_LIKE_materialCode", value = "物料编码", dataType = "string", paramType = "query"),
    })

    @GetMapping("/queryWorkInProcessPage")
    public Result<ResponsePage<WorkInCleanProgressDto>> queryWorkInProcessPage(ServletRequest request, @ApiIgnore RequestPage requestPage) {
        WorkInCleanProcessParamQuery query = new WorkInCleanProcessParamQuery();
        query.setMaterialName(request.getParameter("search_LIKE_materialName"))
                .setMaterialCode(request.getParameter("search_LIKE_materialCode"));
        //1 查询外层列表
        IPage<WorkInCleanProgressDto> iPage = new Page<>(requestPage.getPage(), requestPage.getRows());
        IPage<WorkInCleanProgressDto> workInCleanProgressDtoIPage = cleaningProcessFlowService.queryWorkInProcessPage(iPage, query);
        List<WorkInCleanProgressDto> records = workInCleanProgressDtoIPage.getRecords();
        for (WorkInCleanProgressDto workInCleanProgressDto : records) {
            String type = workInCleanProgressDto.getType();
            BigDecimal weight = workInCleanProgressDto.getWeight();
            switch (type) {
                //待分选重量waitUnpackingWeight
                case "1":
                    workInCleanProgressDto.setWaitUnpackingWeight(weight);
                    break;
                //待清洗重量waitCleanWeight
                case "2":
                    workInCleanProgressDto.setWaitCleanWeight(weight);
                    break;
                //无尘待收货量waitDustFreeWeight
                case "3":
                    workInCleanProgressDto.setWaitDustFreeWeight(weight);
                    break;
                //已清洗重量cleanWeight
                case "4":
                    workInCleanProgressDto.setCleanWeight(weight);
                    break;
                //无尘收货重量dustFreeWeight
                case "5":
                    workInCleanProgressDto.setDustFreeWeight(weight);
                    break;
                //无尘成品重量dustFreeFinishWeight
                case "6":
                    workInCleanProgressDto.setDustFreeFinishWeight(weight);
                    break;
            }
        }
        ResponsePage responsePage = new ResponsePage(records, workInCleanProgressDtoIPage.getTotal());
        return ResultGenerator.success(responsePage);
    }

    @Jinko(author = "yyl", value = "查询硅料在制列表")
    @ApiOperation(value = "查询硅料在制列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "search_LIKE_materialName", value = "物料名称", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_LIKE_materialCode", value = "物料编码", dataType = "string", paramType = "query"),
    })
    @GetMapping("/queryWorkInProcessList")
    public Result<ResponsePage<WorkInCleanProgressDto>> queryWorkInProcessList(ServletRequest request) {
        WorkInCleanProcessParamQuery query = new WorkInCleanProcessParamQuery();
        query.setMaterialName(request.getParameter("search_LIKE_materialName"))
                .setMaterialCode(request.getParameter("search_LIKE_materialCode"));
        //1 查询外层列表
        List<WorkInCleanProgressDto> records = cleaningProcessFlowService.queryWorkInProcessList(query);

        //2 去重物料编码
        Map<String, String> map = records.stream()
                .collect(Collectors.toMap(
                        WorkInCleanProgressDto::getMaterialCode,
                        WorkInCleanProgressDto::getMaterialName,
                        (name1, name2) -> name1 + ", " + name2 // 合并函数
                ));
        //3 准备接收合并数据的集合
        List<WorkInCleanProgressDto> newRecords = new ArrayList<>();
        //4 合并物料编码相同的物料
        for (String materialCode : map.keySet()) {
            //5 封装新的dto
            WorkInCleanProgressDto workInCleanProgressDto = new WorkInCleanProgressDto();
            //6 初始化不同重量属性
            workInCleanProgressDto.setCleanWeight(BigDecimal.ZERO);
            workInCleanProgressDto.setWaitCleanWeight(BigDecimal.ZERO);
            workInCleanProgressDto.setWaitUnpackingWeight(BigDecimal.ZERO);
            workInCleanProgressDto.setDustFreeWeight(BigDecimal.ZERO);
            workInCleanProgressDto.setWaitDustFreeWeight(BigDecimal.ZERO);
            workInCleanProgressDto.setDustFreeFinishWeight(BigDecimal.ZERO);
            //7 赋值不同重量属性
            for (WorkInCleanProgressDto dto : records) {
                String type = dto.getType();
                BigDecimal weight = dto.getWeight();
                String code = dto.getMaterialCode();
                if (materialCode.equals(code)) {
                    workInCleanProgressDto.setMaterialCode(code);
                    workInCleanProgressDto.setMaterialName(dto.getMaterialName());
                    switch (type) {
                        //待分选重量waitUnpackingWeight
                        case "1":
                            workInCleanProgressDto.setWaitUnpackingWeight(weight);
                            break;
                        //待清洗重量waitCleanWeight
                        case "2":
                            workInCleanProgressDto.setWaitCleanWeight(weight);
                            break;
                        //无尘待收货量waitDustFreeWeight
                        case "3":
                            workInCleanProgressDto.setWaitDustFreeWeight(weight);
                            break;
                        //已清洗重量cleanWeight
                        case "4":
                            workInCleanProgressDto.setCleanWeight(weight);
                            break;
                        //无尘收货重量dustFreeWeight
                        case "5":
                            workInCleanProgressDto.setDustFreeWeight(weight);
                            break;
                        //无尘成品重量dustFreeFinishWeight
                        case "6":
                            workInCleanProgressDto.setDustFreeFinishWeight(weight);
                            break;
                    }
                }
            }
            //8 合并新数据
            newRecords.add(workInCleanProgressDto);
        }
        ResponsePage responsePage = new ResponsePage(newRecords, Long.valueOf(newRecords.size()));
        return ResultGenerator.success(responsePage);
    }

    @Jinko(author = "yyl", value = "查询硅料在制详情列表")
    @ApiOperation(value = "查询硅料在制详情列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "search_LIKE_materialName", value = "物料名称", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_LIKE_materialCode", value = "物料编码", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_LIKE_fxProductBatchNo", value = "分选pp号", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_EQ_type",
                    value = "在制类型:1 待分选重量waitUnpackingWeight,2 待清洗重量waitCleanWeight,3 无尘待收货量waitDustFreeWeight,4 已清洗重量cleanWeight,5 无尘收货重量dustFreeWeight 6无尘成品重量dustFreeFinishWeight",
                    dataType = "string", paramType = "query"),
    })
    @GetMapping("/queryWorkInProcessDetailList")
    public Result<ResponsePage<WorkInCleanProgressDetailDto>> queryWorkInProcessDetailList(ServletRequest request) {
        WorkInCleanProcessParamQuery query = new WorkInCleanProcessParamQuery();
        query.setMaterialName(request.getParameter("search_LIKE_materialName"))
                .setMaterialCode(request.getParameter("search_LIKE_materialCode"))
                .setFxProductBatchNo(request.getParameter("search_LIKE_fxProductBatchNo"));
        String type = request.getParameter("search_EQ_type");
        //查询明细详情
        List<WorkInCleanProgressDetailDto> details = cleaningProcessFlowService.findDetailByMaterialCode(query);
        //筛选对应在制类型数据
        if (StringUtils.isNotBlank(type)) {
            details = details.stream()
                    .collect(Collectors.groupingBy(WorkInCleanProgressDetailDto::getType))
                    .get(type);
        }

        ResponsePage responsePage = new ResponsePage(details, Long.valueOf(details.size()));
        return ResultGenerator.success(responsePage);
    }

    @Jinko(author = "yyl", value = "硅料加工记录-硅料在制查询明细-导出")
    @ApiOperation(value = "硅料加工记录-硅料在制查询明细-导出")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "search_LIKE_materialName", value = "物料名称", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_LIKE_materialCode", value = "物料编码", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_LIKE_fxProductBatchNo", value = "分选pp号", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_EQ_type",
                    value = "在制类型:1 待分选重量waitUnpackingWeight,2 待清洗重量waitCleanWeight,3 无尘待收货量waitDustFreeWeight,4 已清洗重量cleanWeight,5 无尘收货重量dustFreeWeight 6无尘成品重量dustFreeFinishWeight",
                    dataType = "string", paramType = "query"),
    })
    @GetMapping("/export")
    public void export(ServletRequest request, HttpServletResponse response) {
        try {
            WorkInCleanProcessParamQuery query = new WorkInCleanProcessParamQuery();
            query.setMaterialName(request.getParameter("search_LIKE_materialName"))
                    .setMaterialCode(request.getParameter("search_LIKE_materialCode"))
                    .setFxProductBatchNo(request.getParameter("search_LIKE_fxProductBatchNo"));
            String type = request.getParameter("search_EQ_type");
            //查询明细详情
            List<WorkInCleanProgressDetailDto> details = cleaningProcessFlowService.findDetailByMaterialCode(query);
            //筛选对应在制类型数据
            if (StringUtils.isNotBlank(type)) {
                details = details.stream()
                        .collect(Collectors.groupingBy(WorkInCleanProgressDetailDto::getType))
                        .get(type);
            }
            EasyExcelUtils.write(response, WorkInCleanProgressDetailDto.class, "硅料在制查询明细", "硅料在制查询明细", details);
        } catch (Exception e) {
            throw new RuntimeException("导出单硅料在制查询明细失败，错误信息：" + e.getMessage());
        }
    }

    public CleaningProcessFlowDto toLazyDto(CleaningProcessFlow entity) {
        return modelMapper.map(entity, CleaningProcessFlowDto.class);
    }

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

    public CleaningProcessFlow fromDto(CleaningProcessFlowDto dto) {
        return modelMapper.map(dto, CleaningProcessFlow.class);
    }
}
