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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.area.utils.CustomizeAreaUtil;
import com.fjhx.customer.service.customer.CustomerService;
import com.fjhx.item.entity.product.po.ProductInfo;
import com.fjhx.item.service.product.ProductInfoService;
import com.fjhx.item.util.excel.util.ExcelUtil;
import com.fjhx.victoriatourist.entity.abnormal.po.AbnormalInfo;
import com.fjhx.victoriatourist.entity.jd.bo.JdOrderExcelImportBo;
import com.fjhx.victoriatourist.entity.jd.dto.JdOrderDto;
import com.fjhx.victoriatourist.entity.jd.dto.JdOrderSelectDto;
import com.fjhx.victoriatourist.entity.jd.po.JdOrder;
import com.fjhx.victoriatourist.entity.jd.po.JdOrderDetails;
import com.fjhx.victoriatourist.entity.jd.vo.JdOrderDetailsVo;
import com.fjhx.victoriatourist.entity.jd.vo.JdOrderVo;
import com.fjhx.victoriatourist.entity.logistics.po.LogisticsDetails;
import com.fjhx.victoriatourist.entity.logistics.po.LogisticsInfos;
import com.fjhx.victoriatourist.entity.stock.dto.StockTransferDto;
import com.fjhx.victoriatourist.entity.stock.po.StockTransfer;
import com.fjhx.victoriatourist.entity.stock.po.StockTransferDetails;
import com.fjhx.victoriatourist.mapper.jd.JdOrderMapper;
import com.fjhx.victoriatourist.service.abnormal.AbnormalInfoService;
import com.fjhx.victoriatourist.service.jd.JdOrderDetailsService;
import com.fjhx.victoriatourist.service.jd.JdOrderService;
import com.fjhx.victoriatourist.service.logistics.LogisticsDetailsService;
import com.fjhx.victoriatourist.service.logistics.LogisticsInfosService;
import com.fjhx.victoriatourist.service.stock.StockTransferDetailsService;
import com.fjhx.victoriatourist.service.stock.StockTransferService;
import com.fjhx.victoriatourist.utils.CodeEnum;
import com.fjhx.wms.entity.stock.emums.JournalType;
import com.fjhx.wms.entity.stock.emums.StockWaitType;
import com.fjhx.wms.entity.stock.po.*;
import com.fjhx.wms.service.stock.*;
import com.ruoyi.common.core.domain.BaseIdPo;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.wrapper.IWrapper;
import com.ruoyi.system.utils.UserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * <p>
 * 京东订单 服务实现类
 * </p>
 *
 * @author
 * @since 2023-04-20
 */
@Service
public class JdOrderServiceImpl extends ServiceImpl<JdOrderMapper, JdOrder> implements JdOrderService {

    @Autowired
    private CustomerService customerService;

    @Autowired
    private JdOrderDetailsService jdOrderDetailsService;

    @Autowired
    private ProductInfoService productInfoService;
    @Autowired
    private StockTransferService stockTransferService;
    @Autowired
    private StockTransferDetailsService stockTransferDetailsService;
    @Autowired
    private StockWaitService stockWaitService;
    @Autowired
    private StockWaitDetailsService stockWaitDetailsService;

    @Autowired
    private AbnormalInfoService abnormalInfoService;
    @Autowired
    private StockJournalService stockJournalService;
    @Autowired
    private StockJournalDetailsService stockJournalDetailsService;
    @Autowired
    private StockService stockService;
    @Autowired
    private LogisticsInfosService logisticsInfosService;
    @Autowired
    private LogisticsDetailsService logisticsDetailsService;

    @Override
    public Page<JdOrderVo> getPage(JdOrderSelectDto dto) {
        IWrapper<JdOrder> wrapper = getWrapper();
        wrapper.eq("jo", JdOrder::getStatus, dto.getStatus());
        wrapper.orderByDesc("jo", JdOrder::getId);

        if (ObjectUtil.isNotEmpty(dto.getKeyword())) {
            wrapper.and(q -> q.like(JdOrderVo::getCode, dto.getKeyword()));
        }

        Page<JdOrderVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        List<JdOrderVo> records = page.getRecords();
        if (records.size() == 0) {
            return page;
        }

        // 赋值国省市
        CustomizeAreaUtil.setAreaName(records);

        // 赋值客户名称
        customerService.attributeAssign(records, JdOrder::getCustomerId, (item, customer) -> {
            item.setCustomerName(customer.getName());
        });

        return page;
    }

