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


import cn.hutool.core.collection.CollectionUtil;
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.annotation.TokenNotValidation;
import com.sw.mes.core.context.BaseContextHandler;
import com.sw.mes.core.enums.ItemCleanEnums;
import com.sw.mes.core.response.ResponsePage;
import com.sw.mes.core.response.Result;
import com.sw.mes.core.response.ResultGenerator;
import com.sw.mes.core.utils.*;
import com.sw.mes.itemclean.clean.domain.MaterialStoreSignBox;
import com.sw.mes.itemclean.clean.dto.*;
import com.sw.mes.itemclean.clean.domain.MaterialUnpacking;
import com.sw.mes.itemclean.clean.mapper.MaterialUnpackingMapper;
import com.sw.mes.itemclean.clean.service.MaterialUnpackingService;
import com.sw.mes.itemclean.clean.vo.MaterialUnpackingVo;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
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.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;


@RestController
@RequestMapping("/clean/materialUnpacking")
@Slf4j
@Api(tags = "分选拆箱")
public class MaterialUnpackingController {
    @Autowired
    ModelMapper modelMapper;

    @Autowired
    private MaterialUnpackingService materialUnpackingService;

    @Autowired
    private MaterialUnpackingMapper materialUnpackingMapper;


    @Jinko(author = "yyl", value = "分选分页查询列表")
    @ApiOperation(value = "分选分页查询列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "rows", value = "行数", dataType = "integer", paramType = "query"),
            @ApiImplicitParam(name = "page", value = "页码", dataType = "integer", paramType = "query"),
    })
    @GetMapping("/listByPage")
    public Result<ResponsePage<MaterialUnpackingDto>> listByPage(ServletRequest request, @ApiIgnore RequestPage requestPage) {
        //分页查询
        QueryWrapper<MaterialUnpacking> queryWrapper =  DynmaicQueryWrapper.searchFilter(request, MaterialUnpacking.class);
        Page<MaterialUnpacking> listPage = materialUnpackingService.page(new Page<>(requestPage.getPage(), requestPage.getRows()), queryWrapper);
        List<MaterialUnpackingDto> dtos = listPage.getRecords().stream()
                .map(entity -> toLazyDto(entity))
                .collect(Collectors.toList());
        ResponsePage responsePage = new ResponsePage(dtos, listPage.getTotal());
        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"),
    })
    @GetMapping("/listByJoinPage")
    public Result<ResponsePage<MaterialUnpackingJoinPageDto>> listByJoinPage(ServletRequest request, @ApiIgnore RequestPage requestPage) {
        //分页查询
        ResponsePage<MaterialUnpackingJoinPageDto> responsePage = new ResponsePage<>();
        MaterialUnpackingParamQuery materialUnpackingParamQuery = new MaterialUnpackingParamQuery();
        materialUnpackingParamQuery.setMaterialName(request.getParameter("search_LIKE_materialName"))
                .setMaterialCode(request.getParameter("search_EQ_materialCode"))
                .setProductBatchNo(request.getParameter("search_EQ_productBatchNo"))
                .setCreateStartTime(request.getParameter("search_GTE_createTime"))
                .setCreateEndTime(request.getParameter("search_LTE_createTime"))
                .setFxProductBatchNo(request.getParameter("search_LIKE_muFxProductBatchNo"));
        IPage<MaterialUnpackingJoinPageDto> iPage = new Page<>(requestPage.getPage(), requestPage.getRows());
        IPage<MaterialUnpackingJoinPageDto> materialUnpackingJoinPageDtoIPage = materialUnpackingService.queryList(iPage, materialUnpackingParamQuery);
        responsePage.setRows(materialUnpackingJoinPageDtoIPage.getRecords());
        responsePage.setTotal(materialUnpackingJoinPageDtoIPage.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_EQ_materialCode", value = "物料编码", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_EQ_fxProductBatchNo", value = "分选生产批次", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_GTE_createTime", value = "创建开始时间", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "search_LTE_createTime", value = "创建结束时间", dataType = "string", paramType = "query"),
    })
    @GetMapping("/export")
    public void export(ServletRequest request, HttpServletResponse response) {
        try {
            MaterialUnpackingParamQuery materialUnpackingParamQuery = new MaterialUnpackingParamQuery();
            materialUnpackingParamQuery.setMaterialName(request.getParameter("search_LIKE_materialName"))
                    .setMaterialCode(request.getParameter("search_EQ_materialCode"))
                    .setProductBatchNo(request.getParameter("search_EQ_productBatchNo"))
                    .setFxProductBatchNo(request.getParameter("search_EQ_fxProductBatchNo"))
                    .setCreateStartTime(request.getParameter("search_GTE_createTime"))
                    .setCreateEndTime(request.getParameter("search_LTE_createTime"));
            List<MaterialUnpackingJoinPageDto> list = materialUnpackingService.queryListByParam(materialUnpackingParamQuery);

            EasyExcelUtils.write(response, MaterialUnpackingJoinPageDto.class, "分选记录", "分选记录", list);
        } catch (Exception e) {
            throw new RuntimeException("导出分选记录失败，错误信息：" + e.getMessage());
        }
    }


    @ApiOperation(value = "获取所有列表")
    @GetMapping("/listAll")
    public Result<List<MaterialUnpackingDto>> listAll(ServletRequest request) {
        QueryWrapper<MaterialUnpacking> queryWrapper =  DynmaicQueryWrapper.searchFilter(request, MaterialUnpacking.class);
        List<MaterialUnpacking> materialUnpackings = materialUnpackingService.list(queryWrapper);
        List<MaterialUnpackingDto> materialUnpackingDtos = materialUnpackings.stream()
                .map(materialUnpacking -> toLazyDto(materialUnpacking))
                .collect(Collectors.toList());
        return ResultGenerator.success(materialUnpackingDtos);
    }

    @ApiOperation(value = "详细信息")
    @GetMapping("/{id}")
    public Result<MaterialUnpackingDto> get(@PathVariable @ApiParam(value="设备类型id") Integer id) {
        MaterialUnpacking materialUnpacking = materialUnpackingService.getById(id);
        if (null == materialUnpacking)
            return ResultGenerator.fail("该对象不存在");
        return ResultGenerator.success(toEagerDto(materialUnpacking));
    }

    @ApiOperation(value = "创建")
    @PostMapping("/create")
    public Result create(@RequestBody @Valid @ApiParam(value = "Dto对象") MaterialUnpackingDto materialUnpackingDto, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        MaterialUnpacking materialUnpacking = fromDto(materialUnpackingDto);
        materialUnpackingService.saveOrUpdate(materialUnpacking);
        return ResultGenerator.success();
    }

    @ApiOperation(value = "更新")
    @PostMapping("/update")
    public Result update(@RequestBody @Valid @ApiParam(value = "Dto对象") MaterialUnpackingDto dto, BindingResult bindingResult) {
        if (bindingResult.hasErrors())
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        if (dto.getId() == null)
            return ResultGenerator.fail("id不能为空");
        MaterialUnpacking entity = materialUnpackingService.getById(dto.getId());
        if (entity == null)
            return ResultGenerator.fail("原信息不存在");
        try {
            MaterialUnpacking entityfromFto = fromDto(dto);
            BeanUtils.copyProperties(entityfromFto, entity, BeanUtil.getIgnoreProperties(entityfromFto, null, null));
            materialUnpackingService.saveOrUpdate(entity);
            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) {
            materialUnpackingMapper.deleteById(id);
        }
        return ResultGenerator.success();
    }

    /**
     * 删除分选信息并回滚领料表中的重量状态
     *
     * @param id
     * @return
     */
    @Jinko(author = "yyl", value = "硅料加工记录-分选记录-删除")
    @ApiOperation(value = "硅料加工记录-分选记录-删除")
    @PostMapping("/deleteById")
    public Result deleteById(@ApiParam(value = "id", type = "query") @RequestParam Integer id) {
        return materialUnpackingService.revertWeightById(id);
    }

    @Jinko(author = "yyl", value = "根据余料批次号查询分选过的信息(包含已删除的)-定位消耗订单号")
    @ApiOperation(value = "根据余料批次号查询分选过的信息(包含已删除的)-定位消耗订单号")
    @PostMapping("/getAufnrByProductBatchNo")
    public Result<String> getAufnrByProductBatchNo(@ApiParam(value = "productBatchNo", type = "query") @RequestParam String productBatchNo) {
        MaterialUnpacking unpacking = materialUnpackingService.getAufnrByProductBatchNo(productBatchNo);
        if (null != unpacking) {
            return ResultGenerator.success(unpacking.getAufnr());
        } else {
            return ResultGenerator.success();
        }
    }


    @ApiOperation(value = "暂存打签")
    @PostMapping("/createStorageSign")
    public Result createStorageSign(@RequestBody @Valid @ApiParam(value = "分选拆箱vo对象") MaterialUnpackingVo materialUnpackingVo, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        return ResultGenerator.success(materialUnpackingService.createStorageSign(materialUnpackingVo));
    }

    @ApiOperation(value = "获取暂存打签的详细信息")
    @GetMapping("/selectStorageSign")
    public Result<MaterialUnpackingVo> selectStorageSign(@ApiParam(value = "成箱箱号") String materialBoxNo) {
        return ResultGenerator.success( materialUnpackingService.selectStorageSign(materialBoxNo));
    }

    @Jinko(author = "yyl", value = "新版分选成箱打签")
    @ApiOperation(value = "新版分选成箱打签")
    @PostMapping("/createFinishStorageSign")
    public Result<FxToBoxInfoPrintDto> createFinishStorageSign(@RequestBody @Valid @ApiParam(value = "分选拆箱vo对象") MaterialUnpackingVo materialUnpackingVo, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        FxToBoxInfoPrintDto finishStorageSign = null;
        try {
            finishStorageSign = materialUnpackingService.createFinishStorageSign(materialUnpackingVo);
        } catch (Exception e) {
            log.error("createFinishStorageSign", e);
            return ResultGenerator.fail(e.getMessage());
        }
        return ResultGenerator.success(finishStorageSign);
    }

    @Jinko(author = "yyl", value = "通过pp批次号获取分选箱内物料信息")
    @ApiOperation(value = "通过pp批次号获取分选箱内物料信息")
    @GetMapping("/getInfoByPpProductBatchNo")
    public Result<MaterialUnpacking> getInfoByPpProductBatchNo(String productBatchNo) {
        MaterialUnpacking unpacking = materialUnpackingService.getCanUseByPpProductBatchNo(productBatchNo);
        if (unpacking == null) {
            return ResultGenerator.fail("不存在可使用的批次号物料");
        } else {
            return ResultGenerator.success(unpacking);
        }
    }

    @Jinko(author = "yyl", value = "通过分选pp批次号获取分选数据")
    @ApiOperation(value = "通过分选pp批次号获取分选数据")
    @GetMapping("/getInfoByFxProductBatchNo")
    public Result<MaterialUnpacking> getInfoByFxProductBatchNo(String productBatchNo) {
        MaterialUnpacking unpacking = materialUnpackingService.getFxProductBatchNo(productBatchNo);
        if (unpacking == null) {
            return ResultGenerator.fail("不存在分选物料信息");
        } else {
            return ResultGenerator.success(unpacking);
        }
    }

    @Jinko(author = "yyl", value = "通过分选pp批次号获取未使用的分选数据")
    @ApiOperation(value = "通过分选pp批次号获取未使用的分选数据")
    @GetMapping("/getUnUsedInfoByFxProductBatchNo")
    public Result<MaterialUnpacking> getUnUsedInfoByFxProductBatchNo(String productBatchNo) {
        MaterialUnpacking unpacking = materialUnpackingService.getByPpProductBatchNo(productBatchNo);
        if (unpacking == null) {
            return ResultGenerator.fail("不存在分选批次号为【" + productBatchNo + "】的分选未使用数据");
        } else {
            return ResultGenerator.success(unpacking);
        }
    }

    @Jinko(author = "yyl", value = "已分选未使用的数据合批")
    @ApiOperation(value = "已分选未使用的数据合批")
    @PostMapping("/blending")
    public Result blending(@RequestBody @Valid @ApiParam(value = "Dto对象") List<MaterialUnpacking> dtos, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultGenerator.fail(bindingResult.getFieldError().getDefaultMessage());
        }
        materialUnpackingService.blending(dtos);
        return ResultGenerator.success();
    }

    public MaterialUnpackingDto toLazyDto(MaterialUnpacking entity) {
        return modelMapper.map(entity, MaterialUnpackingDto.class);
    }

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

    public MaterialUnpacking fromDto(MaterialUnpackingDto dto) {
        return modelMapper.map(dto, MaterialUnpacking.class);
    }
}
