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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
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.item.entity.product.po.ProductInfo;
import com.fjhx.item.service.product.ProductInfoService;
import com.fjhx.item.util.excel.util.ExcelUtil;
import com.fjhx.kd100.entity.company.po.CompanyInfo;
import com.fjhx.kd100.service.company.CompanyInfoService;
import com.fjhx.victoriatourist.entity.jd.dto.JdBackDto;
import com.fjhx.victoriatourist.entity.jd.dto.JdBackSelectDto;
import com.fjhx.victoriatourist.entity.jd.po.JdBack;
import com.fjhx.victoriatourist.entity.jd.po.JdBackDetails;
import com.fjhx.victoriatourist.entity.jd.po.JdBackQualityWait;
import com.fjhx.victoriatourist.entity.jd.vo.JdBackVo;
import com.fjhx.victoriatourist.entity.logistics.po.LogisticsInfos;
import com.fjhx.victoriatourist.mapper.jd.JdBackMapper;
import com.fjhx.victoriatourist.service.jd.JdBackDetailsService;
import com.fjhx.victoriatourist.service.jd.JdBackQualityWaitService;
import com.fjhx.victoriatourist.service.jd.JdBackService;
import com.fjhx.victoriatourist.service.logistics.LogisticsInfosService;
import com.fjhx.wms.entity.warehouse.po.Warehouse;
import com.fjhx.wms.service.warehouse.WarehouseService;
import com.obs.services.internal.ServiceException;
import com.ruoyi.common.utils.wrapper.IWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
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-18
 */
@Service
public class JdBackServiceImpl extends ServiceImpl<JdBackMapper, JdBack> implements JdBackService {
    @Autowired
    private WarehouseService warehouseService;
    @Autowired
    private CompanyInfoService companyInfoService;
    @Autowired
    private LogisticsInfosService logisticsInfosService;
    @Autowired
    private JdBackDetailsService jdBackDetailsService;
    @Autowired
    private ProductInfoService productInfoService;
    @Autowired
    private JdBackQualityWaitService jdBackQualityWaitService;

    @Override
    public Page<JdBackVo> getPage(JdBackSelectDto dto) {
        IWrapper<JdBack> wrapper = getWrapper();
        wrapper.like("jb", JdBackVo::getLogisticsCode, dto.getKeyword());
        wrapper.eq("jb", JdBackVo::getType, dto.getType());
        wrapper.eq("jb", JdBackVo::getStatus, dto.getStatus());
        wrapper.orderByDesc("jb", JdBack::getId);
        Page<JdBackVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        List<JdBackVo> records = page.getRecords();
        if (ObjectUtil.isEmpty(records)) {
            return page;
        }
        //赋值仓库名称
        warehouseService.attributeAssign(records, JdBackVo::getWarehouseId, (item, warehouse) -> {
            item.setWarehouseName(warehouse.getName());
        });
        //赋值物流公司名称
        List<String> companyCode = records.stream().map(JdBackVo::getLogisticsCompanyCode).collect(Collectors.toList());
        List<CompanyInfo> companyInfoList = companyInfoService.list(q -> q.in(CompanyInfo::getCode, companyCode));
        Map<String, String> companyInfoMap = companyInfoList.stream().collect(Collectors.toMap(CompanyInfo::getCode, CompanyInfo::getName));
        for (JdBackVo record : records) {
            record.setLogisticsCompanyName(companyInfoMap.get(record.getLogisticsCompanyCode()));
        }
        return page;
    }

