package com.zbkj.service.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import com.zbkj.common.config.CrmebConfig;
import com.zbkj.common.constants.SysConfigConstants;
import com.zbkj.common.enums.BcxBrokerageConfigBelongTypeEnum;
import com.zbkj.common.enums.ChangeTypeEnum;
import com.zbkj.common.exception.CrmebException;
import com.zbkj.common.model.bcx.BcxBrokerageConfig;
import com.zbkj.common.model.bcx.BcxBrokerageConfigRegion;
import com.zbkj.common.model.bcx.BcxRegion;
import com.zbkj.common.model.product.Product;
import com.zbkj.common.model.product.ProductAttrValue;
import com.zbkj.common.request.*;
import com.zbkj.common.response.BcxBrokerageConfigResponse;
import com.zbkj.common.response.BcxBrokerageLoadResponse;
import com.zbkj.common.response.PlatformProductListResponse;
import com.zbkj.common.result.CommonResultCode;
import com.zbkj.common.utils.IdGeneratorSnowflake;
import com.zbkj.service.dao.BcxBrokerageConfigDao;
import com.zbkj.service.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * description: 佣金绩效配置表 服务实现类
 * author : linchunpeng
 * date : 2023/8/3
 */
@Service
public class BcxBrokerageConfigServiceImpl extends ServiceImpl<BcxBrokerageConfigDao, BcxBrokerageConfig> implements BcxBrokerageConfigService {
    
    @Resource
    private BcxBrokerageConfigDao dao;

    @Autowired
    private CrmebConfig crmebConfig;
    @Autowired
    private SystemConfigService systemConfigService;
    @Autowired
    private BcxBrokerageConfigRegionService bcxBrokerageConfigRegionService;
    @Autowired
    private ProductService productService;
    @Autowired
    private ProductAttrValueService productAttrValueService;
    @Autowired
    private BcxRegionService bcxRegionService;
    @Autowired
    private IdGeneratorSnowflake snowflake;

