package com.fjhx.victoriatourist.service.deliver.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.common.constant.SourceConstant;
import com.fjhx.common.utils.Assert;
import com.fjhx.item.entity.product.po.ProductInfo;
import com.fjhx.item.service.product.ProductInfoService;
import com.fjhx.purchase.entity.arrival.po.ArrivalDetail;
import com.fjhx.purchase.entity.arrival.vo.ArrivalDetailVo;
import com.fjhx.purchase.entity.purchase.po.Purchase;
import com.fjhx.purchase.entity.purchase.po.PurchaseDetail;
import com.fjhx.purchase.entity.purchase.vo.PurchaseDetailVo;
import com.fjhx.purchase.entity.purchase.vo.PurchaseVo;
import com.fjhx.purchase.entity.quality.po.QualityDetail;
import com.fjhx.purchase.service.arrival.ArrivalDetailService;
import com.fjhx.purchase.service.purchase.PurchaseDetailService;
import com.fjhx.purchase.service.purchase.PurchaseService;
import com.fjhx.supply.entity.supplier.po.SupplierInfo;
import com.fjhx.supply.service.supplier.SupplierInfoService;
import com.fjhx.victoriatourist.entity.deliver.dto.DeliverGoodsDto;
import com.fjhx.victoriatourist.entity.deliver.dto.DeliverGoodsSelectDto;
import com.fjhx.victoriatourist.entity.deliver.po.DeliverGoods;
import com.fjhx.victoriatourist.entity.deliver.po.DeliverGoodsDetails;
import com.fjhx.victoriatourist.entity.deliver.vo.DeliverGoodsDetailsVo;
import com.fjhx.victoriatourist.entity.deliver.vo.DeliverGoodsVo;
import com.fjhx.victoriatourist.entity.logistics.po.LogisticsDetails;
import com.fjhx.victoriatourist.entity.logistics.po.LogisticsInfos;
import com.fjhx.victoriatourist.entity.purchase.po.PurchaseBack;
import com.fjhx.victoriatourist.entity.purchase.po.PurchaseBackDetails;
import com.fjhx.victoriatourist.mapper.deliver.DeliverGoodsMapper;
import com.fjhx.victoriatourist.service.deliver.DeliverGoodsDetailsService;
import com.fjhx.victoriatourist.service.deliver.DeliverGoodsService;
import com.fjhx.victoriatourist.service.logistics.LogisticsDetailsService;
import com.fjhx.victoriatourist.service.logistics.LogisticsInfosService;
import com.fjhx.victoriatourist.service.purchase.PurchaseBackDetailsService;
import com.fjhx.victoriatourist.service.purchase.PurchaseBackService;
import com.fjhx.wms.entity.stock.po.StockJournal;
import com.fjhx.wms.entity.stock.po.StockJournalDetails;
import com.fjhx.wms.entity.stock.po.StockWait;
import com.fjhx.wms.entity.stock.po.StockWaitDetails;
import com.fjhx.wms.entity.stock.vo.StockJournalDetailsVo;
import com.fjhx.wms.service.stock.StockJournalDetailsService;
import com.fjhx.wms.service.stock.StockJournalService;
import com.fjhx.wms.service.stock.StockWaitDetailsService;
import com.fjhx.wms.service.stock.StockWaitService;
import com.ruoyi.common.utils.wrapper.IWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * <p>
 * 发货 服务实现类
 * </p>
 *
 * @author
 * @since 2023-04-13
 */
@DS(SourceConstant.VICTORIATOURIST)
@Service
public class DeliverGoodsServiceImpl extends ServiceImpl<DeliverGoodsMapper, DeliverGoods> implements DeliverGoodsService {
    @Autowired
    DeliverGoodsDetailsService deliverGoodsDetailsService;
    @Autowired
    ProductInfoService productInfoService;
    @Autowired
    PurchaseDetailService purchaseDetailService;
    @Autowired
    LogisticsInfosService logisticsInfosService;
    @Autowired
    LogisticsDetailsService logisticsDetailsService;
    @Autowired
    PurchaseService purchaseService;
    @Autowired
    private SupplierInfoService supplierInfoService;
    @Autowired
    private ArrivalDetailService arrivalDetailService;
    @Autowired
    private PurchaseBackDetailsService purchaseBackDetailsService;
    @Autowired
    private PurchaseBackService purchaseBackService;
    @Autowired
    private StockWaitService stockWaitService;
    @Autowired
    private StockWaitDetailsService stockWaitDetailsService;
    @Autowired
    private StockJournalDetailsService stockJournalDetailsService;
    @Autowired
    private StockJournalService stockJournalService;

