package com.ruoyi.logistics.service.impl;

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

import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.logistics.constant.JDDictConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.logistics.mapper.SysDeptRateMapper;
import com.ruoyi.logistics.domain.SysDeptRate;
import com.ruoyi.logistics.service.ISysDeptRateService;

/**
 * 供应商费率配置Service业务层处理
 * 
 * @author RuiJing
 * @date 2026-03-17
 */
@Service
public class SysDeptRateServiceImpl implements ISysDeptRateService 
{
    @Autowired
    private SysDeptRateMapper sysDeptRateMapper;

    /**
     * 查询供应商费率配置
     * 
     * @param rateId 供应商费率配置主键
     * @return 供应商费率配置
     */
    @Override
    public SysDeptRate selectSysDeptRateByRateId(Long rateId)
    {
        return sysDeptRateMapper.selectSysDeptRateByRateId(rateId);
    }

    /**
     * 查询供应商费率配置列表
     * 
     * @param sysDeptRate 供应商费率配置
     * @return 供应商费率配置
     */
    @Override
    public List<SysDeptRate> selectSysDeptRateList(SysDeptRate sysDeptRate)
    {
        List<SysDeptRate> sysDeptRates = sysDeptRateMapper.selectSysDeptRateList(sysDeptRate);
            
        // 根据 companyType 和 productType 分组后，再根据 intervalBegins 正序排列
        return sysDeptRates.stream()
            .sorted(
                Comparator.comparing(SysDeptRate::getCompanyType)
                    .thenComparing(SysDeptRate::getProductType)
                    .thenComparing(SysDeptRate::getIntervalBegins)
            )
            .collect(Collectors.toList());
    }

    /**
     * 新增供应商费率配置
     * 
     * @param sysDeptRates 供应商费率配置
     * @return 结果
     */
    @Override
    public int insertSysDeptRate(List<SysDeptRate> sysDeptRates, Long deptId)
    {
//        if (sysDeptRates == null || sysDeptRates.isEmpty()) {
//            throw new ServiceException("批量插入的费率配置列表不能为空");
//        }

        // 按 companyType + productType 分组校验区间重叠
        Map<String, List<SysDeptRate>> groupedRates = new HashMap<>();

        for (SysDeptRate rate : sysDeptRates) {
            // 构建分组 key: companyType_productType
            String groupKey = rate.getCompanyType() + "_" + rate.getProductType();
            groupedRates.computeIfAbsent(groupKey, k -> new ArrayList<>()).add(rate);
        }

        // 对每个分组进行区间重叠校验
        for (Map.Entry<String, List<SysDeptRate>> entry : groupedRates.entrySet()) {
            List<SysDeptRate> rates = entry.getValue();
            validateIntervalOverlap(rates);
        }

        // 设置创建时间并批量插入
        sysDeptRateMapper.deleteSysDeptRateByDeptId(deptId);
        for (SysDeptRate rate : sysDeptRates) {
            rate.setCreateTime(DateUtils.getNowDate());
            rate.setCreateBy(SecurityUtils.getUsername());
            rate.setUserId(SecurityUtils.getUserId());
            rate.setDeptId(deptId);
            sysDeptRateMapper.insertSysDeptRate(rate);
        }

        if (sysDeptRates.size() == 0) {
            return 1;
        }

        return sysDeptRates.size();
    }

    /**
     * 修改供应商费率配置
     * 
     * @param sysDeptRate 供应商费率配置
     * @return 结果
     */
    @Override
    public int updateSysDeptRate(SysDeptRate sysDeptRate)
    {
        sysDeptRate.setUpdateTime(DateUtils.getNowDate());
        return sysDeptRateMapper.updateSysDeptRate(sysDeptRate);
    }

    /**
     * 批量删除供应商费率配置
     * 
     * @param rateIds 需要删除的供应商费率配置主键
     * @return 结果
     */
    @Override
    public int deleteSysDeptRateByRateIds(Long[] rateIds)
    {
        return sysDeptRateMapper.deleteSysDeptRateByRateIds(rateIds);
    }

    /**
     * 删除供应商费率配置信息
     * 
     * @param rateId 供应商费率配置主键
     * @return 结果
     */
    @Override
    public int deleteSysDeptRateByRateId(Long rateId)
    {
        return sysDeptRateMapper.deleteSysDeptRateByRateId(rateId);
    }
    