    @Override
    public JdOrderVo detail(Long id) {
        JdOrder JdOrder = this.getById(id);
        JdOrderVo result = BeanUtil.toBean(JdOrder, JdOrderVo.class);

        List<JdOrderDetails> jdOrderDetailsList = jdOrderDetailsService.list(q -> q.eq(JdOrderDetails::getJdOrderId, id));
        List<JdOrderDetailsVo> jdOrderDetailsVoList = BeanUtil.copyToList(jdOrderDetailsList, JdOrderDetailsVo.class);
        productInfoService.attributeAssign(jdOrderDetailsVoList, JdOrderDetails::getProductId, (item, product) -> {
            item.setProductCode(product.getCode());
            item.setProductName(product.getName());
            item.setProductCustomCode(product.getCustomCode());
        });

        result.setJdOrderDetailsList(jdOrderDetailsVoList);
        return result;
    }

    @DSTransactional
    @Override
    public void add(JdOrderDto jdOrderDto) {

        // 订单id
        long jdOrderId = IdWorker.getId();

        // 订单金额
        BigDecimal amount = BigDecimal.ZERO;

        //创建待出库记录
        StockWait stockWait = new StockWait();
        stockWait.setType(2);//待出库
        stockWait.setBusinessType(StockWaitType.JD_ORDER_OUT.getDetailType());
        stockWait.setBusinessId(jdOrderId);
        stockWait.setBusinessCode(jdOrderDto.getCode());
        stockWait.setStatus(0);
        stockWaitService.save(stockWait);

        List<JdOrderDetails> jdOrderDetailsList = jdOrderDto.getJdOrderDetailsList();

        List<StockWaitDetails> stockWaitDetailsList = new ArrayList<>();
        for (JdOrderDetails jdOrderDetails : jdOrderDetailsList) {
            jdOrderDetails.setJdOrderId(jdOrderId);
            jdOrderDetails.setSubtotal(jdOrderDetails.getPrice().multiply(jdOrderDetails.getQuantity()));
            jdOrderDetails.setQuantityDelivered(BigDecimal.ZERO);
            amount = amount.add(jdOrderDetails.getSubtotal());

            //创建待出库明细
            StockWaitDetails stockWaitDetails = new StockWaitDetails();
            stockWaitDetails.setStockWaitId(stockWait.getId());
            stockWaitDetails.setProductId(jdOrderDetails.getProductId());
            stockWaitDetails.setQuantity(jdOrderDetails.getQuantity());
            stockWaitDetails.setBusinessDetailsId(jdOrderDetails.getId());
            stockWaitDetailsList.add(stockWaitDetails);
        }
        stockWaitDetailsService.saveBatch(stockWaitDetailsList);

        jdOrderDto.setId(jdOrderId);
        // 未出库
        jdOrderDto.setStatus(1);
        // 订单金额
        jdOrderDto.setAmount(amount);
        jdOrderDto.setQuantityDelivered(BigDecimal.ZERO);

        this.save(jdOrderDto);
        this.jdOrderDetailsService.saveBatch(jdOrderDetailsList);

        CustomizeAreaUtil.setAreaId(jdOrderDto);


    }

