package com.ruoyi.wms.controller;

import com.cmeim.common.core.utils.BeanUtil;
import com.cmeim.common.core.utils.ExcelExportUtil;
import com.cmeim.common.core.web.controller.GenericController;
import com.cmeim.common.core.web.domain.Respond;
import com.cmeim.common.core.web.page.PageVo;
import com.ruoyi.wms.po.ContainerInfo;
import com.ruoyi.wms.repository.OrderInfoRepository;
import com.ruoyi.wms.repository.StationInfoRepository;
import com.ruoyi.wms.service.ContainerService;
import com.ruoyi.wms.service.OrderService;
import com.ruoyi.wms.vo.ContainerInfoExportVo;
import com.ruoyi.wms.vo.FindOrderByStationVo;
import com.ruoyi.wms.po.OrderInfo;
import com.ruoyi.wms.po.StationInfo;
import com.ruoyi.wms.vo.OrderInfoExportVo;
import com.ruoyi.wms.vo.OrderQueryVo;
import com.google.common.collect.Lists;
import com.ruoyi.ruiYiController.annotation.Log;
import com.ruoyi.ruiYiController.enums.BusinessType;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.*;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;
import java.util.stream.Collectors;

/**
 * @author 李俊辉
 * @version 1.0
 * date: 2023/6/26
 */
@Api(tags = "生产任务单")
@RestController
@RequestMapping(value = "order")
@Slf4j
public class OrderController extends GenericController {
    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderInfoRepository orderInfoRepository;
    @Autowired
    private StationInfoRepository stationInfoRepository;
    @Autowired
    private ContainerService containerService;

    @ApiOperation(value = "列表")
    @GetMapping(value = "list")
    public Respond list(PageVo pv, OrderInfo orderInfo) {
        PageRequest pageRequest = PageRequest.of(pv.getPageNo() - 1, pv.getPageSize(),
                Sort.by(sortOrder(orderInfo.getOrders())));
        Page page = orderInfoRepository.findAll(buildSpecification(orderInfo), pageRequest);
        List<OrderInfo> list = page.getContent();
        pv.setRecordsTotal(page.getTotalElements());
        pv.setData(list);
        return buildSuccess(pv);
    }

    @ApiOperation(value = "查询可出库订单")
    @GetMapping(value = "findStockableOrder")
    public Respond findStockableOrder() {
        //查询符合要求的周转箱
        List<ContainerInfo> containerInfoList = containerService.queryGreaterThanEightHours();
        List<OrderInfo> orderInfoList = new ArrayList<>();
        for (ContainerInfo containerInfo : containerInfoList) {
            OrderInfo orderInfo = orderInfoRepository.findByProductionTask(containerInfo.getProductionTask());
            if (orderInfo == null) {
                continue;
            }
            if (orderInfo.getOrderStatus() == 5) {
                orderInfo.setOrderStatusShow("已录入");
            } else if (orderInfo.getOrderStatus() == 10) {
                orderInfo.setOrderStatusShow("部分入库");
            } else if (orderInfo.getOrderStatus() == 15) {
                orderInfo.setOrderStatusShow("全部入库");
            }
            orderInfoList.add(orderInfo);
        }

        List<OrderInfo> list = orderInfoList.stream()
                .collect(Collectors.collectingAndThen(Collectors.toCollection(
                        () -> new TreeSet<>(Comparator.comparing(OrderInfo::getProductionTask))), ArrayList::new));

        return buildSuccess(list);
    }

    @ApiOperation(value = "查询可送待检缓存区的订单")
    @GetMapping(value = "findSendWaitCheckOrder")
    public Respond findSendWaitCheckOrder() {
        List<OrderInfo> orderInfoList = new ArrayList<>();
        List<OrderInfo> orderInfos = orderInfoRepository.findAll();
        for (OrderInfo orderInfo : orderInfos) {
            //对比出库数量和待校验数量的值
            if (orderInfo.getOutQty() > orderInfo.getWaitCheckQty()) {
                orderInfoList.add(orderInfo);
            }
        }
        return buildSuccess(orderInfoList);
    }

