package com.huaheng.pc.shipment.shipmentDetail.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.huaheng.common.exception.BusinessException;
import com.huaheng.common.utils.Wrappers;
import com.huaheng.common.constant.QuantityConstant;
import com.huaheng.common.exception.service.ServiceException;
import com.huaheng.common.support.Convert;
import com.huaheng.common.utils.DataUtils;
import com.huaheng.common.utils.StringUtils;
import com.huaheng.common.utils.security.ShiroUtils;
import com.huaheng.framework.web.domain.AjaxResult;
import com.huaheng.pc.config.material.domain.Material;
import com.huaheng.pc.config.material.service.MaterialService;
import com.huaheng.pc.config.shipmentPreference.domain.ShipmentPreference;
import com.huaheng.pc.config.shipmentPreference.service.ShipmentPreferenceService;
import com.huaheng.pc.config.statusFlow.domain.StatusFlowDetail;
import com.huaheng.pc.config.statusFlow.domain.StatusFlowHeader;
import com.huaheng.pc.config.statusFlow.service.StatusFlowDetailService;
import com.huaheng.pc.config.statusFlow.service.StatusFlowHeaderService;
import com.huaheng.pc.config.warehouse.domain.Warehouse;
import com.huaheng.pc.config.warehouse.service.WarehouseService;
import com.huaheng.pc.config.waveMaster.domain.WaveMaster;
import com.huaheng.pc.config.waveMaster.service.WaveMasterService;
import com.huaheng.pc.receipt.receiptDetail.domain.ReceiptDetail;
import com.huaheng.pc.receipt.receiptHeader.domain.ReceiptHeader;
import com.huaheng.pc.shipment.lockingWorkOrder.domain.LockingWorkOrder;
import com.huaheng.pc.shipment.shipmentHeader.domain.ShipmentHeader;
import com.huaheng.pc.shipment.shipmentHeader.service.ShipmentHeaderService;
import com.huaheng.pc.shipment.wave.domain.Wave;
import com.huaheng.pc.shipment.wave.service.WaveService;
import com.huaheng.pc.task.taskDetail.domain.TaskDetail;
import org.aspectj.weaver.ast.Var;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huaheng.pc.shipment.shipmentDetail.mapper.ShipmentDetailMapper;
import com.huaheng.pc.shipment.shipmentDetail.domain.ShipmentDetail;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ShipmentDetailServiceImpl extends ServiceImpl<ShipmentDetailMapper, ShipmentDetail> implements ShipmentDetailService{

    @Autowired
    private ShipmentHeaderService shipmentHeaderService;

    @Autowired
    private MaterialService materialService;
    @Resource
    private ShipmentDetailMapper shipmentDetailMapper;
    @Autowired
    private WaveMasterService waveMasterService;
    @Autowired
    private WaveService waveService;
    @Autowired
    private ShipmentPreferenceService shipmentPreferenceService;
    @Autowired
    private StatusFlowHeaderService statusFlowHeaderService;
    @Autowired
    private StatusFlowDetailService statusFlowDetailService;
    @Autowired
    private WarehouseService warehouseService;

    /**
     * 新增出库明细
     *
     * @param shipmentDetail
     * @return
     */
    @Override
    public AjaxResult insertDetail(ShipmentDetail shipmentDetail) {
        //查看主单是否存在
        LambdaQueryWrapper<ShipmentHeader> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(ShipmentHeader::getId,shipmentDetail.getShipmentId())
                .eq(ShipmentHeader::getWarehouseCode,ShiroUtils.getWarehouseCode());
        ShipmentHeader shipmentHeader = shipmentHeaderService.getOne(lambdaQueryWrapper);
        if (shipmentHeader == null) {
            return AjaxResult.error("找不到主单据");
        }
        if (shipmentHeader.getFirstStatus() > QuantityConstant.SHIPMENT_HEADER_POOL) {
            //表示已经加入了波次
            return AjaxResult.error("主单据状态不允许新增明细");
        }
        //查找物料
        LambdaQueryWrapper<Material> lam = Wrappers.lambdaQuery();
        lam.eq(Material::getCode,shipmentDetail.getMaterialCode())
                .eq(Material::getWarehouseCode,ShiroUtils.getWarehouseCode());
        Material material = materialService.getOne(lam);
        if (material == null) {
            return AjaxResult.error("物料未找到");
        }
        if (StringUtils.isNotEmpty(material.getCompanyCode()) &&
                ShiroUtils.getCompanyCodeList().contains(material.getCompanyCode()) == false)
        {
            return AjaxResult.error("物料不属于当前货主!");
        }
        shipmentDetail.setId(null);
        shipmentDetail.setWarehouseCode(ShiroUtils.getWarehouseCode());
        shipmentDetail.setMaterialCode(material.getCode());
        shipmentDetail.setMaterialName(material.getName());
        shipmentDetail.setReferCode(shipmentHeader.getReferCode());
        shipmentDetail.setReferId(shipmentHeader.getReferId());
        shipmentDetail.setMaterialSpec(material.getSpec());
        shipmentDetail.setMaterialUnit(material.getUnit());
        shipmentDetail.setInventorySts(QuantityConstant.GOOD);
        shipmentDetail.setCreated(null);
        shipmentDetail.setCreatedBy(ShiroUtils.getLoginName());
        shipmentDetail.setLastUpdated(null);
        shipmentDetail.setLastUpdatedBy(ShiroUtils.getLoginName());
        if (this.save(shipmentDetail)==true){
            //更新单据总行数与总数量
//            shipmentHeader.setTotalLines(shipmentHeader.getTotalLines() + 1);
//            shipmentHeader.setTotalQty(shipmentHeader.getTotalQty().add(shipmentDetail.getShipQty()));
//            shipmentHeaderService.saveOrUpdate(shipmentHeader);
            updateShipmentHeader(shipmentHeader);
            return AjaxResult.success("新增单据明细成功");
        }
        else {
            return AjaxResult.error("新增单据明细失败");
        }
    }


    /**
     * 删除出库单据明细
     *
     * @param id
     * @return
     */
    @Override
    @Transactional
    public AjaxResult deleteDetail(String id) {
        if (StringUtils.isEmpty(id)) {
            return AjaxResult.error("id不能为空");
        }
        String[] ids = id.split(",");
        List<Map<String,Integer>> list = shipmentDetailMapper.SelectFirstStatus(id);
        if (list.size() < 1) {
            return AjaxResult.error("找不到主单据!");
        }
        if (list.size() > 1) {
            return AjaxResult.error("有多个主单据,不能一起删除!");
        }
        if (list.get(0).get("firstStatus") > QuantityConstant.SHIPMENT_HEADER_POOL) {
            return AjaxResult.error("单据状进入订单池,不允许删除明细");
        }
        Integer result = shipmentDetailMapper.batchDelete(ids);
        if (result > 0) {
            Integer headerId=list.get(0).get("id");
            Map<String,String> map= shipmentDetailMapper.StatisticalByReceiptId(headerId);
            if(DataUtils.getInteger(map.get("totalLines")) <= 0)    {
                shipmentHeaderService.removeById(headerId);
            }
            else    {
                //更新表头的总行数和总数量统计
                ShipmentHeader shipmentHeader = new ShipmentHeader();
                shipmentHeader.setId(headerId);
//                shipmentHeader.setTotalLines(DataUtils.getInteger(map.get("totalLines")));
//                shipmentHeader.setTotalQty(DataUtils.getBigDecimal(map.get("totalQty")));
//                shipmentHeaderService.saveOrUpdate(shipmentHeader);
                updateShipmentHeader(shipmentHeader);
            }
            return AjaxResult.success("删除单据明细成功");
        }
        else {
            return AjaxResult.error("删除单据明细失败");
        }
    }

    /**
    ** 查找没有出库完的详情
     */
    @Override
    public Integer countUnCompleted(Integer shipmentId) {
        LambdaQueryWrapper<ShipmentDetail> shipmentDetailLambdaQueryWrapper = Wrappers.lambdaQuery();
        shipmentDetailLambdaQueryWrapper.eq(ShipmentDetail::getShipmentId, shipmentId);
        List<ShipmentDetail> shipmentDetailList = list(shipmentDetailLambdaQueryWrapper);
        int n = 0;
        for(ShipmentDetail shipmentDetail : shipmentDetailList) {
            BigDecimal qty = shipmentDetail.getQty();
            BigDecimal taskQty = shipmentDetail.getTaskQty();
            if(qty.compareTo(taskQty) > 0) {
                n++;
            }
        }
        return n;
    }


    /**
     * 查看选中的单据状态是否符合出库流程
     * 选中的单据加入波次
     * 根据选中的主单ID和波次主表的code,判断主单之和是否符合波次的限制条件,
     * 看此code的波次是否建成未开始执行,如果是则只需修改波次属性,否则创建新的波次,
     * 修改加入波次的子单,修改子单和主单的状态,并修改子单的waveId
     */
    @Override
    @Transactional
    public void saveWave(String ids, String code) {
        Integer status = QuantityConstant.SHIPMENT_HEADER_POOL;
        List<ShipmentHeader> shipmentHeaderList =shipmentPreferenceService.checkShipmentProcess(ids,status,code);

        //找到波次主表,看系统是否有此波次
        LambdaQueryWrapper<WaveMaster> lam=Wrappers.lambdaQuery();
        lam.eq(WaveMaster::getCode,code)
                .eq(WaveMaster::getWarehouseCode,ShiroUtils.getWarehouseCode());
        WaveMaster waveMaster=waveMasterService.getOne(lam);
        if(waveMaster == null){
            throw new ServiceException("系统没有此波次");
        }

        if(Convert.toIntArray(ids).length >waveMaster.getMaxShipments()){
            throw new ServiceException("加入波次的单据数量超过波次的单据限制");
        }

        List<ShipmentDetail> shipmentDetailList=new ArrayList<>();
        BigDecimal qty=new BigDecimal(0);
        //检查出库子表是否有处于波次的
        for (Integer id : Convert.toIntArray(ids))
        {
            LambdaQueryWrapper<ShipmentDetail> lamDetail=Wrappers.lambdaQuery();
            lamDetail.eq(ShipmentDetail::getWarehouseCode,ShiroUtils.getWarehouseCode())
                    .eq(ShipmentDetail::getShipmentId,id);
            List<ShipmentDetail> shipmentDetails=this.list(lamDetail);
            if(shipmentDetails == null || shipmentDetails.size() == 0){
                throw new ServiceException("系统没有主单id为"+id+"的子单");
            }

            //查看是否有单据处于波次中
            for(ShipmentDetail shipmentDetail : shipmentDetails) {
                if (shipmentDetail.getWaveId() != 0) {
                    throw new ServiceException("主单id为" + id + "子单id为" + shipmentDetail.getId() + "的子单已加入波次,不可再加入波次");
                }
                if(shipmentDetail.getQty().compareTo(shipmentDetail.getTaskQty())!=0) {
                    shipmentDetailList.add(shipmentDetail);
                    qty = qty.add(shipmentDetail.getQty().subtract(shipmentDetail.getTaskQty()));
                }
            }
        }

        if(shipmentDetailList.size()>waveMaster.getMaxLines()){
            throw new ServiceException("加入波次的总行数超过波次的行数限制");
        }

        Boolean flag=false;

        //查看波次是否建成未执行
        LambdaQueryWrapper<Wave> waveLam = Wrappers.lambdaQuery();
        waveLam.eq(Wave::getStatus,QuantityConstant.WAVE_STATUS_BUILD)
                .eq(Wave::getWaveMode,code)
                .eq(Wave::getWarehouseCode,ShiroUtils.getWarehouseCode());
        Wave wave = waveService.getOne(waveLam);
        if(wave != null && (wave.getTotalShipments()+Convert.toIntArray(ids).length)<= waveMaster.getMaxShipments()
        && (wave.getTotalLines()+shipmentDetailList.size()<= waveMaster.getMaxLines())){
            //修改波次
            wave.setTotalShipments(Convert.toIntArray(ids).length + wave.getTotalShipments());
            wave.setTotalLines(shipmentDetailList.size() + wave.getTotalLines());
            wave.setTotalQty(qty.add(wave.getTotalQty()));
            wave.setLastUpdatedBy(ShiroUtils.getLoginName());

        }else {
            //创建波次
            wave=new Wave();
            wave.setWarehouseCode(ShiroUtils.getWarehouseCode());
            wave.setMasterCode(code);
            wave.setWaveName(waveMaster.getName());
            wave.setStatus(QuantityConstant.WAVE_STATUS_BUILD);
            wave.setCurrentWaveStep(QuantityConstant.WAVE_STEP_BUILD);
            wave.setTotalShipments(Convert.toIntArray(ids).length);
            wave.setTotalLines(shipmentDetailList.size());
            wave.setTotalQty(qty);
            wave.setCreatedBy(ShiroUtils.getLoginName());
            flag = waveService.save(wave);
            if (flag == false) {
                throw new ServiceException("波次建立失败");
            }
        }

        //修改出库子单,加入波次ID,并修改状态为波次
        for(ShipmentDetail shipmentDetail :shipmentDetailList){
            shipmentDetail.setWaveId(wave.getId());
            if(shipmentDetail.getStatus()<QuantityConstant.SHIPMENT_HEADER_WAVE) {
                shipmentDetail.setStatus(QuantityConstant.SHIPMENT_HEADER_WAVE);
            }
        }

        flag = this.updateBatchById(shipmentDetailList);
        if(flag == false){
            throw new ServiceException("出库子单加入波次失败");
        }

        for(ShipmentHeader shipmentHeader :shipmentHeaderList){
            shipmentHeader.setWaveId(wave.getId());
            shipmentHeader.setFirstStatus(QuantityConstant.SHIPMENT_HEADER_WAVE);
            if(shipmentHeader.getLastStatus()<QuantityConstant.SHIPMENT_HEADER_WAVE) {
                shipmentHeader.setLastStatus(QuantityConstant.SHIPMENT_HEADER_WAVE);
            }
        }
        flag = shipmentHeaderService.updateBatchById(shipmentHeaderList);
        if(flag == false){
            throw new ServiceException("修改主单状态失败");
        }

    }


    //查看最高状态和最低状态
    @Override
    public Map<String,Integer> selectStatus(Integer id) {
        return shipmentDetailMapper.selectStatus(id);
    }

    @Override
    public List<TaskDetail> getShipmentQtyLast7Days() {
        return shipmentDetailMapper.getShipmentQtyLast7Days();
    }

    @Override
    public List<TaskDetail> getWarehouseShipment() {
        return shipmentDetailMapper.getWarehouseShipment();
    }

    @Override
    public List<TaskDetail> getCompanyShipment() {
        return shipmentDetailMapper.getCompanyShipment();
    }

    @Override
    public Boolean insertDetails(List<ShipmentDetail> shipmentDetails) {
        int flag = shipmentDetailMapper.insertDetails(shipmentDetails);
        if(flag > 0){
            return true;
        }else {
            return false;
        }
    }

    /**
     * 更新入库单头表状态
     * @param shipmentHeader 入库单按头表
     * @return
     */
    @Override
    public AjaxResult updateShipmentHeader(ShipmentHeader shipmentHeader) {
        BigDecimal totalQty = BigDecimal.ZERO;
        int totalLines = 0;
        LambdaQueryWrapper<ShipmentDetail> shipmentDetailLambdaQueryWrapper = Wrappers.lambdaQuery();
        shipmentDetailLambdaQueryWrapper.eq(ShipmentDetail::getShipmentId, shipmentHeader.getId());
        List<ShipmentDetail> shipmentDetailList =  list(shipmentDetailLambdaQueryWrapper);
        for(ShipmentDetail shipmentDetail : shipmentDetailList) {
            totalLines++;
            totalQty = totalQty.add(shipmentDetail.getQty());
        }
        shipmentHeader.setTotalQty(totalQty);
        shipmentHeader.setTotalLines(totalLines);
        if (!shipmentHeaderService.updateById(shipmentHeader)){
            return AjaxResult.error("出库头表更新失败");
        }
        return AjaxResult.success("入库头表更新成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String insertExcelData(List<ShipmentDetail> list, boolean updateSupport, String operName) {

        if (StringUtils.isNull(list) || list.size() == 0) {
            throw new BusinessException("导入数据不能为空!");
        }
        ShipmentHeader shipmentHeader=createHeader(list);
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        for (ShipmentDetail importData : list) {
            /*if(StringUtils.isEmpty(importData.getWarehouseCode())){
                failureNum++;
                String msg = "<br/>" + failureNum + "、仓库编码为空 导入失败:";
                failureMsg.append(msg );
                continue;
            }
            if(StringUtils.isEmpty(importData.getCompanyCode())){
                failureNum++;
                String msg = "<br/>" + failureNum + "、货主编码为空 导入失败:";
                failureMsg.append(msg );
                continue;
            }*/
            if(StringUtils.isNull(importData.getQty())){
                failureNum++;
                String msg = "<br/>" + failureNum + "、数量为空 导入失败:";
                failureMsg.append(msg );
                continue;
            }
            try {
                importData.setShipmentId(shipmentHeader.getId());
                importData.setShipmentCode(shipmentHeader.getCode());
                Material material = materialService.getMaterialByCode(importData.getMaterialCode());
                importData.setMaterialName(material.getName());
                importData.setMaterialSpec(material.getSpec());
                importData.setMaterialUnit(material.getUnit());
                importData.setWarehouseCode(ShiroUtils.getWarehouseCode());
                importData.setCompanyCode(QuantityConstant.COMPANY_CS);
                importData.setInventorySts(QuantityConstant.GOOD);
                this.save(importData);
                successNum++;
                successMsg.append("<br/>" + successNum + "、数据 " + importData.getMaterialCode() + " 导入成功");

            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、物料编码 " + importData.getMaterialCode() + " 导入失败:";
                failureMsg.append(msg + e.getMessage());
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
            throw new BusinessException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
        }
        return successMsg.toString();
    }
    public ShipmentHeader createHeader(List<ShipmentDetail> list){
        ShipmentHeader shipmentHeader=new ShipmentHeader();
        String code =shipmentHeaderService.createCode(QuantityConstant.SHIPMENT_TYPE_PO,ShiroUtils.getWarehouseCode());
        shipmentHeader.setId(null);
        shipmentHeader.setLastUpdated(null);
        shipmentHeader.setLastUpdatedBy((ShiroUtils.getLoginName()));
        shipmentHeader.setCreated(null);
        shipmentHeader.setCreatedBy((ShiroUtils.getLoginName()));
        shipmentHeader.setWarehouseCode(ShiroUtils.getWarehouseCode());
        shipmentHeader.setCompanyCode(QuantityConstant.COMPANY_CS);
        shipmentHeader.setCode(code);
        shipmentHeader.setShipmentType(QuantityConstant.SHIPMENT_TYPE_PO);
        shipmentHeader.setTotalLines(list.size());
        shipmentHeader.setFirstStatus(QuantityConstant.SHIPMENT_HEADER_BUILD);
        shipmentHeader.setLastStatus(QuantityConstant.SHIPMENT_HEADER_BUILD);
        BigDecimal bigDecimal = list.stream().map(ShipmentDetail::getQty).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
        shipmentHeader.setTotalQty(bigDecimal);
        if (!shipmentHeaderService.save(shipmentHeader)) {
            throw new ServiceException("导入失败,添加出库单头表失败");
        }
        return shipmentHeader;
    }

    @Override
    public ShipmentDetail createShipmentDetail(ShipmentHeader header, LockingWorkOrder lockingWorkOrder) throws Exception {
        if (header == null || lockingWorkOrder == null){
            throw new Exception("找不到主单据");
        }
        ShipmentDetail shipmentDetail = new ShipmentDetail();
        // 公司编码
        shipmentDetail.setCompanyCode(ShiroUtils.getCompanyCode());
        // 公司id
//        shipmentDetail.setCompanyId(QuantityConstant.COMPANYID);
        // 库存状态
        shipmentDetail.setInventorySts("good");
        // 工作令
        shipmentDetail.setMoCode(lockingWorkOrder.getWorkOrder());
        // 物料编码
        shipmentDetail.setMaterialCode(lockingWorkOrder.getBomCode());
        // 数量
        shipmentDetail.setQty(lockingWorkOrder.getBnum());
        // 头表编码
        shipmentDetail.setShipmentCode(header.getCode());
        // 头表id
        shipmentDetail.setShipmentId(header.getId());
        ShipmentHeader shipmentHeader = shipmentHeaderService.getById(shipmentDetail.getShipmentId());
        if (shipmentHeader == null) {
            throw new Exception("找不到主单据");
        }
        if (shipmentHeader.getFirstStatus() > 100) {
            throw new Exception("主单据状态不允许新增明细");
        }
        Material material = new Material();
        if(shipmentDetail.getMaterialCode().length() == 11) {
            material.setCode(shipmentDetail.getMaterialCode());
        }else {
            material.setBarcode(shipmentDetail.getMaterialCode());
        }
        material = materialService.getMaterialByDomain(material);
        if (material == null) {
            throw new Exception("物料未找到");
        }
        if (StringUtils.isNotEmpty(material.getCompanyCode()) && ShiroUtils.getUser() != null &&
                ShiroUtils.getCompanyCodeList().contains(material.getCompanyCode()) == false)
        {
            throw new Exception("物料不属于当前货主!");
        }
        shipmentDetail.setId(null);
//        shipmentDetail.setWarehouseId(ShiroUtils.getWarehouseId());
        shipmentDetail.setWarehouseCode(ShiroUtils.getWarehouseCode());
        shipmentDetail.setMaterialId(material.getId());
        shipmentDetail.setMaterialCode(material.getCode());
        shipmentDetail.setMaterialName(material.getName());
        shipmentDetail.setCreated(null);
        shipmentDetail.setUWarehouseCode(shipmentHeader.getUWarehouseCode());
        if (ShiroUtils.getUser() == null){
            shipmentDetail.setCreatedBy(shipmentDetail.getCreatedBy());
            shipmentDetail.setLastUpdatedBy(shipmentDetail.getCreatedBy());
        }else {
            shipmentDetail.setCreatedBy(ShiroUtils.getLoginName());
            shipmentDetail.setLastUpdatedBy(ShiroUtils.getLoginName());
        }
        shipmentDetail.setLastUpdated(null);
        return shipmentDetail;
//        if (this.insert(shipmentDetail) > 0){
//            //更新单据总行数与总数量
//            shipmentHeader.setTotalLines(shipmentHeader.getTotalLines() + 1);
//            shipmentHeader.setTotalQty(shipmentHeader.getTotalQty().add(shipmentDetail.getQty()));
//            shipmentHeaderService.updateByModel(shipmentHeader);
//            return shipmentDetail;
//        }
//        else{
//            throw new RuntimeException("新增单据明细失败!");
//        }
    }

    @Override
    public List<ShipmentDetail> getListByShipmentHeaderId(Integer id,String warehouseCode) {
        if(id==0 || StringUtils.isEmpty(warehouseCode)){
            return null;
        }
        Warehouse warehouse = warehouseService.getOne(new LambdaQueryWrapper<Warehouse>()
                .eq(Warehouse::getCode, warehouseCode));
        if(warehouse==null){
            return null;
        }
        return this.list(new LambdaQueryWrapper<ShipmentDetail>()
                .eq(ShipmentDetail::getShipmentId,id)
                .eq(ShipmentDetail::getWarehouseCode,warehouseCode));
    }

}