package com.ruoyi.wms.controller;


import com.cmeim.common.core.utils.BeanUtil;
import com.cmeim.common.core.utils.ExcelExportUtil;
import com.cmeim.common.core.utils.StringUtils;
import com.cmeim.common.core.web.controller.GenericController;
import com.cmeim.common.core.web.domain.Respond;
import com.cmeim.common.core.web.domain.RespondEnum;
import com.cmeim.common.core.web.page.PageVo;
import com.ruoyi.ruiYiController.exception.ServiceException;
import com.ruoyi.wms.po.ContainerInfo;
import com.ruoyi.wms.po.OrderInfo;
import com.ruoyi.wms.po.ShelfInfo;
import com.ruoyi.wms.repository.OrderInfoRepository;
import com.ruoyi.wms.repository.StationInfoRepository;
import com.ruoyi.wms.po.StationInfo;
import com.google.common.collect.Lists;
import com.ruoyi.ruiYiController.annotation.Log;
import com.ruoyi.ruiYiController.enums.BusinessType;
import com.ruoyi.wms.vo.ShelfInfoExportVo;
import com.ruoyi.wms.vo.StationInfoExportVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
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/28
 */
@Api(tags = "工位")
@RestController
@RequestMapping(value = "station")
@Slf4j
public class StationController extends GenericController {
    @Autowired
    private StationInfoRepository stationInfoRepository;
    @Autowired
    private OrderInfoRepository orderInfoRepository;

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

    @ApiOperation(value = "导出excel")
    @PostMapping("exportExcel")
    public void export(StationInfo stationInfo, HttpServletResponse response) throws Exception {
        List<StationInfo> list = stationInfoRepository.findAll(buildSpecification(stationInfo));
        List<StationInfoExportVo> exportList = new ArrayList<>();
        for(StationInfo station:list){
            StationInfoExportVo stationInfoExportVo = BeanUtil.copyProperties(station, StationInfoExportVo.class);
            exportList.add(stationInfoExportVo);
        }
        // 创建工作簿对象
        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 (StationInfoExportVo vo : exportList) {
            if(vo.getStationStatus() == 5){
                vo.setStationStatusShow("空闲");
            }else if(vo.getStationStatus() == 10){
                vo.setStationStatusShow("作业中");
            }else if(vo.getStationStatus() == 15){
                vo.setStationStatusShow("停止作业");
            }else if(vo.getStationStatus() == 20){
                vo.setStationStatusShow("作业完成");
            }

            if(vo.getStationType() == 5){
                vo.setStationTypeShow("入库工位");
            }else if(vo.getStationType() == 10){
                vo.setStationTypeShow("出库工位");
            }else if(vo.getStationType() == 15){
                vo.setStationTypeShow("校验工位");
            }else if(vo.getStationType() == 20){
                vo.setStationTypeShow("抽检工位");
            }else if(vo.getStationType() == 25){
                vo.setStationTypeShow("发货库位");
            }

            objs = new Object[rowsName.length];
            objs[0] = i;
            objs[1] = vo.getStationCode();
            objs[2] = vo.getStoreCode();
            objs[3] = vo.getStationName();
            objs[4] = vo.getStationTypeShow();
            objs[5] = vo.getStationStatusShow();
            objs[6] = vo.getStationSubnumber();
            objs[7] = vo.getProductionTask();
            objs[8] = vo.getCreatedBy();
            objs[9] = vo.getCreatedDt();
            objs[10] = vo.getUpdatedBy();
            objs[11] = vo.getUpdatedDt();
            dataList.add(objs);
            i += 1;
        }
        ExcelExportUtil.getExportWorkbook(workbook, sheet, rowsName, dataList);
        ExcelExportUtil.sendHttpResponse(response, "Station", workbook);
    }