    @ApiOperation(value = "查询可从缓存库位到检验库位的订单")
    @GetMapping(value = "findSendCheckOrder")
    public Respond findSendCheckOrder() {
        List<OrderInfo> orderInfoList = new ArrayList<>();
        List<OrderInfo> orderInfos = orderInfoRepository.findAll();
        for (OrderInfo orderInfo : orderInfos) {
            //对比出库数量和待校验数量的值
            if (orderInfo.getWaitCheckQty() > 0) {
                orderInfoList.add(orderInfo);
            }
        }
        return buildSuccess(orderInfoList);
    }


    @ApiOperation(value = "导出excel")
    @PostMapping("exportExcel")
    public void export(OrderInfo orderInfo, HttpServletResponse response) throws Exception {
        List<OrderInfo> list = orderInfoRepository.findAll(buildSpecification(orderInfo));
        List<OrderInfoExportVo> exportList = new ArrayList<>();
        for(OrderInfo order:list){
            OrderInfoExportVo orderInfoExportVo = BeanUtil.copyProperties(order, OrderInfoExportVo.class);
            exportList.add(orderInfoExportVo);
        }
        // 创建工作簿对象
        SXSSFWorkbook workbook = new SXSSFWorkbook(1000);
        // 创建工作表
        SXSSFSheet sheet = workbook.createSheet("生产任务单列表");

        String[] rowsName = new String[]{"序号","生产任务单","单据状态","销售订单","物料编码","物料名称","物料规格","计划完工日期","计划数量","已入库数","入库中数量","出库数量","出库中数量","待校验数","已校验数","校验中数","成品区已入库数","成品区入库中数量","成品区出库数量","成品区出库中数量","创建人","创建时间","更新人","更新时间"};
        List<Object[]> dataList = new ArrayList<Object[]>();
        Object[] objs = null;
        int i = 1;
        for (OrderInfoExportVo vo : exportList) {
            if(vo.getOrderStatus() == 5){
                vo.setOrderStatusShow("未录入");
            }else if(vo.getOrderStatus() == 10){
                vo.setOrderStatusShow("部分入库");
            }else if(vo.getOrderStatus() == 15){
                vo.setOrderStatusShow("全部入库");
            }

            objs = new Object[rowsName.length];
            objs[0] = i;
            objs[1] = vo.getProductionTask();
            objs[2] = vo.getOrderStatusShow();
            objs[3] = vo.getSaleOrder();
            objs[4] = vo.getMaterialCode();
            objs[5] = vo.getMaterialName();
            objs[6] = vo.getMaterialSpec();
            objs[7] = vo.getPlannedCompletionDate();
            objs[8] = vo.getPlanQty();
            objs[9] = vo.getInQty();
            objs[10] = vo.getOngoingQty();
            objs[11] = vo.getOutQty();
            objs[12] = vo.getOnoutingCheckQty();
            objs[13] = vo.getWaitCheckQty();
            objs[14] = vo.getFinishCheckQty();
            objs[15] = vo.getCheckQty();
            objs[16] = vo.getProductInQty();
            objs[17] = vo.getProductOngoingQty();
            objs[18] = vo.getProductOutQty();
            objs[19] = vo.getProductOnoutingQty();
            objs[20] = vo.getCreatedBy();
            objs[21] = vo.getCreatedDt();
            objs[22] = vo.getUpdatedBy();
            objs[23] = vo.getUpdatedDt();
            dataList.add(objs);
            i += 1;
        }
        ExcelExportUtil.getExportWorkbook(workbook, sheet, rowsName, dataList);
        ExcelExportUtil.sendHttpResponse(response, "Order", workbook);
    }

    @ApiOperation(value = "通过站位查询工单信息")
    @GetMapping(value = "findOrderByStation")
    public Respond findOrderByStation(String stationCode) {
        StationInfo stationInfo = stationInfoRepository.findByStationCode(stationCode);
        if (stationInfo == null) {
            return buildFailure("无该站位信息：" + stationCode);
        }
        OrderInfo orderInfo = orderInfoRepository.findByProductionTask(stationInfo.getProductionTask());
        if (orderInfo == null) {
            return buildSuccess("该站位无工单信息");
        }
        FindOrderByStationVo vo = BeanUtil.copyProperties(orderInfo, FindOrderByStationVo.class);
        vo.setStationStatus(stationInfo.getStationStatus());
        vo.setStationCode(stationInfo.getStationCode());
        vo.setStationName(stationInfo.getStationName());
        vo.setStationType(stationInfo.getStationType());
        return buildSuccess(vo);
    }