    @Override
    public Page<DeliverGoodsVo> getPage(DeliverGoodsSelectDto dto) {
        IWrapper<DeliverGoods> wrapper = getWrapper();
        wrapper.orderByDesc("dg", DeliverGoods::getId);
        Page<DeliverGoodsVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        return page;
    }

    @Override
    public List<DeliverGoodsDetailsVo> detail(Long id) {
        Assert.notEmpty(id, "发货id不能为空");
//        DeliverGoods deliverGoods = this.getById(id);
//        DeliverGoodsVo deliverGoodsVo = BeanUtil.copyProperties(deliverGoods, DeliverGoodsVo.class);

        //根据发货id查发货明细
        IWrapper<DeliverGoods> wrapper = IWrapper.getWrapper();
        wrapper.eq("dgd.deliver_goods_id", id);
        wrapper.eq("dg.status", 0);
        List<DeliverGoodsDetailsVo> deliverGoodsDetailsVos = baseMapper.listDeliverGoodsDetails(wrapper);
        //获取采购明细列表
        //赋值产品信息
        List<Long> pdids = deliverGoodsDetailsVos.stream().map(DeliverGoodsDetails::getPurchaseDetailId).collect(Collectors.toList());
        if (ObjectUtil.isEmpty(pdids)) {
            return deliverGoodsDetailsVos;
        }
        List<PurchaseDetail> purchaseDetailList = purchaseDetailService.listByIds(pdids);
        Map<Long, Long> goodidmap = purchaseDetailList.stream().collect(Collectors.toMap(PurchaseDetail::getId, PurchaseDetail::getBussinessId));
        List<Long> goodids = purchaseDetailList.stream().map(PurchaseDetail::getBussinessId).collect(Collectors.toList());
        List<ProductInfo> productInfos = productInfoService.listByIds(goodids);
        Map<Long, ProductInfo> productInfoMap = productInfos.stream().collect(Collectors.toMap(ProductInfo::getId, Function.identity()));
        //获取采购明细信息
        Map<Long, PurchaseDetail> purchaseDetailMap = purchaseDetailList.stream().collect(Collectors.toMap(PurchaseDetail::getId, Function.identity()));

        for (DeliverGoodsDetailsVo deliverGoodsDetailsVo : deliverGoodsDetailsVos) {
            //赋值产品信息
            Long goodid = goodidmap.get(deliverGoodsDetailsVo.getPurchaseDetailId());
            ProductInfo productInfo = productInfoMap.get(goodid);
            if (ObjectUtil.isNotEmpty(productInfo)) {
                deliverGoodsDetailsVo.setProductId(productInfo.getId());
                deliverGoodsDetailsVo.setType(productInfo.getType());
                deliverGoodsDetailsVo.setCode(productInfo.getCode());
                deliverGoodsDetailsVo.setName(productInfo.getName());
                deliverGoodsDetailsVo.setSpec(productInfo.getSpec());
                deliverGoodsDetailsVo.setUnit(productInfo.getUnit());
                deliverGoodsDetailsVo.setDefinition(productInfo.getDefinition());
            }
            //赋值采购数量
            PurchaseDetail purchaseDetail = purchaseDetailMap.get(deliverGoodsDetailsVo.getPurchaseDetailId());
            deliverGoodsDetailsVo.setCount(purchaseDetail.getCount());
            //赋值在途数量
            IWrapper<DeliverGoods> wrapper1 = IWrapper.getWrapper();
            wrapper1.eq("dgd", DeliverGoodsDetails::getPurchaseDetailId, deliverGoodsDetailsVo.getPurchaseDetailId());
            wrapper1.eq("dg.status", 0);
            List<DeliverGoodsDetailsVo> list = baseMapper.listDeliverGoodsDetails(wrapper1);
            BigDecimal count = list.stream()
                    .map(DeliverGoodsDetails::getDeliverGoodsQuantity)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal subtract = count.subtract(deliverGoodsDetailsVo.getDeliverGoodsQuantity());
            deliverGoodsDetailsVo.setTransitQuantity(subtract);
        }

//        deliverGoodsVo.setDeliverGoodsDetailsList(deliverGoodsDetailsVos);
        return deliverGoodsDetailsVos;
    }