    @Override
    public JdBackVo detail(Long id) {
        JdBack JdBack = this.getById(id);
        JdBackVo result = BeanUtil.toBean(JdBack, JdBackVo.class);
        //赋值物流信息
        LogisticsInfos logisticsInfos = logisticsInfosService.getOne(q -> q.eq(LogisticsInfos::getBusinessId, result.getId()));
        if (ObjectUtil.isNotEmpty(logisticsInfos)) {
            result.setLogisticsCompanyCode(logisticsInfos.getLogisticsCompanyCode());
            result.setLogisticsCode(logisticsInfos.getCode());
        }
        //赋值仓库名称
        Warehouse warehouse = warehouseService.getById(result.getWarehouseId());
        if (ObjectUtil.isNotEmpty(warehouse)) {
            result.setWarehouseName(warehouse.getName());
        }
        //赋值物流公司名称
        CompanyInfo companyInfo = companyInfoService.getOne(q -> q.eq(CompanyInfo::getCode, result.getLogisticsCompanyCode()));
        if (ObjectUtil.isNotEmpty(companyInfo)) {
            result.setLogisticsCompanyName(companyInfo.getName());
        }
        //赋值退货明细
        List<JdBackDetails> jdBackDetailsList = jdBackDetailsService.list(q -> q.eq(JdBackDetails::getJdBackId, id));
        result.setJdBackDetailsList(jdBackDetailsList);
        return result;
    }

    @DSTransactional
    @Override
    public void add(JdBackDto jdBackDto) {
        jdBackDto.setType(1);
        jdBackDto.setStatus(1);
        this.save(jdBackDto);
        //创建物流信息
        LogisticsInfos logisticsInfos = new LogisticsInfos();
        logisticsInfos.setLogisticsStatus(4);
        logisticsInfos.setStatus(0);
        logisticsInfos.setInStockStatus(10);
        logisticsInfos.setBusinessId(jdBackDto.getId());
        logisticsInfos.setBusinessType(4);//京东退货
        logisticsInfos.setWarehouseId(jdBackDto.getWarehouseId());
        logisticsInfos.setLogisticsCompanyCode(jdBackDto.getLogisticsCompanyCode());
        logisticsInfos.setCode(jdBackDto.getLogisticsCode());
        logisticsInfosService.save(logisticsInfos);
        //创建退货明细
        List<JdBackDetails> jdBackDetailsList = jdBackDto.getJdBackDetailsList();
        if (ObjectUtil.isNotEmpty(jdBackDetailsList)) {
            for (JdBackDetails jdBackDetails : jdBackDetailsList) {
                jdBackDetails.setJdBackId(jdBackDto.getId());
            }
            jdBackDetailsService.saveBatch(jdBackDetailsList);
        }
        //创建待质检记录
//        createJdBackQualityWait(jdBackDetailsList);
    }