    @DSTransactional
    @Override
    public void excelImport(MultipartFile file, Long customerId) {
        List<JdOrderExcelImportBo> boList = ExcelUtil.read(file, JdOrderExcelImportBo.class);
        if (ObjectUtil.isEmpty(boList)) {
            throw new ServiceException("Excel文档为空！！！");
        }
        if (boList.stream().filter(item -> ObjectUtil.isEmpty(item.getCode())).count() > 0) {
            throw new ServiceException("Excel中存在没有采购单号的数据请检查！！！");
        }
        if (boList.stream().filter(item -> ObjectUtil.isEmpty(item.getProductCode())).count() > 0) {
            throw new ServiceException("Excel中存在没有商品编号的数据请检查！！！");
        }

        //检查采购单号是否已经在系统中存在,如果存在报错
        List<String> codes = boList.stream().map(JdOrderExcelImportBo::getCode).distinct().collect(Collectors.toList());
        List<JdOrder> jdOrderList = this.list(q -> q.in(JdOrder::getCode, codes));
        if (ObjectUtil.isNotEmpty(jdOrderList)) {
            String codeList = jdOrderList.stream().map(JdOrder::getCode).collect(Collectors.joining(","));
            throw new ServiceException("以下订单已经在系统中存在->" + codeList);
        }

        List<String> productCodeList = boList.stream().map(JdOrderExcelImportBo::getProductCode)
                .filter(Objects::nonNull).distinct().collect(Collectors.toList());

        // 验证产品编号是否存在
        List<ProductInfo> productInfoList = productInfoService.list(q -> q.in(ProductInfo::getCustomCode, productCodeList));
        if (productInfoList.size() != productCodeList.size()) {
            List<String> itemCodeList = productInfoList.stream().map(ProductInfo::getCustomCode).collect(Collectors.toList());
            String nonCodeStr = productCodeList.stream().filter(item -> !itemCodeList.contains(item)).collect(Collectors.joining(","));
            throw new ServiceException("未知产品编号：" + nonCodeStr);
        }

        // 产品编号、产品id map
        Map<String, Long> productCodeIdMap = productInfoList.stream().collect(Collectors.toMap(ProductInfo::getCustomCode, BaseIdPo::getId));

        // 订单编号、订单信息 map
        HashMap<String, JdOrder> orderCodeIdMap = new LinkedHashMap<>();
        List<JdOrderDetails> orderDetailsList = new ArrayList<>();

//        List<StockWait> stockWaitList = new ArrayList<>();
        //订单编号、待出库记录 map
        Map<String, StockWait> stockWaitMap = new HashMap<>();
        List<StockWaitDetails> stockWaitDetailsList = new ArrayList<>();

        long batchFlag = IdWorker.getId();

        for (JdOrderExcelImportBo bo : boList) {
            // 订单id
            JdOrder jdOrder = orderCodeIdMap.computeIfAbsent(bo.getCode(), code -> {
                Long id = IdWorker.getId();

                JdOrder item = new JdOrder();
                item.setId(id);
                item.setCode(bo.getCode());
                item.setCustomerId(customerId);
                item.setDistributionCenter(bo.getDistributionCenter());
                item.setDetailedAddress(bo.getDetailedAddress());
                item.setContactPerson(bo.getContactPerson());
                item.setContactNumber(bo.getContactNumber());
                item.setAmount(BigDecimal.ZERO);
                item.setStatus(1);
                item.setQuantityDelivered(BigDecimal.ZERO);
                item.setBatchFlag(batchFlag);

                //创建待出库记录
                StockWait stockWait = new StockWait();
                stockWait.setType(2);//待出库
                stockWait.setBusinessType(StockWaitType.JD_ORDER_OUT.getDetailType());
                stockWait.setBusinessId(item.getId());
                stockWait.setBusinessCode(item.getCode());
                stockWait.setStatus(0);
//                stockWaitList.add(stockWait);
                stockWaitMap.put(bo.getCode(), stockWait);

                return item;
            });

            BigDecimal subtotal = bo.getQuantity().multiply(bo.getPrice());
            jdOrder.setAmount(jdOrder.getAmount().add(subtotal));

            JdOrderDetails jdOrderDetails = new JdOrderDetails();
            jdOrderDetails.setId(IdWorker.getId());
            jdOrderDetails.setJdOrderId(jdOrder.getId());
            Long productId = productCodeIdMap.get(bo.getProductCode());
            if (ObjectUtil.isEmpty(productId)) {
                throw new ServiceException("未知产品->" + bo.getProductCode());
            }
            jdOrderDetails.setProductId(productId);
            jdOrderDetails.setPrice(bo.getPrice());
            jdOrderDetails.setQuantity(bo.getQuantity());
            jdOrderDetails.setSubtotal(subtotal);
            jdOrderDetails.setQuantityDelivered(BigDecimal.ZERO);
            orderDetailsList.add(jdOrderDetails);

            //创建待出库明细
            StockWaitDetails stockWaitDetails = new StockWaitDetails();
            //获取待出库id并赋值给明细
            StockWait stockWait = stockWaitMap.get(bo.getCode());
            if (ObjectUtil.isEmpty(stockWait)) {
                throw new ServiceException("待出库id为空");
            }
            stockWaitDetails.setStockWaitId(stockWait.getId());
            stockWaitDetails.setProductId(jdOrderDetails.getProductId());
            stockWaitDetails.setQuantity(jdOrderDetails.getQuantity());
            stockWaitDetails.setBusinessDetailsId(jdOrderDetails.getId());
            stockWaitDetailsList.add(stockWaitDetails);
        }

        //保存京东订单信息
        this.saveBatch(orderCodeIdMap.values());
        this.jdOrderDetailsService.saveBatch(orderDetailsList);

        //保存待出库明细
        stockWaitService.saveBatch(stockWaitMap.values());
        stockWaitDetailsService.saveBatch(stockWaitDetailsList);
    }