    @ApiOperation(value = "新增")
    @Log(title = "生产任务单", businessType = BusinessType.INSERT)
    @PostMapping(value = "add")
    public Respond add(@RequestBody OrderInfo orderInfo) {
        OrderInfo info = orderInfoRepository.findByProductionTask(orderInfo.getProductionTask());
        if (info == null) {
            orderInfo.setInQty(0);
            orderInfo.setOngoingQty(0);
            orderInfo.setOutQty(0);
            orderInfo.setOnoutingCheckQty(0);
            orderInfo.setWaitCheckQty(0);
            orderInfo.setFinishCheckQty(0);
            orderInfo.setCheckQty(0);
            orderInfo.setProductInQty(0);
            orderInfo.setProductOngoingQty(0);
            orderInfo.setProductOutQty(0);
            orderInfo.setProductOnoutingQty(0);
            orderInfoRepository.save(orderInfo);
        }
        //绑定工位和任务单
        StationInfo stationInfo = stationInfoRepository.findByStationCode(orderInfo.getStationCode());
        if (stationInfo != null) {
            stationInfo.setStationStatus(orderInfo.getStationStatus());
            stationInfo.setProductionTask(orderInfo.getProductionTask());
            stationInfo.setUpdatedDt(orderInfo.getCreatedDt());
            stationInfo.setUpdatedBy(orderInfo.getCreatedBy());
            stationInfoRepository.save(stationInfo);
        }
        return buildSuccess();
    }

    @ApiOperation(value = "通过甲方接口获取单据列表")
    @PostMapping(value = "findByOrderQueryVo")
    public Respond findByOrderQueryVo(@RequestBody OrderQueryVo orderQueryVo) {
        List<OrderInfo> orderInfoList = orderService.findByOrderQueryVo(orderQueryVo);
        return buildSuccess(orderInfoList);
    }

    private Specification buildSpecification(OrderInfo orderInfo) {
        Specification<OrderInfo> specification = new Specification<OrderInfo>() {
            @Override
            public Predicate toPredicate(Root<OrderInfo> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
                List<Predicate> predicates = Lists.newArrayList();
                if (orderInfo.getMaterialCode() != null) {
                    predicates.add(cb.like(root.get("materialCode").as(String.class), "%" + orderInfo.getMaterialCode() + "%"));
                }
                if (orderInfo.getMaterialName() != null) {
                    predicates.add(cb.like(root.get("materialName").as(String.class), "%" + orderInfo.getMaterialName() + "%"));
                }
                if (orderInfo.getMaterialSpec() != null) {
                    predicates.add(cb.like(root.get("materialSpec").as(String.class), "%" + orderInfo.getMaterialSpec() + "%"));
                }
                if (orderInfo.getOrderStatus() != null) {
                    predicates.add(cb.equal(root.get("orderStatus").as(Integer.class), orderInfo.getOrderStatus()));
                }
                if (orderInfo.getProductionTask() != null) {
                    predicates.add(cb.like(root.get("productionTask").as(String.class), "%" + orderInfo.getProductionTask() + "%"));
                }
                if (orderInfo.getSaleOrder() != null) {
                    predicates.add(cb.like(root.get("saleOrder").as(String.class), "%" + orderInfo.getSaleOrder() + "%"));
                }
                if (StringUtils.isNotBlank(orderInfo.getPlannedCompletionDateStart())) {
                    predicates.add(cb.greaterThanOrEqualTo(root.get("plannedCompletionDate").as(String.class), orderInfo.getPlannedCompletionDateStart()));
                }
                if (StringUtils.isNotBlank(orderInfo.getPlannedCompletionDateEnd())) {
                    predicates.add(cb.lessThanOrEqualTo(root.get("plannedCompletionDate").as(String.class), orderInfo.getPlannedCompletionDateEnd()));
                }
                if (orderInfo.getOrderStatusArr() != null) {
                    CriteriaBuilder.In<Integer> in = cb.in(root.get("orderStatus").as(Integer.class));
                    for (Integer dictStatus : orderInfo.getOrderStatusArr()) {
                        in.value(dictStatus);
                    }
                    predicates.add(in);
                }
                return cb.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };

        return specification;
    }
}