    /**
     * 校验同一物流公司和产品类型的区间是否重叠
     * 区间规则：(intervalBegins, intervalEnds] 左开右闭
     * 
     * @param rates 费率配置列表
     * @throws ServiceException 如果存在区间重叠
     */
    private static void validateIntervalOverlap(List<SysDeptRate> rates) {
        if (rates == null || rates.isEmpty()) {
            return;
        }

        // 按起始金额排序，便于连续性校验
        rates.sort(Comparator.comparing(SysDeptRate::getIntervalBegins));

        String companyType = rates.get(0).getCompanyType();
        String productType = rates.get(0).getProductType();
        String companyName = getCompanyName(companyType);
        String productName = getProductName(productType);

        // 单个规则的校验
        if (rates.size() == 1) {
            SysDeptRate rate = rates.get(0);
            Long begins = rate.getIntervalBegins();
            Long ends = rate.getIntervalEnds();

            if (begins == null || begins != 0) {
                throw new ServiceException(String.format(
                        "%s、%s的第一条规则起始金额必须为0", companyName, productName));
            }
            // 检查区间有效性
            if (begins == null || ends == null) {
                throw new ServiceException("区间开始和结束值不能为空");
            }

            if (begins >= ends) {
                throw new ServiceException(String.format(
                        "%s、%s配置的区间开始值必须小于结束值", companyName, productName));
            }

            if (rate.getRate() == null || rate.getRate().compareTo(new BigDecimal("0")) == 0) {
                throw new ServiceException(String.format(
                        "%s、%s的费率不能为0", companyName, productName));
            }
            return;
        }

        // 多条规则的校验
        // 1. 第一条起始金额必须为0
        SysDeptRate firstRate = rates.get(0);
        if (firstRate.getIntervalBegins() == null || firstRate.getIntervalBegins() != 0) {
            throw new ServiceException(String.format(
                    "%s、%s的第一条规则起始金额必须为0", companyName, productName));
        }

        // 2. 校验每条规则的有效性
        for (int i = 0; i < rates.size(); i++) {
            SysDeptRate rate = rates.get(i);
            Long begins = rate.getIntervalBegins();
            Long ends = rate.getIntervalEnds();

            if (begins == null || ends == null) {
                throw new ServiceException(String.format(
                        "%s、%s第%d条规则的区间开始和结束值不能为空", companyName, productName, i + 1));
            }

            if (begins >= ends) {
                throw new ServiceException(String.format(
                        "%s、%s第%d条规则的区间开始值必须小于结束值", companyName, productName, i + 1));
            }

            if (rate.getRate() == null || rate.getRate().compareTo(new BigDecimal("0")) == 0) {
                throw new ServiceException(String.format(
                        "%s、%s第%d条规则的费率不能为0", companyName, productName, i + 1));
            }
        }

        // 3. 校验连续性：当前行的起始金额必须等于上一行的结束金额
        for (int i = 1; i < rates.size(); i++) {
            SysDeptRate prevRate = rates.get(i - 1);
            SysDeptRate currRate = rates.get(i);

            if (!currRate.getIntervalBegins().equals(prevRate.getIntervalEnds())) {
                throw new ServiceException(String.format(
                        "%s、%s的规则不连续：第%d条规则结束金额为%d，第%d条规则起始金额为%d，必须相等",
                        companyName, productName,
                        i, prevRate.getIntervalEnds(),
                        i + 1, currRate.getIntervalBegins()));
            }
        }

        // 4. 校验区间重叠（虽然连续性校验已经保证了不重叠，但保留此校验作为双重保障）
        for (int i = 0; i < rates.size(); i++) {
            for (int j = i + 1; j < rates.size(); j++) {
                SysDeptRate rate1 = rates.get(i);
                SysDeptRate rate2 = rates.get(j);

                Long begins1 = rate1.getIntervalBegins();
                Long ends1 = rate1.getIntervalEnds();
                Long begins2 = rate2.getIntervalBegins();
                Long ends2 = rate2.getIntervalEnds();

                // 判断两个区间是否重叠
                // 区间 1: (begins1, ends1]
                // 区间 2: (begins2, ends2]
                // 不重叠的条件：ends1 <= begins2 或 ends2 <= begins1
                // 重叠的条件：!(ends1 <= begins2 || ends2 <= begins1)
                boolean isOverlap = !(ends1 <= begins2 || ends2 <= begins1);

                if (isOverlap) {
                    throw new ServiceException(String.format(
                            "%s、%s的区间配置存在重叠：第%d条规则(%d,%d] 与第%d条规则(%d,%d]",
                            companyName, productName,
                            i + 1, begins1, ends1,
                            j + 1, begins2, ends2));
                }
            }
        }

        // 5. 校验费率递减：起始金额小的区间，费率应该更大或相等
        for (int i = 0; i < rates.size() - 1; i++) {
            SysDeptRate currentRate = rates.get(i);
            SysDeptRate nextRate = rates.get(i + 1);

            if (currentRate.getRate().compareTo(nextRate.getRate()) < 0) {
                throw new ServiceException(String.format(
                        "%s、%s的费率配置有误：第%d条规则费率%.2f应大于等于第%d条规则费率%.2f",
                        companyName, productName,
                        i + 1, currentRate.getRate(),
                        i + 2, nextRate.getRate()));
            }
        }
    }

    private static String getCompanyName(String companyType) {
        if (companyType == null) {
            return null;
        }
        if (companyType.equals("1")) {
            return "京东";
        }
        if (companyType.equals("2")) {
            return "顺丰";
        }
        return null;
    }

    private static String getProductName(String productType) {
        if (productType == null) {
            return null;
        }
        if (productType.equals(JDDictConstants.PRODUCT_CODE_ED_M_0001)) {
            return "京东标快";
        }
        if (productType.equals(JDDictConstants.PRODUCT_CODE_ED_M_0002)) {
            return "京东特快";
        }
        if (productType.equals(JDDictConstants.PRODUCT_CODE_FR_M_0004)) {
            return "特快重货";
        }
        return null;
    }
}