    /**
     * description：查询佣金配置基础
     * author：linchunpeng
     * date：2023/8/7
     */
    @Override
    public BcxBrokerageLoadResponse load(BcxBrokerageLoadSearchRequest searchRequest) {
        BcxBrokerageLoadResponse response = new BcxBrokerageLoadResponse();
        if (searchRequest.getProductId() == null) {
            //查询默认配置
            response.setMaxBrokerage(Integer.parseInt(systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_PRODUCT_MAX_BROKERAGE)));
            response.setRetailStoreBrokerageFirstRatio(Integer.parseInt(systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_BROKERAGE_FIRST_RATIO)));
            response.setRetailStoreBrokerageSecondRatio(Integer.parseInt(systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_BROKERAGE_SECOND_RATIO)));
        } else {
            Product product = productService.getById(searchRequest.getProductId());
            if (product.getIsSub()) {
                //单独配置
                //查询商品配置
                response.setIsSub(1);
                response.setMaxBrokerage(product.getMaxBrokerage() != null ? product.getMaxBrokerage().intValue() : null);
                List<ProductAttrValue> skuList = productAttrValueService.getListByProductIdAndType(searchRequest.getProductId(), 0);
                if (CollectionUtil.isNotEmpty(skuList)) {
                    response.setRetailStoreBrokerageFirstRatio(skuList.get(0).getBrokerage());
                    response.setRetailStoreBrokerageSecondRatio(skuList.get(0).getBrokerageTwo());
                }
            } else {
                //默认配置
                response.setIsSub(0);
                response.setMaxBrokerage(Integer.parseInt(systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_PRODUCT_MAX_BROKERAGE)));
                response.setRetailStoreBrokerageFirstRatio(Integer.parseInt(systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_BROKERAGE_FIRST_RATIO)));
                response.setRetailStoreBrokerageSecondRatio(Integer.parseInt(systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_BROKERAGE_SECOND_RATIO)));
            }
        }
        //渠道佣金配置列表
        response.setConfigChannelList(this.getList(
                new BcxBrokerageConfigSearchRequest(searchRequest.getProductId(), BcxBrokerageConfigBelongTypeEnum.CHANNEL.getValue(), null)));
        //部门佣金配置列表
        response.setConfigDepartmentList(this.getList(
                new BcxBrokerageConfigSearchRequest(searchRequest.getProductId(), BcxBrokerageConfigBelongTypeEnum.DEPARTMENT.getValue(), null)));
        //部门成员佣金配置列表
        response.setConfigDepartmentMemberList(this.getList(
                new BcxBrokerageConfigSearchRequest(searchRequest.getProductId(), BcxBrokerageConfigBelongTypeEnum.DEPARTMENT_MEMBER.getValue(), null)));
        return response;
    }


    /**
     * description：查询佣金配置列表
     * author：linchunpeng
     * date：2023/8/7
     */
    @Override
    public List<BcxBrokerageConfigResponse> getList(BcxBrokerageConfigSearchRequest searchRequest) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("productId", searchRequest.getProductId());
        paramMap.put("regionCode", searchRequest.getRegionCode());
        if (searchRequest.getBelongType().intValue() == BcxBrokerageConfigBelongTypeEnum.CHANNEL.getValue().intValue()) {
            //渠道佣金配置
            return dao.selectChannelConfigList(paramMap);
        } else if (searchRequest.getBelongType().intValue() == BcxBrokerageConfigBelongTypeEnum.DEPARTMENT.getValue().intValue()) {
            //部门佣金配置
            return dao.selectDepartmentConfigList(paramMap);
        } else if (searchRequest.getBelongType().intValue() == BcxBrokerageConfigBelongTypeEnum.DEPARTMENT_MEMBER.getValue().intValue()) {
            //部门成员佣金配置
            return dao.selectDepartmentMemberConfigList(paramMap);
        }
        return null;
    }

    /**
     * description：佣金绩效配置信息保存
     * author：linchunpeng
     * date：2023/8/4
     */
    @Override
    @Transactional
    public Boolean saveBcxBrokerageConfig(BcxBrokerageConfigRequest request) {
        //验证商品最大分佣比例 一级佣金 二级佣金参数
        validRetailStoreBrokerageRatio(request);
        //验证渠道商配置
        validConfigDetail(request.getConfigChannelList());
        //验证部门配置
        validConfigDetail(request.getConfigDepartmentList());
        //验证部门成员商配置
        validConfigDetail(request.getConfigDepartmentMemberList());
        //保存商品最大分佣比例 一级佣金 二级佣金
        if (CollectionUtil.isEmpty(request.getProductIdList())) {
            //设置默认
            systemConfigService.updateOrSaveValueByName(SysConfigConstants.RETAIL_STORE_PRODUCT_MAX_BROKERAGE, request.getMaxBrokerage().toString());
            systemConfigService.updateOrSaveValueByName(SysConfigConstants.RETAIL_STORE_BROKERAGE_FIRST_RATIO, request.getRetailStoreBrokerageFirstRatio().toString());
            systemConfigService.updateOrSaveValueByName(SysConfigConstants.RETAIL_STORE_BROKERAGE_SECOND_RATIO, request.getRetailStoreBrokerageSecondRatio().toString());
        } else {
            //设置商品
            if (request.getIsSub() == null) {
                throw new CrmebException(CommonResultCode.ERROR.setMessage("佣金计算方式 不能为空"));
            }
            for (Integer productId : request.getProductIdList()) {
                Product product = productService.getById(productId);
                if (product == null) {
                    throw new CrmebException(CommonResultCode.ERROR.setMessage("要设置的商品不存在"));
                }
                if (product.getIsBrokerage() == null || product.getIsBrokerage() == 0) {
                    throw new CrmebException(CommonResultCode.ERROR.setMessage("要设置的商品不是分销商品，请先开启成为分销商品再设置佣金配置"));
                }
                //设置商品最大分佣比例
                product.setMaxBrokerage(new BigDecimal(request.getMaxBrokerage()));
                //设置分佣方式
                product.setIsSub(request.getIsSub() == 1);
                productService.updateById(product);
                if (product.getIsSub()) {
                    //验证一级佣金 二级佣金参数
                    validRetailStoreBrokerageRatio(request);
                    //设置单独佣金配置
                    List<ProductAttrValue> skuList = productAttrValueService.getListByProductIdAndType(product.getId(), 0);
                    if (CollectionUtil.isEmpty(skuList)) {
                        throw new CrmebException(CommonResultCode.ERROR.setMessage("要设置的商品sku不存在"));
                    }
                    //设置sku佣金比例
                    for (ProductAttrValue productAttrValue : skuList) {
                        productAttrValue.setBrokerage(request.getRetailStoreBrokerageFirstRatio());
                        productAttrValue.setBrokerageTwo(request.getRetailStoreBrokerageSecondRatio());
                    }
                    productAttrValueService.updateBatchById(skuList);
                }
            }
        }

        //清掉渠道/部门/部门成员的佣金设置
        UpdateWrapper<BcxBrokerageConfig> wrapper = Wrappers.update();
        if (CollectionUtil.isEmpty(request.getProductIdList())) {
            wrapper.isNull("product_id");
        } else {
            wrapper.in("product_id", request.getProductIdList());
        }
        dao.delete(wrapper);

        if (CollectionUtil.isNotEmpty(request.getProductIdList()) && request.getIsSub() != null && request.getIsSub() == 0) {
            //设置商品 && 设置默认佣金配置，那就不用设置明细了
            return true;
        }

        //设置配置列表
        List<BcxBrokerageConfig> list = new ArrayList<>();
        List<BcxBrokerageConfigRegion> regionList = new ArrayList<>();
        Date now = new Date();
        if (CollectionUtil.isEmpty(request.getProductIdList())) {
            //设置渠道配置列表
            setConfigList(null, request.getConfigChannelList(), BcxBrokerageConfigBelongTypeEnum.CHANNEL, list, regionList, now);
            //设置部门配置列表
            setConfigList(null, request.getConfigDepartmentList(), BcxBrokerageConfigBelongTypeEnum.DEPARTMENT, list, regionList, now);
            //设置部门成员配置列表
            setConfigList(null, request.getConfigDepartmentMemberList(), BcxBrokerageConfigBelongTypeEnum.DEPARTMENT_MEMBER, list, regionList, now);
        } else {
            for (Integer productId : request.getProductIdList()) {
                //设置渠道配置列表
                setConfigList(productId, request.getConfigChannelList(), BcxBrokerageConfigBelongTypeEnum.CHANNEL, list, regionList, now);
                //设置部门配置列表
                setConfigList(productId, request.getConfigDepartmentList(), BcxBrokerageConfigBelongTypeEnum.DEPARTMENT, list, regionList, now);
                //设置部门成员配置列表
                setConfigList(productId, request.getConfigDepartmentMemberList(), BcxBrokerageConfigBelongTypeEnum.DEPARTMENT_MEMBER, list, regionList, now);
            }
        }

        //保存渠道/部门/部门成员佣金设置
        this.saveBatch(list);
        bcxBrokerageConfigRegionService.saveBatch(regionList);
        return true;
    }

    private void validRetailStoreBrokerageRatio(BcxBrokerageConfigRequest request) {
        if (request.getMaxBrokerage() == null) {
            throw new CrmebException("商品最大分佣比例不能为空");
        }
        if (request.getMaxBrokerage() < 0 || request.getMaxBrokerage() > 100) {
            throw new CrmebException("商品最大分佣比例请在0-100中选择");
        }
        // 返佣比例之和+起来不能超过100%
        if (request.getRetailStoreBrokerageFirstRatio() == null) {
            throw new CrmebException("分销一级返佣比例不能为空");
        }
        if (request.getRetailStoreBrokerageSecondRatio() == null) {
            throw new CrmebException("分销二级返佣比例不能为空");
        }
        int ration = request.getRetailStoreBrokerageFirstRatio() + request.getRetailStoreBrokerageSecondRatio();
        if (ration > crmebConfig.getRetailStoreBrokerageRatio() || ration < 0) {
            throw new CrmebException(StrUtil.format("一级、二级返佣比例之和范围为 0 ~ {}", crmebConfig.getRetailStoreBrokerageRatio()));
        }
        if (ration > request.getMaxBrokerage()) {
            throw new CrmebException("一级、二级返佣比例之和大于商品最大分佣比例");
        }
    }


    /**
     * description：验证配置明细，是否出现重复区域配置
     * author：linchunpeng
     * date：2023/10/24
     */
    private void validConfigDetail(List<BcxBrokerageConfigDetailRequest> configDetailList) {
       if (CollectionUtil.isNotEmpty(configDetailList)) {
           Set<String> regionSet = new HashSet<>();
           Map<Long, List<String>> belongRegionListMap = new HashMap<>();
           for (BcxBrokerageConfigDetailRequest configDetail : configDetailList) {
               List<String> regionList;
               if (belongRegionListMap.get(configDetail.getBelongId()) == null) {
                   regionList = new ArrayList<>();
               } else {
                   regionList = belongRegionListMap.get(configDetail.getBelongId());
               }
               //验证同一个归属，区域是否已经配置过，如果没有，则添加到列表，如果已有，则跑出异常
               validDetailRegionAndAdd(configDetail, regionList);
               belongRegionListMap.put(configDetail.getBelongId(), regionList);

               //验证是否存在全国配置
               List<String> regionConfigList = belongRegionListMap.get(configDetail.getBelongId());
               if (CollectionUtil.isNotEmpty(regionConfigList) && regionConfigList.contains("all") && regionConfigList.size() > 1) {
                   throw new CrmebException(String.format("【%s】配置中，已经配置了【全国】，就不能配置其他区域了，请重新配置后提交",
                           configDetail.getBelongName()));
               }
//               if (configDetail.getChannelType() != null && configDetail.getChannelType().intValue() == ChangeTypeEnum.REGION.getValue().intValue()) {
//                   //区域渠道，需要判断区域是否已经配置过
//                   for (String region : configDetail.getRegionCodeList()) {
//                       if (!regionSet.add(region)) {
//                           BcxRegion bcxRegion = bcxRegionService.findByCode(region);
//                           throw new CrmebException(String.format("【%s】配置中，区域：【%s】出现重复，请重新配置后提交",
//                                   configDetail.getBelongName(), bcxRegion == null ? "全国" : bcxRegion.getRegionName()));
//                       }
//                   }
//               }
           }
       }
    }

    /**
     * description：验证区域是否配置过，如果没有，则添加到列表，如果已有，则跑出异常
     * author：linchunpeng
     * date：2023/10/24
     */
    private void validDetailRegionAndAdd(BcxBrokerageConfigDetailRequest configDetail, List<String> regionList) {
        for (String region : configDetail.getRegionCodeList()) {
            if (regionList.contains(region)) {
                BcxRegion bcxRegion = bcxRegionService.findByCode(region);
                throw new CrmebException(String.format("【%s】配置中，区域：【%s】出现重复，请重新配置后提交",
                        configDetail.getBelongName(), bcxRegion == null ? "全国" : bcxRegion.getRegionName()));
            }
            regionList.add(region);
        }
    }

    /**
     * description：设置配置列表
     * author：linchunpeng
     * date：2023/8/4
     */
    private void setConfigList(Integer productId, List<BcxBrokerageConfigDetailRequest> configList, BcxBrokerageConfigBelongTypeEnum belongTypeEnum,
                               List<BcxBrokerageConfig> list, List<BcxBrokerageConfigRegion> regionList, Date now) {
        if (CollectionUtil.isNotEmpty(configList)) {
            for (BcxBrokerageConfigDetailRequest detailRequest : configList) {
                BcxBrokerageConfig config = new BcxBrokerageConfig();
                config.setId(snowflake.snowflakeId());
                config.setProductId(productId);
                config.setBelongId(detailRequest.getBelongId());
                config.setBelongType(belongTypeEnum.getValue());
                config.setChannelType(detailRequest.getChannelType());
                config.setType(detailRequest.getType());
                config.setRatio(detailRequest.getRatio());
                config.setServiceRatio(detailRequest.getServiceRatio());
                config.setCalculateRatio(detailRequest.getCalculateRatio());
                config.setStatus(1);
                config.setCreateTime(now);
                config.setUpdateTime(now);
                list.add(config);

                if (CollectionUtil.isNotEmpty(detailRequest.getRegionCodeList())) {
                    Optional<String> all = detailRequest.getRegionCodeList().stream().filter(regionCode -> regionCode.equals("all")).findFirst();
                    if (all.isPresent()) {
                        BcxBrokerageConfigRegion region = new BcxBrokerageConfigRegion();
                        region.setId(snowflake.snowflakeId());
                        region.setBrokerageConfigId(config.getId());
                        region.setRegionCode(all.get());
                        region.setCreateTime(now);
                        region.setUpdateTime(now);
                        regionList.add(region);
                    } else {
                        for (String regionCode : detailRequest.getRegionCodeList()) {
                            BcxBrokerageConfigRegion region = new BcxBrokerageConfigRegion();
                            region.setId(snowflake.snowflakeId());
                            region.setBrokerageConfigId(config.getId());
                            region.setRegionCode(regionCode);
                            region.setCreateTime(now);
                            region.setUpdateTime(now);
                            regionList.add(region);
                        }
                    }
                }
            }
        }
    }

    /**
     * description：设置商品是否开启分销
     * author：linchunpeng
     * date：2023/8/9
     */
    @Override
    @Transactional
    public boolean setProductBrokerage(BcxSetProductBrokerageRequest request) {
        for (Integer productId : request.getProductIdList()) {
            Product product = productService.getById(productId);
            if (product == null) {
                throw new CrmebException(CommonResultCode.ERROR.setMessage("要设置的商品不存在"));
            }
            //由于众邦分销流程，没有用这个开关，所以设置佣金
            if (request.getIsBrokerage() == 0) {
                //关闭分销，需要把sku的分佣比例设置0
                List<ProductAttrValue> skuList = productAttrValueService.getListByProductIdAndType(product.getId(), 0);
                if (CollectionUtil.isNotEmpty(skuList)) {
                    for (ProductAttrValue productAttrValue : skuList) {
                        productAttrValue.setBrokerage(0);
                        productAttrValue.setBrokerageTwo(0);
                    }
                    productAttrValueService.updateBatchById(skuList);
                }
                //同时也要修改是否单独分佣，不然会走默认配置
                product.setIsSub(true);
            }
            product.setIsBrokerage(request.getIsBrokerage());
            productService.updateById(product);
        }
        return true;
    }

    /**
     * description：获取分销商品列表
     * author：linchunpeng
     * date：2023/8/9
     */
    @Override
    public PageInfo<PlatformProductListResponse> getProductList(ProductSearchRequest searchRequest, PageParamRequest pageParamRequest) {
        PageInfo<PlatformProductListResponse> productPage = productService.getPlatformPageList(searchRequest, pageParamRequest);
        if (CollectionUtil.isNotEmpty(productPage.getList())) {
            for (PlatformProductListResponse response : productPage.getList()) {
                BcxBrokerageLoadSearchRequest request = new BcxBrokerageLoadSearchRequest();
                request.setProductId(response.getId());
                BcxBrokerageLoadResponse loadResponse = this.load(request);
                response.setBrokerageConfig("一级返佣：".concat(loadResponse.getRetailStoreBrokerageFirstRatio().toString())
                        .concat("\r\n二级返佣").concat(loadResponse.getRetailStoreBrokerageSecondRatio().toString()));
            }
        }
        return productPage;
    }
}