package com.ruoyi.bst.suit.service.impl;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;

import com.ruoyi.common.utils.MathUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ruoyi.bst.suit.domain.SuitQuery;
import com.ruoyi.bst.suit.domain.SuitVO;
import com.ruoyi.bst.suit.domain.enums.SuitRidingRule;
import com.ruoyi.bst.suit.domain.vo.SuitIntervalFeeRule;
import com.ruoyi.bst.suit.domain.vo.SuitStartFeeRule;
import com.ruoyi.bst.suit.mapper.SuitMapper;
import com.ruoyi.bst.suit.service.SuitValidator;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.collection.CollectionUtils;

@Service
public class SuitValidatorImpl implements SuitValidator {

    @Autowired
    private SuitMapper suitMapper;

    /**
     * 当前用户是否可以编辑
     *
     * @param id
     * @return
     */
    @Override
    public boolean canEdit(Long id) {
        return this.canOperate(Arrays.asList(id));
    }

    /**
     * 当前用户是否可以删除
     *
     * @param ids@return
     */
    @Override
    public boolean canDelete(List<Long> ids) {
        return this.canOperate(ids);
    }

    private boolean canOperate(List<Long> ids) {
        if (CollectionUtils.isEmptyElement(ids)) {
            return false;
        }
        SuitQuery query = new SuitQuery();
        query.setIds(ids);
        query.setScope(true);
        List<Long> suitIds = suitMapper.selectIdList(query);
        return new HashSet<>(suitIds).containsAll(ids);
    }

    /**
     * 校验收费规则
     */
    @Override
    public void validate(SuitVO suit) {
        ServiceUtil.assertion(suit == null, "套餐不能为空");

        // 收费规则
        if (SuitRidingRule.START_FEE.getCode().equals(suit.getRidingRule())) {
            SuitStartFeeRule startRule = suit.getStartRule();
            ServiceUtil.assertion(startRule == null, "收费规则不能为空");
            ServiceUtil.assertion(startRule.getStartingTime() == null, "起步时长不能为空");
            ServiceUtil.assertion(startRule.getStartingPrice() == null, "起步价不能为空");
            ServiceUtil.assertion(startRule.getTimeoutTime() == null, "超时时长不能为空");
            ServiceUtil.assertion(startRule.getTimeoutPrice() == null, "超时价格不能为空");
            ServiceUtil.assertion(startRule.getStartingPrice().compareTo(BigDecimal.ZERO) <= 0, "起步价不能小于或等于0");
            ServiceUtil.assertion(startRule.getTimeoutPrice().compareTo(BigDecimal.ZERO) <= 0, "超时价格不能小于或等于0");
            ServiceUtil.assertion(startRule.getStartingTime() <= 0, "起步时长不能小于或等于0");
            ServiceUtil.assertion(startRule.getTimeoutTime() <= 0, "超时时长不能小于或等于0");
        } else if (SuitRidingRule.INTERVAL_FEE.getCode().equals(suit.getRidingRule())) {
            List<SuitIntervalFeeRule> intervalRules = suit.getIntervalRule();
            ServiceUtil.assertion(CollectionUtils.isEmptyElement(intervalRules), "收费规则不能为空");
            for (int i = 0; i < intervalRules.size(); i++) {
                SuitIntervalFeeRule rule = intervalRules.get(i);
                try {
                    ServiceUtil.assertion(rule.getStart() == null, "区间开始时间不能为空");
                    ServiceUtil.assertion(rule.getEachUnit() == null, "计费间隔不能为空");
                    ServiceUtil.assertion(rule.getFee() == null, "费用不能为空");
                    ServiceUtil.assertion(rule.getStart() < 0, "区间开始时间不能小于0");
                    ServiceUtil.assertion(rule.getEachUnit() <= 0, "计费间隔必须大于0");
                    ServiceUtil.assertion(rule.getFee().compareTo(BigDecimal.ZERO) <= 0, "费用不能小于或者等于0");
                    if (i < intervalRules.size() - 1) {
                        SuitIntervalFeeRule nextRule = intervalRules.get(i + 1);
                        ServiceUtil.assertion(rule.getEnd() == null, "区间结束时间不能为空");
                        ServiceUtil.assertion(rule.getStart() > rule.getEnd(), "区间的结束时间不允许小于开始时间");
                        ServiceUtil.assertion(!MathUtils.equals(rule.getEnd(), nextRule.getStart()), "区间的结束时间必须等于下一个区间的开始时间");
                        int eachUnit = rule.getEachUnit();
                        int duration = rule.getEnd() - rule.getStart();
                        ServiceUtil.assertion(duration % eachUnit != 0, "区间间隔必须能够被区间整除");
                    }
                } catch (Exception e) {
                    throw new ServiceException("第" + (i + 1) + "条收费规则校验失败:" + e.getMessage());
                }
            }
        }
    }
}
