package com.jwipc.sys.logic.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.jwipc.api.constant.RestCode;
import com.jwipc.api.dto.ApiResult;
import com.jwipc.sys.convert.ProductApiConvert;
import com.jwipc.sys.dto.*;
import com.jwipc.sys.entity.ProductInfo;
import com.jwipc.sys.entity.ProductStock;
import com.jwipc.sys.logic.*;
import com.jwipc.sys.model.query.ProductGroupQuery;
import com.jwipc.sys.model.query.PurchaseGroupQuery;
import com.jwipc.sys.service.IProductInfoService;
import com.jwipc.sys.service.IProductInfoStockService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.baomidou.dynamic.datasource.support.DdConstants.SLAVE;

/**
 * @author shenyang.ou
 * @date 2024/3/18 12:08
 * @desc
 */
@Service
@RequiredArgsConstructor
@DS(SLAVE)
public class ProductApiLogicImpl implements ProductApiLogic {
    private final ProductLogic productLogic;

    private final IProductInfoService productInfoService;
    private final IProductInfoStockService productInfoStockService;
    private final ProductApiConvert productApiConvert;
    private final FactoryLogic factoryLogic;
    private final PurchaseGroupLogic purchaseGroupLogic;
    private final ProductGroupLogic productGroupLogic;
    /**
     * 物料保存或更新
     *
     * @param param 接口参数
     * @return 结果
     */
    @Override
    @Transactional
    public ApiResult saveOrUpdate(ProductItemDTO param) {
        if (ObjectUtil.isEmpty(param)){
            return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("参数不能为空").build();
        }
        List<ProductApiDTO> productApiDTOList = param.getProductApiDTOList();
        try {
            productApiDTOList = productApiDTOList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(()
                    -> new TreeSet<>(Comparator.comparing(o -> o.getMaterialCode() + ";" + o.getFactoryCode()))), ArrayList::new));
            List<ProductInfo> needSaveOrUpdate = new ArrayList<>();
            //工厂
            final List<FactoryDTO> all = factoryLogic.findByAllList();
            final Map<String, FactoryDTO> factoryCache = all.stream()
                    .collect(Collectors.toMap(FactoryDTO::getFactory, a -> a));
            final Set<String> factoryCodes = factoryCache.keySet();
            //采购组
            final List<PurchaseGroupDTO> purchaseGroupDTOS = purchaseGroupLogic.listAll(new PurchaseGroupQuery());
            final Map<String, PurchaseGroupDTO> purchaseGroupCache = purchaseGroupDTOS.stream()
                    .collect(Collectors.toMap(PurchaseGroupDTO::getPurchaseGroupCode, a -> a));
            final Set<String> purchaseGroupCodes = purchaseGroupCache.keySet();
            //物料组
            final List<ProductGroupDTO> productGroupDTOS = productGroupLogic.listAll(new ProductGroupQuery());
            final Map<String, ProductGroupDTO> productGroupCache = productGroupDTOS.stream()
                    .collect(Collectors.toMap(ProductGroupDTO::getMaterialGroup, a -> a));
            final Set<String> productGroupCodes = productGroupCache.keySet();
            for (ProductApiDTO productApiDTO : productApiDTOList){
                if (StringUtils.isEmpty(productApiDTO.getMaterialCode())){
                    return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入物料编码").build();
                }
                if (StringUtils.isEmpty(productApiDTO.getMaterialName())){
                    return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入物料名称").build();
                }
                if (StringUtils.isEmpty(productApiDTO.getFactoryCode())){
                    return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入工厂").build();
                }
                if (!factoryCodes.contains(productApiDTO.getFactoryCode())) {
                    return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message(StrUtil.format("工厂：{}在系统中不存在",productApiDTO.getFactoryCode())).build();
                }
//                if (StringUtils.isEmpty(productApiDTO.getMaterialPurchaseGroup())){
//                    return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入采购组").build();
//                }
//                if (!purchaseGroupCodes.contains(productApiDTO.getMaterialPurchaseGroup())) {
//                    return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message(StrUtil.format("采购组：{}在系统中不存在",productApiDTO.getMaterialPurchaseGroup())).build();
//                }
                if (StringUtils.isEmpty(productApiDTO.getMaterialGroupCode())){
                    return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入物料组").build();
                }
                if (!productGroupCodes.contains(productApiDTO.getMaterialGroupCode())) {
                    return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message(StrUtil.format("物料组：{}在系统中不存在",productApiDTO.getMaterialGroupCode())).build();
                }
                ProductInfo productInfo = productApiConvert.productApiDTO2Entity(productApiDTO);
                ProductGroupDTO productGroupDTO = productGroupCache.get(productApiDTO.getMaterialGroupCode());
                productInfo.setMaterialGroupName(productGroupDTO.getMaterialDesc());
                //分子
                BigDecimal umrez = StringUtils.isNotEmpty(productApiDTO.getBasisUnitConvertMolecules())?new BigDecimal(productApiDTO.getBasisUnitConvertMolecules()):new BigDecimal(1);
                //分母
                BigDecimal umren = StringUtils.isNotEmpty(productApiDTO.getBasisUnitConvertDenominator())?new BigDecimal(productApiDTO.getBasisUnitConvertDenominator()):new BigDecimal(1);
                if(umrez.compareTo(BigDecimal.ZERO)==0||umren.compareTo(BigDecimal.ZERO)==0){
                    productInfo.setUnitChange(new BigDecimal("1").doubleValue());
                }else {
                    //转换比例=分子/分母
                    productInfo.setUnitChange(umrez.divide(umren).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
                }

                //这里因为分片算法，无法批量保存更新，且更新必须带上分片键
                ProductInfoDTO productInfoDTO = productLogic.getByMaterialCodeAndFactoryCode(productApiDTO.getMaterialCode(),productApiDTO.getFactoryCode());
                if (ObjectUtil.isNotNull(productInfoDTO)){
                    productInfo.setId(productInfoDTO.getId());
                    productInfo.setLastUpdateTime(LocalDateTime.now());
                    productInfoService.update(productInfo, Wrappers.lambdaQuery(ProductInfo.class).eq(ProductInfo::getId,productInfoDTO.getId()).eq(ProductInfo::getFactoryCode,productInfoDTO.getFactoryCode()));
                }else {
                    productInfo.setCreateTime(LocalDateTime.now());
                    productInfoService.save(productInfo);
                }
                needSaveOrUpdate.add(productInfo);
            }
//            if (CollectionUtil.isNotEmpty(needSaveOrUpdate)){
//                productInfoService.saveOrUpdateBatch(needSaveOrUpdate);
//            }
        }catch (Exception e){
            e.printStackTrace();
            return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message(e.getMessage()).build();
        }
        return ApiResult.builder().code(RestCode.SAP_SUCCESS.getCode()).message("成功").build();
    }



    /**
     * 物料保存或更新
     *
     * @param param 接口参数
     * @return 结果
     */
    @Override
    @Transactional
    public ApiResult mesSaveOrUpdate(ProductStockItemDTO param) {
        if (ObjectUtil.isEmpty(param)){
            return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("参数不能为空").build();
        }
        List<ProductStockApiDTO> productStockApiDTOList = param.getProductStockApiDTOList();
        try {
            for (ProductStockApiDTO productStockApiDTO : productStockApiDTOList){
                if (StringUtils.isEmpty(productStockApiDTO.getMaterialCode())){
                    return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入物料编码").build();
                }
//                if (StringUtils.isEmpty(productStockApiDTO.getStockLocation())){
//                    return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message("请传入MES储位").build();
//                }
            }
                //保存逻辑
                Map<String, String> stockLocationMap = new HashMap<>();
                for (ProductStockApiDTO dto : productStockApiDTOList) {

                    String materialCode = dto.getMaterialCode();
                    String stockLocation = dto.getStockLocation();

                    if (stockLocationMap.containsKey(materialCode)) {
                        // 如果已存在该 materialCode，则将 stockLocation 追加到原字符串后面
                        String existingLocations = stockLocationMap.get(materialCode);
                        if(Objects.nonNull(existingLocations) && StringUtils.isNotBlank(existingLocations) && Objects.nonNull(stockLocation) && StringUtils.isNotBlank(stockLocation)){
                            stockLocationMap.put(materialCode, existingLocations + "," + stockLocation);
                        }else if(Objects.nonNull(existingLocations) && StringUtils.isNotBlank(existingLocations)&& (Objects.isNull(stockLocation) || stockLocation.isEmpty())){
                            stockLocationMap.put(materialCode, existingLocations  + stockLocation);
                        }else if((Objects.isNull(existingLocations) || existingLocations.isEmpty()) && Objects.nonNull(stockLocation) && StringUtils.isNotBlank(stockLocation)){
                            stockLocationMap.put(materialCode, existingLocations  + stockLocation);
                        }

                    } else {
                        // 如果不存在该 materialCode，则直接将 stockLocation 存入 Map
                        stockLocationMap.put(materialCode, stockLocation);
                    }
                }

                List<ProductStockApiDTO> newProductStockApiDTOList = new ArrayList<>();
                for (Map.Entry<String, String> entry : stockLocationMap.entrySet()) {
                    String materialCode = entry.getKey();
                    String stockLocations = entry.getValue();

                    ProductStockApiDTO newDTO = new ProductStockApiDTO();
                    newDTO.setMaterialCode(materialCode);
                    newDTO.setStockLocation(stockLocations);
                    List<ProductStock> productStockss = productInfoStockService.list();
                    for (ProductStock product : productStockss) {
                        if (product.getMaterialCode().equals(materialCode)) {
                            // 找到了与当前 materialCode 相等的数据
                            // 更新 product 的相关字段值
                            newDTO.setId(product.getId());
                            break; // 如果只需要更新第一个匹配的数据，可以添加 break 结束循环
                        }
                    }
                    newProductStockApiDTOList.add(newDTO);
                }
                List<ProductStock> productStocks = productApiConvert.productStockApiDTO2Entities(newProductStockApiDTOList);
                productInfoStockService.saveOrUpdateBatch(productStocks);
        }catch (Exception e){
            e.printStackTrace();
            return ApiResult.builder().code(RestCode.SAP_ERROR.getCode()).message(e.getMessage()).build();
        }
        return ApiResult.builder().code(RestCode.MES_SUCCESS.getCode()).message("成功").build();
    }
}