    @ApiOperation(value = "根据工位编码查询生产任务单")
    @GetMapping(value = "findOrderByStationCode")
    public Respond findOrderByStationCode(String stationCode) {
        StationInfo stationInfo = stationInfoRepository.findByStationCode(stationCode);
        if (stationInfo == null || StringUtils.isBlank(stationInfo.getProductionTask())) {
            return buildFailure("未找到该库位编码或该库位编码没有绑定生产任务单！");
        }
        OrderInfo orderInfo = orderInfoRepository.findByProductionTask(stationInfo.getProductionTask());
        if (orderInfo == null) {
            return buildFailure("未找到生产任务单：" + stationInfo.getProductionTask());
        }
        orderInfo.setStationStatus(stationInfo.getStationStatus());
        if (stationInfo.getStationStatus() == 5) {
            orderInfo.setStationStatusShow("空闲");
        } else if (stationInfo.getStationStatus() == 10) {
            orderInfo.setStationStatusShow("作业中");
        } else if (stationInfo.getStationStatus() == 15) {
            orderInfo.setStationStatusShow("停止作业");
        } else if (stationInfo.getStationStatus() == 20) {
            orderInfo.setStationStatusShow("作业完成");
        }
        if (orderInfo.getOrderStatus() == 5) {
            orderInfo.setOrderStatusShow("已录入");
        } else if (orderInfo.getOrderStatus() == 10) {
            orderInfo.setOrderStatusShow("部分入库");
        } else if (orderInfo.getOrderStatus() == 15) {
            orderInfo.setOrderStatusShow("全部入库");
        }
        return buildSuccess(orderInfo);
    }

    @ApiOperation(value = "修改工位状态")
    @Log(title = "工位", businessType = BusinessType.UPDATE)
    @PostMapping(value = "updateStationStatus")
    public Respond updateStationStatus(@RequestBody StationInfo stationInfo) {
        StationInfo station = stationInfoRepository.findByStationCode(stationInfo.getStationCode());
        if (station == null) {
            throw new ServiceException("未找到该工位号对应的工位");
        }
        station.setStationStatus(stationInfo.getStationStatus());
        station.setUpdatedBy(stationInfo.getUpdatedBy());
        station.setUpdatedDt(stationInfo.getUpdatedDt());
        StationInfo save = stationInfoRepository.save(station);
        return buildSuccess(save);
    }

    @ApiOperation(value = "根据站位号修改单据")
    @Log(title = "工位", businessType = BusinessType.UPDATE)
    @PostMapping(value = "updateProductionTask")
    public Respond updateProductionTask(@RequestBody StationInfo stationInfo) {
        StationInfo station = stationInfoRepository.findByStationCode(stationInfo.getStationCode());
        if (station == null) {
            throw new ServiceException("未找到该工位号对应的工位");
        }
        station.setProductionTask(stationInfo.getProductionTask());
        station.setUpdatedBy(stationInfo.getUpdatedBy());
        station.setUpdatedDt(stationInfo.getUpdatedDt());
        StationInfo save = stationInfoRepository.save(station);
        return buildSuccess(save);
    }

    private Specification buildSpecification(StationInfo stationInfo) {
        Specification<StationInfo> specification = new Specification<StationInfo>() {
            @Override
            public Predicate toPredicate(Root<StationInfo> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
                List<Predicate> predicates = Lists.newArrayList();
                if (stationInfo.getStationCode() != null) {
                    predicates.add(cb.like(root.get("stationCode").as(String.class), "%" + stationInfo.getStationCode() + "%"));
                }
                if (stationInfo.getStationName() != null) {
                    predicates.add(cb.like(root.get("stationName").as(String.class), "%" + stationInfo.getStationName() + "%"));
                }
                if (stationInfo.getStationSubnumber() != null) {
                    predicates.add(cb.equal(root.get("stationSubnumber").as(Integer.class), stationInfo.getStationSubnumber()));
                }
                if (stationInfo.getProductionTask() != null) {
                    predicates.add(cb.equal(root.get("productionTask").as(Integer.class), stationInfo.getProductionTask()));
                }
                if (stationInfo.getStationStatus() != null) {
                    predicates.add(cb.equal(root.get("stationStatus").as(Integer.class), stationInfo.getStationStatus()));
                }
                if (stationInfo.getStationType() != null) {
                    predicates.add(cb.equal(root.get("stationType").as(Integer.class), stationInfo.getStationType()));
                }
                if (stationInfo.getStationStatusArr() != null) {
                    CriteriaBuilder.In<Integer> in = cb.in(root.get("stationStatus").as(Integer.class));
                    for (Integer status : stationInfo.getStationStatusArr()) {
                        in.value(status);
                    }
                    predicates.add(in);
                }
                if (stationInfo.getStationTypeArr() != null) {
                    CriteriaBuilder.In<Integer> in = cb.in(root.get("stationType").as(Integer.class));
                    for (Integer status : stationInfo.getStationTypeArr()) {
                        in.value(status);
                    }
                    predicates.add(in);
                }
                return cb.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
        return specification;
    }
}
