package com.ningdatech.carapi.sys.manage;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.carapi.sys.entity.BonusPointsRule;
import com.ningdatech.carapi.sys.entity.CodingRule;
import com.ningdatech.carapi.sys.entity.CodingRuleInfo;
import com.ningdatech.carapi.sys.entity.ScoreDeductionRule;
import com.ningdatech.carapi.sys.entity.enumeration.CodingRuleBehaviorTypeEnum;
import com.ningdatech.carapi.sys.entity.enumeration.CodingRuleVehicleType;
import com.ningdatech.carapi.sys.entity.enumeration.RuleOperationTypeEnum;
import com.ningdatech.carapi.sys.entity.req.ReqCodingRulePO;
import com.ningdatech.carapi.sys.entity.vo.ResCodingRuleVO;
import com.ningdatech.carapi.sys.service.ICodingRuleService;
import com.ningdatech.carapi.user.util.LoginUserUtil;

import cn.hutool.core.collection.CollectionUtil;
import lombok.RequiredArgsConstructor;

/**
 * @author liuxinxin
 * @date 2022/10/24 下午2:01
 */
@Component
@RequiredArgsConstructor
public class CodingRuleManage {

    private final ICodingRuleService iCodingRuleService;

    public ResCodingRuleVO getCodingRule() {
        ResCodingRuleVO resCodingRuleVO = new ResCodingRuleVO();

        List<CodingRule> codingRuleList = iCodingRuleService.list();
        Map<String, List<CodingRule>> operationCodingRuleMap = codingRuleList.stream().collect(Collectors.groupingBy(CodingRule::getRuleOperationType));
        // 装配加分规则
        List<CodingRuleInfo> codingRuleInfoList = new ArrayList<>();
        List<CodingRule> bonusPointsCodingRuleList = operationCodingRuleMap.get(RuleOperationTypeEnum.bonus_points.name());
        if (CollectionUtil.isNotEmpty(bonusPointsCodingRuleList)) {
            for (CodingRule codingRule : bonusPointsCodingRuleList) {
                CodingRuleInfo codingRuleInfo = new CodingRuleInfo();
                codingRuleInfo.setRuleOperationType(RuleOperationTypeEnum.valueOf(codingRule.getRuleOperationType()));
                codingRuleInfo.setOperationScore(codingRule.getOperationScore());
                codingRuleInfo.setCodingRuleBehaviorType(CodingRuleBehaviorTypeEnum.valueOf(codingRule.getBehaviorType()));
                codingRuleInfoList.add(codingRuleInfo);
            }
        }
        BonusPointsRule bonusPointsRule = new BonusPointsRule();
        bonusPointsRule.setCodingRuleInfoList(codingRuleInfoList);
        resCodingRuleVO.setBonusPointsRule(bonusPointsRule);

        // 装配扣分规则
        List<CodingRule> scoreDeductionCodingRuleList = operationCodingRuleMap.get(RuleOperationTypeEnum.score_deduction.name());

        List<ScoreDeductionRule> scoreDeductionRuleList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(scoreDeductionCodingRuleList)) {
            Map<String, List<CodingRule>> vehicleMap = scoreDeductionCodingRuleList.stream()
                    .collect(Collectors.groupingBy(CodingRule::getVehicleType));
            for (String vehicleTypeStr : vehicleMap.keySet()) {
                ScoreDeductionRule scoreDeductionRule = new ScoreDeductionRule();
                scoreDeductionRule.setVehicleType(CodingRuleVehicleType.valueOf(vehicleTypeStr));
                List<CodingRuleInfo> vehicleTypeCodingRuleInfoList = new ArrayList<>();

                List<CodingRule> vehicleCodingRuleList = vehicleMap.get(vehicleTypeStr);
                if (CollectionUtil.isNotEmpty(vehicleCodingRuleList)) {
                    for (CodingRule codingRule : vehicleCodingRuleList) {
                        CodingRuleInfo codingRuleInfo = new CodingRuleInfo();
                        codingRuleInfo.setRuleOperationType(RuleOperationTypeEnum.valueOf(codingRule.getRuleOperationType()));
                        codingRuleInfo.setOperationScore(codingRule.getOperationScore());
                        codingRuleInfo.setCodingRuleBehaviorType(CodingRuleBehaviorTypeEnum.valueOf(codingRule.getBehaviorType()));
                        vehicleTypeCodingRuleInfoList.add(codingRuleInfo);
                    }
                }
                scoreDeductionRule.setCodingRuleInfoList(vehicleTypeCodingRuleInfoList);
                scoreDeductionRuleList.add(scoreDeductionRule);
            }
        }
        resCodingRuleVO.setScoreDeductionRuleList(scoreDeductionRuleList);
        return resCodingRuleVO;
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveCodingRule(ReqCodingRulePO request) {
        Long userId = LoginUserUtil.getUserId();
        BonusPointsRule bonusPointsRule = request.getBonusPointsRule();
        List<ScoreDeductionRule> scoreDeductionRuleList = request.getScoreDeductionRuleList();
        // 保存加分规则
        List<CodingRuleInfo> bonusPointsRuleInfoList = bonusPointsRule.getCodingRuleInfoList();
        for (CodingRuleInfo bonusPointsRuleInfo : bonusPointsRuleInfoList) {
            CodingRule codingRule = iCodingRuleService.getOne(Wrappers.lambdaQuery(CodingRule.class)
                    .eq(CodingRule::getBehaviorType, bonusPointsRuleInfo.getCodingRuleBehaviorType().name()));
            if (Objects.isNull(codingRule)) {
                codingRule = new CodingRule();
                codingRule.setCreateOn(LocalDateTime.now());
                codingRule.setCreateBy(userId);
            }
            codingRule.setUpdateOn(LocalDateTime.now());
            codingRule.setOperationScore(bonusPointsRuleInfo.getOperationScore());
            codingRule.setRuleOperationType(bonusPointsRuleInfo.getRuleOperationType().name());
            codingRule.setBehaviorType(bonusPointsRuleInfo.getCodingRuleBehaviorType().name());
            iCodingRuleService.saveOrUpdate(codingRule);
        }

        // 保存扣分规则
        for (ScoreDeductionRule scoreDeductionRule : scoreDeductionRuleList) {
            CodingRuleVehicleType vehicleType = scoreDeductionRule.getVehicleType();
            List<CodingRuleInfo> codingRuleInfoList = scoreDeductionRule.getCodingRuleInfoList();
            for (CodingRuleInfo codingRuleInfo : codingRuleInfoList) {
                CodingRule codingRule = iCodingRuleService.getOne(Wrappers.lambdaQuery(CodingRule.class)
                        .eq(CodingRule::getBehaviorType, codingRuleInfo.getCodingRuleBehaviorType().name())
                        .eq(CodingRule::getVehicleType, vehicleType.name()));

                if (Objects.isNull(codingRule)) {
                    codingRule = new CodingRule();
                    codingRule.setCreateOn(LocalDateTime.now());
                    codingRule.setCreateBy(userId);
                    codingRule.setVehicleType(vehicleType.name());
                }
                codingRule.setUpdateOn(LocalDateTime.now());
                codingRule.setOperationScore(codingRuleInfo.getOperationScore());
                codingRule.setRuleOperationType(codingRuleInfo.getRuleOperationType().name());
                codingRule.setBehaviorType(codingRuleInfo.getCodingRuleBehaviorType().name());
                iCodingRuleService.saveOrUpdate(codingRule);
            }
        }
    }
}