    @DSTransactional
    @Override
    public void outbound(JdOrderDto jdOrderDto) {
        //修改待出库状态
        StockWait stockWait = stockWaitService.getOne(q -> q.eq(StockWait::getBusinessId, jdOrderDto.getId()));
        stockWait.setStatus(2);
        stockWaitService.updateById(stockWait);

        JdOrder jdOrder = getById(jdOrderDto.getId());
        jdOrder.setStatus(3);//将京东订单状态修改为出库
        updateById(jdOrder);
        //创建京东订单调仓
        StockTransfer stockTransfer = new StockTransfer();
        stockTransfer.setType(2);//京东订单出库
        stockTransfer.setCode(CodeEnum.STOCK_TRANSFER.getCode());
        stockTransfer.setBusinessId(jdOrder.getId());
        stockTransfer.setBusinessCode(jdOrder.getCode());
        stockTransfer.setInWarehouseId(jdOrderDto.getInWarehouseId());
        stockTransfer.setOutWarehouseId(jdOrderDto.getOutWarehouseId());
        stockTransfer.setInStatus(0);
        stockTransfer.setRemark(jdOrderDto.getRemark());
        stockTransferService.save(stockTransfer);
        //创建明细
        List<StockTransferDetails> stockTransferDetailsList = new ArrayList<>();
        List<JdOrderDetails> jdOrderDetailsList = jdOrderDto.getJdOrderDetailsList();
        List<Stock> stockList = new ArrayList<>();
        for (JdOrderDetails jdOrderDetails : jdOrderDetailsList) {
            StockTransferDetails stockTransferDetails = new StockTransferDetails();
            stockTransferDetails.setBusinessDetailsId(jdOrderDetails.getId());
            stockTransferDetails.setStockTransferId(stockTransfer.getId());
            stockTransferDetails.setOutQuantity(jdOrderDetails.getQuantity());
            stockTransferDetails.setProductId(jdOrderDetails.getProductId());
            stockTransferDetailsList.add(stockTransferDetails);

            //创建出库数据
            Stock stock = new Stock();
            stock.setProductId(jdOrderDetails.getProductId());
            stock.setQuantity(jdOrderDetails.getQuantity());
            stockList.add(stock);
        }
        stockTransferDetailsService.saveBatch(stockTransferDetailsList);

        //创建出库记录
        StockJournal stockJournal1 = new StockJournal();
        stockJournal1.setOpType(2);
        stockJournal1.setType(JournalType.ADJUSTING_OUT.getDetailType());
        stockJournal1.setCode(stockTransfer.getCode());
        stockJournal1.setWarehouseId(stockTransfer.getOutWarehouseId());
        stockJournal1.setBusinessId(stockTransfer.getId());
        //保存出库记录
        stockJournalService.save(stockJournal1);
        if (ObjectUtil.isNotEmpty(stockList)) {
            //出库
            List<StockJournalDetails> stockJournalDetailsList1 = stockService.ModifyInventory(stockJournal1.getId(), 2, stockList, stockTransfer.getOutWarehouseId());
            //保存出库记录明细
            stockJournalDetailsService.saveBatch(stockJournalDetailsList1);
        }

        //创建物流数据
        LogisticsInfos logisticsInfos = new LogisticsInfos();
        logisticsInfos.setBusinessId(jdOrderDto.getId());
        logisticsInfos.setBusinessCode(jdOrderDto.getCode());
        logisticsInfos.setBusinessType(2);//京东订单出库
        logisticsInfos.setLogisticsCompanyCode(jdOrderDto.getLogisticsCompanyCode());
        logisticsInfos.setCode(jdOrderDto.getLogisticsCode());
        logisticsInfos.setWarehouseId(jdOrderDto.getOutWarehouseId());
        logisticsInfos.setReservationCode(jdOrderDto.getReservationCode());
        logisticsInfos.setIsKd100(0);
        logisticsInfosService.save(logisticsInfos);

        List<LogisticsDetails> logisticsDetailsList = new ArrayList<>();
        for (JdOrderDetails jdOrderDetails : jdOrderDetailsList) {
            LogisticsDetails logisticsDetails = new LogisticsDetails();
            logisticsDetails.setLogisticsInfoId(logisticsInfos.getId());
            logisticsDetails.setLogisticsInfoCode(logisticsInfos.getCode());
            logisticsDetails.setBusinessDetailsId(jdOrderDetails.getId());
            logisticsDetails.setReceiptQuantity(jdOrderDetails.getQuantity());
        }
        logisticsDetailsService.saveBatch(logisticsDetailsList);
    }