    @DSTransactional
    @Override
    public void add(DeliverGoodsDto deliverGoodsDto) {
        deliverGoodsDto.setStatus(0);//设置未到货
        this.save(deliverGoodsDto);

        //获取采购信息
        Purchase purchase = purchaseService.getById(deliverGoodsDto.getPurchaseId());
        //创建物流信息
        LogisticsInfos logisticsInfos = new LogisticsInfos();
        logisticsInfos.setBusinessId(deliverGoodsDto.getId());//设置业务id为发货id
//        logisticsInfos.setBusinessCode(purchase.getCode());//设置采购单号为业务单号
        String victoriatouristJson2 = purchase.getVictoriatouristJson();
        JSONObject json2 = ObjectUtil.isNotEmpty(victoriatouristJson2) ? JSONObject.parseObject(victoriatouristJson2) : new JSONObject();
        logisticsInfos.setBusinessCode(json2.getString("contractCode"));
        logisticsInfos.setBusinessType(1);//采购到货
        logisticsInfos.setStatus(0);
        logisticsInfos.setInStockStatus(10);
        logisticsInfos.setCode(deliverGoodsDto.getCode());
        logisticsInfos.setLogisticsCompanyCode(deliverGoodsDto.getLogisticsCompanyCode());
        logisticsInfos.setIsKd100(0);
        logisticsInfosService.save(logisticsInfos);

        List<DeliverGoodsDetails> deliverGoodsDetailsList = deliverGoodsDto.getDeliverGoodsDetailsList();
        List<LogisticsDetails> logisticsDetailsList = new ArrayList<>();

        for (DeliverGoodsDetails deliverGoodsDetails : deliverGoodsDetailsList) {
            deliverGoodsDetails.setDeliverGoodsId(deliverGoodsDto.getId());

            LogisticsDetails logisticsDetails = new LogisticsDetails();
            logisticsDetails.setBusinessDetailsId(deliverGoodsDetails.getId());//设置发货明细id为业务id
            logisticsDetails.setLogisticsInfoId(logisticsInfos.getId());
            logisticsDetails.setPurchaseId(purchase.getId());
            logisticsDetails.setPurchaseDetailsId(deliverGoodsDetails.getPurchaseDetailId());
            logisticsDetails.setShipmentQuantity(deliverGoodsDetails.getDeliverGoodsQuantity());
            logisticsDetailsList.add(logisticsDetails);
        }
        deliverGoodsDetailsService.saveBatch(deliverGoodsDetailsList);
        logisticsDetailsService.saveBatch(logisticsDetailsList);
    }

    @Override
    public void edit(DeliverGoodsDto deliverGoodsDto) {
        this.updateById(deliverGoodsDto);
    }

    @Override
    public void delete(Long id) {
        this.removeById(id);
    }

    @Override
    public List<DeliverGoods> list(Long id) {
        //根据采购id查发货列表
        List<DeliverGoods> list = list(q -> q.eq(DeliverGoods::getPurchaseId, id).eq(DeliverGoods::getStatus, 0));
        return list;
    }