    /**
     * 根据退货列表创建待质检记录通用方法
     */
    @DSTransactional
    @Override
    public void createJdBackQualityWait(List<JdBackDetails> jdBackDetailsList) {
        Map<Long, BigDecimal> map = new HashMap<>();
        List<String> productCodeList = jdBackDetailsList.stream().map(JdBackDetails::getProductCode).collect(Collectors.toList());
        if (ObjectUtil.isEmpty(productCodeList)) {
            throw new ServiceException("退货列表为空");
        }
        List<ProductInfo> productList = productInfoService.list(q -> q.in(ProductInfo::getCustomCode, productCodeList));
        if (productList.size() != jdBackDetailsList.size()) {
            throw new ServiceException("存在未知产品");
        }
        Map<String, ProductInfo> productInfoMap = productList.stream().collect(Collectors.toMap(ProductInfo::getCustomCode, Function.identity()));
        for (JdBackDetails jdBackDetails : jdBackDetailsList) {
            ProductInfo productInfo = productInfoMap.get(jdBackDetails.getProductCode());
            if (ObjectUtil.isEmpty(productInfo)) {
                continue;
            }
            //判断是否存在扩展json
            String victoriatouristJson = productInfo.getVictoriatouristJson();
            if (ObjectUtil.isNotEmpty(victoriatouristJson)) {
                JSONObject json = JSONObject.parseObject(victoriatouristJson);
                //判断是否是组合
                if (1 == json.getInteger("combination")) {
                    JSONArray productCombinationList = json.getJSONArray("productCombinationList");
                    if (ObjectUtil.isEmpty(productCombinationList)) {
                        continue;
                    }
                    for (int i = 0; i < productCombinationList.size(); i++) {
                        JSONObject productCombination = productCombinationList.getJSONObject(i);
                        Long linkProductId = productCombination.getLong("linkProductId");
                        BigDecimal linkQuantity = productCombination.getBigDecimal("linkQuantity");

                        //根据退货数量*组合产品对应组成产品所需要的数量计算待质检数量
                        BigDecimal quantity0 = jdBackDetails.getQuantity().multiply(linkQuantity);

                        BigDecimal quantity = map.getOrDefault(linkProductId, BigDecimal.ZERO);
                        map.put(productInfo.getId(), quantity.add(quantity0));
                    }
                    //组合产品处理完直接结束
                    continue;
                }
            }
            //如果不是组合产品
            BigDecimal quantity = map.getOrDefault(productInfo.getId(), BigDecimal.ZERO);
            map.put(productInfo.getId(), quantity.add(jdBackDetails.getQuantity()));
        }
        //创建待质检记录
        if (ObjectUtil.isEmpty(map)) {
            return;
        }
        List<JdBackQualityWait> addJdBackQualityWaitList = new ArrayList<>();
        //获取已存在的待质检产品列表
        List<JdBackQualityWait> jdBackQualityWaitList1 = jdBackQualityWaitService.list(q -> q.in(JdBackQualityWait::getProductId, map.keySet()));
        Map<Long, JdBackQualityWait> JdBackQualityWaitMap = jdBackQualityWaitList1.stream().collect(Collectors.toMap(JdBackQualityWait::getProductId, Function.identity()));
        for (Map.Entry<Long, BigDecimal> entry : map.entrySet()) {
            JdBackQualityWait oldJdBackQualityWait = JdBackQualityWaitMap.getOrDefault(entry.getKey(), new JdBackQualityWait());
            oldJdBackQualityWait.setProductId(entry.getKey());
            //计算历史待质检+当前待质检
            BigDecimal oldQuantity = oldJdBackQualityWait.getQuantity() == null ? BigDecimal.ZERO : oldJdBackQualityWait.getQuantity();
            oldJdBackQualityWait.setQuantity(oldQuantity.add(entry.getValue()));

            //添加部分直接丢list统一处理
            if (ObjectUtil.isEmpty(oldJdBackQualityWait.getId())) {
                addJdBackQualityWaitList.add(oldJdBackQualityWait);
            }
            //处理更新部分
            jdBackQualityWaitService.update(q -> q
                    .eq(JdBackQualityWait::getId, oldJdBackQualityWait.getId())
                    .setSql("quantity = quantity + " + entry.getValue()));
        }
        //统一处理添加部分
        jdBackQualityWaitService.saveBatch(addJdBackQualityWaitList);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(JdBackDto jdBackDto) {
        this.updateById(jdBackDto);
        //更新物流信息
        LogisticsInfos logisticsInfos = logisticsInfosService.getOne(q -> q.eq(LogisticsInfos::getBusinessId, jdBackDto.getId()));
        logisticsInfos.setLogisticsCompanyCode(jdBackDto.getLogisticsCompanyCode());
        logisticsInfos.setCode(jdBackDto.getLogisticsCode());
        logisticsInfosService.updateById(logisticsInfos);
        //更新退货明细
        List<JdBackDetails> jdBackDetailsList = jdBackDto.getJdBackDetailsList();
        if (ObjectUtil.isEmpty(jdBackDetailsList)) {
            return;
        }
        //处理删除部分
        List<Long> jdBackDetailsIds = jdBackDetailsList.stream().filter(item -> item.getId() != null).map(JdBackDetails::getId).collect(Collectors.toList());
        jdBackDetailsService.remove(q -> q.eq(JdBackDetails::getJdBackId, jdBackDto.getId()).notIn(JdBackDetails::getId, jdBackDetailsIds));
        //处理新增部分
        for (JdBackDetails jdBackDetails : jdBackDetailsList) {
            jdBackDetails.setJdBackId(jdBackDto.getId());
        }
        jdBackDetailsService.saveOrUpdateBatch(jdBackDetailsList);
    }

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

    @DSTransactional
    @Override
    public void excelImport(MultipartFile file, Long warehouseId) {
        long batchFlag = IdWorker.getId();

        // 读取excel数据
        List<JdBackDetails> jdBackDetailsList = ExcelUtil.read(file, JdBackDetails.class);

        if (jdBackDetailsList.size() == 0) {
            return;
        }

        //判断运单号是否唯一
        List<String> waybillList = jdBackDetailsList.stream().map(JdBackDetails::getWaybill).collect(Collectors.toList());
        List<JdBack> list1 = list(q -> q.in(JdBack::getWaybill, waybillList));
        if (list1.size() > 0) {
            List<String> waybillList1 = list1.stream().map(JdBack::getWaybill).collect(Collectors.toList());
            throw new ServiceException("以下运单号已存在，请检查：" + waybillList1);
        }

        //赋值退货数量excel导入默认退货数量为1
        for (JdBackDetails jdBackDetails : jdBackDetailsList) {
            jdBackDetails.setQuantity(BigDecimal.ONE);
        }

        List<String> productCodeString = jdBackDetailsList.stream().map(JdBackDetails::getProductCode).distinct().collect(Collectors.toList());
        List<String> list = productInfoService.listObject(ProductInfo::getCustomCode, q -> q.in(ProductInfo::getCustomCode, productCodeString));
        StringJoiner stringJoiner = new StringJoiner(",");
        if (list.size() < productCodeString.size()) {
            productCodeString.forEach(item -> {
                if (!list.contains(item)) {
                    stringJoiner.add(item);
                }
            });
            throw new ServiceException("物品编码不存在：" + stringJoiner);
        }


        // 按运单号分组
        Map<String, List<JdBackDetails>> byWaybillMap = jdBackDetailsList.stream()
                .collect(Collectors.groupingBy(JdBackDetails::getWaybill));

        List<JdBack> jdBackList = new ArrayList<>();
        byWaybillMap.forEach((k, v) -> {
            Long id = IdWorker.getId();

            JdBack jdBack = new JdBack();
            jdBack.setId(id);
            jdBack.setWaybill(k);
            jdBack.setWarehouseId(warehouseId);
            jdBack.setBatchFlag(batchFlag);
            jdBack.setType(2);//设置类型批量导入
            jdBack.setStatus(3);//设置状态待质检
            jdBackList.add(jdBack);

            v.forEach(item -> item.setJdBackId(id));

        });

        //创建待质检记录
        createJdBackQualityWait(jdBackDetailsList);

        //根据运单号生成物流信息
        //根据运单号分组
        List<LogisticsInfos> logisticsInfoList = new ArrayList<>();
        Map<String, List<JdBackDetails>> collect1s = jdBackDetailsList.stream().collect(Collectors.groupingBy(JdBackDetails::getWaybill));
        for (Map.Entry<String, List<JdBackDetails>> entry : collect1s.entrySet()) {
            JdBackDetails jdBackDetails = entry.getValue().get(0);
            LogisticsInfos logisticsInfo = new LogisticsInfos();
            logisticsInfo.setBusinessId(jdBackDetails.getJdBackId());
            logisticsInfo.setBusinessCode(jdBackDetails.getBackCode());
            logisticsInfo.setBusinessType(4);//设置类型为京东退货
            logisticsInfo.setCode(jdBackDetails.getWaybill());
            logisticsInfo.setInStockStatus(10);
            logisticsInfo.setLogisticsCompanyCode("jingdongkuaiyun");//物流公司编码
            logisticsInfo.setWarehouseId(warehouseId);
            logisticsInfoList.add(logisticsInfo);
        }
        logisticsInfosService.saveBatch(logisticsInfoList);

        saveBatch(jdBackList);
        jdBackDetailsService.saveBatch(jdBackDetailsList);
    }

}