    @Override
    public Page<JdOrderVo> receivePage(JdOrderSelectDto dto) {
        IWrapper<JdOrder> wrapper = getWrapper();
        wrapper.eq("st.in_status", dto.getInStatus());
        wrapper.orderByDesc("jdo.create_time");

        if (ObjectUtil.isNotEmpty(dto.getKeyword())) {
            wrapper.and(q -> q.like("jdo", JdOrderVo::getCode, dto.getKeyword()));
        }

        Page<JdOrderVo> page = this.baseMapper.getReceivePage(dto.getPage(), wrapper);
        List<JdOrderVo> records = page.getRecords();
        // 赋值国省市
        CustomizeAreaUtil.setAreaName(records);
        //赋值接收人名字
        UserUtil.assignmentNickName(records, JdOrderVo::getInUserId, JdOrderVo::setInUserName);
        // 赋值客户名称
        customerService.attributeAssign(records, JdOrderVo::getCustomerId, (item, customer) -> {
            item.setCustomerName(customer.getName());
        });
        return page;
    }

    @DSTransactional
    @Override
    public void receive(StockTransferDto stockTransferDto) {
        StockTransfer stockTransfer = stockTransferService.getById(stockTransferDto.getId());
        //修改调仓状态
        stockTransfer.setInStatus(2);//修改为已接收
        stockTransfer.setInUserId(SecurityUtils.getUserId());//赋值接收人
        stockTransfer.setInTime(new Date());//赋值接收时间

        //明细
        List<Stock> stockList = new ArrayList<>();
        List<StockTransferDetails> stockTransferDetailsList = stockTransferDto.getStockTransferDetailsList();
        if (ObjectUtil.isNotEmpty(stockTransferDetailsList)) {
            //获取数据库中的数据
            List<Long> ids = stockTransferDetailsList.stream().map(StockTransferDetails::getId).collect(Collectors.toList());
            List<StockTransferDetails> oldstockTransferDetailsList = stockTransferDetailsService.listByIds(ids);
            Map<Long, StockTransferDetails> oldstockTransferDetailsMap = oldstockTransferDetailsList.stream().collect(Collectors.toMap(StockTransferDetails::getId, Function.identity()));

            Integer abnormalFlag = 0;
            for (StockTransferDetails stockTransferDetails : stockTransferDetailsList) {
                Stock stock = new Stock();
                stock.setProductId(stockTransferDetails.getProductId());
                stock.setQuantity(stockTransferDetails.getInQuantity());
                stockList.add(stock);

                //调仓接收数量与发出数量不一致
                StockTransferDetails oldstockTransferDetails = oldstockTransferDetailsMap.get(stockTransferDetails.getId());
                //计算接收总数 接收数+已经接收数
                BigDecimal inQuantitySum = oldstockTransferDetails.getInQuantity().add(stockTransferDetails.getInQuantity());
                if (inQuantitySum.compareTo(oldstockTransferDetails.getOutQuantity()) != 0) {
                    abnormalFlag = 1;
                }

                //计算已入库数量
                BigDecimal inCount = oldstockTransferDetails.getInQuantity().add(stockTransferDetails.getInQuantity());
                if (inCount.compareTo(oldstockTransferDetails.getOutQuantity()) != 0) {
                    stockTransfer.setInStatus(1);//设置为部分接收
                }
                stockTransferDetails.setInQuantity(inCount);


            }
            if (abnormalFlag == 1) {
                AbnormalInfo abnormalInfo = new AbnormalInfo();
                abnormalInfo.setStatus(0);
                abnormalInfo.setId(IdWorker.getId());
                abnormalInfo.setType(30);
                abnormalInfo.setLinkId(stockTransfer.getId());
                abnormalInfo.setLinkCode(stockTransfer.getCode());
                abnormalInfo.setTitle("京东订单接收数量与发出数量不一致");
                abnormalInfoService.save(abnormalInfo);
            }
        }

        stockTransferService.updateById(stockTransfer);
        stockTransferDetailsService.updateBatchById(stockTransferDetailsList);
        //创建入库记录
        StockJournal stockJournal = new StockJournal();
        stockJournal.setOpType(1);
        stockJournal.setType(JournalType.ADJUSTING_IN.getDetailType());
        stockJournal.setCode(stockTransfer.getCode());
        stockJournal.setWarehouseId(stockTransfer.getInWarehouseId());
        stockJournal.setBusinessId(stockTransfer.getId());
        //保存人库记录
        stockJournalService.save(stockJournal);
        if (ObjectUtil.isNotEmpty(stockList)) {
            //入库
            List<StockJournalDetails> stockJournalDetailsList = stockService.ModifyInventory(stockJournal.getId(), 1, stockList, stockTransfer.getInWarehouseId());
            //保存入库记录明细
            stockJournalDetailsService.saveBatch(stockJournalDetailsList);
        }
    }

}