    @Override
    public PurchaseVo arrivalDetail(Long purchaseId) {
        Purchase purchase = purchaseService.getById(purchaseId);
        PurchaseVo result = BeanUtil.toBean(purchase, PurchaseVo.class);
        //赋值供应商信息
        SupplierInfo supplierInfo = supplierInfoService.getById(purchase.getSupplyId());
        if (ObjectUtil.isNotEmpty(supplierInfo)) {
            result.setSupplyName(supplierInfo.getName());
        }
        //赋值采购明细
        List<PurchaseDetail> purchaseDetailList = purchaseDetailService.list(q -> q.eq(PurchaseDetail::getPurchaseId, purchase.getId()));
        List<PurchaseDetailVo> purchaseDetailVoList = BeanUtil.copyToList(purchaseDetailList, PurchaseDetailVo.class);
        //赋值产品信息
        productInfoService.attributeAssign(purchaseDetailVoList, PurchaseDetailVo::getBussinessId, (item, productInfo) -> {
            item.setProductCode(productInfo.getCode());
            item.setProductName(productInfo.getName());
            item.setProductCustomCode(productInfo.getCustomCode());
        });
        //赋值质检信息
        List<QualityDetail> qualityInfoByPurchaseId = baseMapper.getQualityInfoByPurchaseId(purchase.getId());
        if (ObjectUtil.isNotEmpty(qualityInfoByPurchaseId)) {
            Map<Long, QualityDetail> qualityDetailsMap = qualityInfoByPurchaseId.stream().collect(Collectors.toMap(QualityDetail::getBussinessId, Function.identity()));
            for (PurchaseDetailVo purchaseDetailVo : purchaseDetailVoList) {
                QualityDetail qualityDetails = qualityDetailsMap.get(purchaseDetailVo.getBussinessId());
                if (ObjectUtil.isEmpty(qualityDetails)) {
                    purchaseDetailVo.setQualifiedCount(BigDecimal.ZERO);
                    purchaseDetailVo.setNoQualifiedCount(BigDecimal.ZERO);
                    purchaseDetailVo.setQualityQuantity(BigDecimal.ZERO);
                    continue;
                }
                purchaseDetailVo.setQualifiedCount(qualityDetails.getQualifiedCount());
                purchaseDetailVo.setNoQualifiedCount(qualityDetails.getNoQualifiedCount());
                purchaseDetailVo.setQualityQuantity(qualityDetails.getQualifiedCount().add(qualityDetails.getNoQualifiedCount()));
            }
        }
        //赋值发货信息
        IWrapper<DeliverGoods> wrapper = getWrapper();
        wrapper.eq("dg", DeliverGoods::getPurchaseId, purchaseId);
        List<DeliverGoodsDetailsVo> list = baseMapper.listDeliverGoodsDetails(wrapper);
        if (ObjectUtil.isNotEmpty(list)) {
            Map<Long, List<DeliverGoodsDetailsVo>> collect = list.stream().collect(Collectors.groupingBy(DeliverGoodsDetailsVo::getPurchaseDetailId));
            for (PurchaseDetailVo purchaseDetailVo : purchaseDetailVoList) {
                List<DeliverGoodsDetailsVo> list1 = collect.get(purchaseDetailVo.getId());
                if (ObjectUtil.isEmpty(list1)) {
                    purchaseDetailVo.setDeliverGoodsQuantity(BigDecimal.ZERO);
                    continue;
                }
                //发货数量求和
                BigDecimal dgdCount = list1.stream()
                        .map(DeliverGoodsDetailsVo::getDeliverGoodsQuantity)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                purchaseDetailVo.setDeliverGoodsQuantity(dgdCount);
                purchaseDetailVo.setDeliverGoodsDetailList(list1);
            }
        }
        //赋值到货信息
        IWrapper<ArrivalDetail> wrapper1 = arrivalDetailService.getWrapper();
        wrapper1.eq("a.purchase_id", purchaseId);
        List<ArrivalDetailVo> arrivalDetail = arrivalDetailService.getArrivalDetail(wrapper1);
        if (ObjectUtil.isNotEmpty(arrivalDetail)) {
            Map<Long, List<ArrivalDetailVo>> collect = arrivalDetail.stream().collect(Collectors.groupingBy(ArrivalDetailVo::getBussinessId));

            Map<Long, String> dgdMap = list.stream().collect(Collectors.toMap(DeliverGoodsDetailsVo::getId, DeliverGoodsDetailsVo::getLogisticsCode));
            for (PurchaseDetailVo purchaseDetailVo : purchaseDetailVoList) {
                List<ArrivalDetailVo> list1 = collect.get(purchaseDetailVo.getBussinessId());
                if (ObjectUtil.isEmpty(list1)) {
                    purchaseDetailVo.setArrivalQuantity(BigDecimal.ZERO);
                    continue;
                }

                //赋值发货单号
                for (ArrivalDetailVo arrivalDetailVo : list1) {
                    arrivalDetailVo.setLogisticsCode(dgdMap.get(arrivalDetailVo.getDeliverGoodsDetailsId()));
                }

                //到货数量求和
                BigDecimal arrCount = list1.stream()
                        .map(ArrivalDetailVo::getCount)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                purchaseDetailVo.setArrivalQuantity(arrCount);
                purchaseDetailVo.setArrivalDetailList(list1);
            }
        }
        //赋值退货信息
        List<PurchaseBack> list1 = purchaseBackService.list(q -> q.eq(PurchaseBack::getPurchaseId, purchaseId));
        if (ObjectUtil.isNotEmpty(list1)) {
            List<Long> ids = list1.stream().map(PurchaseBack::getId).collect(Collectors.toList());
            Map<Long, List<PurchaseBackDetails>> longListMap = purchaseBackDetailsService.mapKGroup(PurchaseBackDetails::getPurchaseDetailsId, q -> q.in(PurchaseBackDetails::getPurchaseBackId, ids));

            for (PurchaseDetailVo purchaseDetailVo : purchaseDetailVoList) {
                List<PurchaseBackDetails> purchaseBackDetails = longListMap.get(purchaseDetailVo.getId());

                if (ObjectUtil.isEmpty(purchaseBackDetails)) {
                    purchaseDetailVo.setPurchaseBackQuantity(BigDecimal.ZERO);
                    continue;
                }
                //退货数量求和
                BigDecimal backCount = purchaseBackDetails.stream()
                        .map(PurchaseBackDetails::getQuantity)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                purchaseDetailVo.setPurchaseBackQuantity(backCount);
                purchaseDetailVo.setPurchaseBackDetailsList(purchaseBackDetails);
            }
        }
        //赋值已入库记录
        for (PurchaseDetailVo purchaseDetailVo : purchaseDetailVoList) {
            //根据采购明细id查到货明细
            List<ArrivalDetail> arrivalDetailList = arrivalDetailService.list(q -> q.eq(ArrivalDetail::getPurchaseDetailId, purchaseDetailVo.getId()));
            if (ObjectUtil.isEmpty(arrivalDetailList)) {
                continue;
            }
            //根据到货明细id查待入库明细
            List<Long> arrivalDetailIds = arrivalDetailList.stream().map(ArrivalDetail::getId).collect(Collectors.toList());
            List<StockWaitDetails> stockWaitDetailsList = stockWaitDetailsService.list(q -> q.in(StockWaitDetails::getBusinessDetailsId, arrivalDetailIds));
            if (ObjectUtil.isEmpty(stockWaitDetailsList)) {
                continue;
            }
            //根据待入库id查出入库记录
            List<Long> stockWaitId = stockWaitDetailsList.stream().map(StockWaitDetails::getStockWaitId).collect(Collectors.toList());
            List<Long> stockJournalIds = stockJournalService.listObject(StockJournal::getId, q -> q.in(StockJournal::getBusinessId, stockWaitId));
            if (ObjectUtil.isEmpty(stockJournalIds)) {
                continue;
            }
            //查出产品的出入库明细
            List<StockJournalDetails> stockJournalDetailsList = stockJournalDetailsService.list(q -> q.in(StockJournalDetails::getStockJournalId, stockJournalIds)
                    .eq(StockJournalDetails::getProductId, purchaseDetailVo.getBussinessId()));
            if (ObjectUtil.isEmpty(stockJournalDetailsList)) {
                continue;
            }
            List<StockJournalDetailsVo> stockJournalDetailsVos = BeanUtil.copyToList(stockJournalDetailsList, StockJournalDetailsVo.class);
            //对入库已入库列表赋值发货单号
            Map<Long, String> dgdMap = list.stream().collect(Collectors.toMap(DeliverGoodsDetailsVo::getId, DeliverGoodsDetailsVo::getLogisticsCode));

            for (StockJournalDetailsVo stockJournalDetailsVo : stockJournalDetailsVos) {
                StockJournal stockJournal = stockJournalService.getById(stockJournalDetailsVo.getStockJournalId());
                StockWaitDetails stockWaitDetails = stockWaitDetailsService.getOne(q -> q.eq(StockWaitDetails::getStockWaitId, stockJournal.getBusinessId()));

                Long businessDetailsId = stockWaitDetails.getBusinessDetailsId();
                ArrivalDetail arrivalDetail1 = arrivalDetailService.getById(businessDetailsId);

                //赋值发货单号
                stockJournalDetailsVo.setLogisticsCode(dgdMap.get(arrivalDetail1.getDeliverGoodsDetailsId()));
            }

            //对数量求和
            BigDecimal receiptQuantity = stockJournalDetailsList.stream()
                    .map(StockJournalDetails::getQuantity)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            //赋值数量和记录
            purchaseDetailVo.setReceiptQuantity(receiptQuantity);
            purchaseDetailVo.setReceiptList(stockJournalDetailsVos);
        }

        result.setPurchaseDetailVoList(purchaseDetailVoList);
        return result;
    }

}
