package com.yeejoin.equipmanage.action;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;
import com.yeejoin.amos.component.rule.MethodParam;
import com.yeejoin.amos.component.rule.RuleActionBean;
import com.yeejoin.amos.component.rule.RuleMethod;
import com.yeejoin.equipmanage.common.entity.dto.EquipQrDateDto;
import com.yeejoin.equipmanage.common.enums.CalculationRulesEnum;
import com.yeejoin.equipmanage.common.utils.DateUtils;
import com.yeejoin.equipmanage.service.ICarService;
import com.yeejoin.equipmanage.service.IEquipmentSpecificSerivce;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 赋码动作
 * @author DELL
 */
@Component
@RuleActionBean(beanLabel = "动态预案")
@Slf4j
public class UpdateQrCodeAction {

    @Autowired
    private ICarService carService;

    @Autowired
    private IEquipmentSpecificSerivce equipmentSpecificSerivce;

    private final String SOURCE_ID = "sourceId";
    private final String SOURCE_CAR = "car";
    private final String SOURCE_EQUIP = "equip";

    /**
     * 开闭区间正则表达式
     */
    private static final Pattern NUM_RANGE_PATTERN = Pattern.compile("[\\[|\\(]\\s?\\d+\\s?,\\s?\\d+\\s?[\\)|\\]]");

    @RuleMethod(methodLabel = "更新码", project = "车辆更新码颜色")
    public void updateCarQrCode(@MethodParam(paramLabel = "判断值") String value, @MethodParam(paramLabel = "赋码颜色") String color,
                                @MethodParam(paramLabel = "判断对象") Object equipQrDateDto, @MethodParam(paramLabel = "是否启用") Boolean enable,
                                @MethodParam(paramLabel = "计算规则") String rule) {

        if (Boolean.TRUE.equals(enable)) {
            EquipQrDateDto equipQrDateDtoN = JSONObject.parseObject(equipQrDateDto.toString(), EquipQrDateDto.class);
            List<Map<String, String>> data = equipQrDateDtoN.getData();
            String contrast = equipQrDateDtoN.getContrast();
            String source = equipQrDateDtoN.getSource();
            if (!CollectionUtils.isEmpty(data)) {
                List<Map<String, String>> collect = data.stream().map(map -> {
                    try {
                        String compareValue = null;
                        switch (source) {
                            case SOURCE_CAR:
                                Date date;
                                String s = map.get(contrast).replace("T", " ");
                                date = DateUtils.longStr2Date(s);
                                compareValue = String.valueOf(DateUtils.dateBetween(date, new Date()));
                                break;
                            case SOURCE_EQUIP:
                                compareValue = map.get(contrast);
                                break;
                            default:
                                break;
                        }
                        return StringUtils.isEmpty(compareValue) ? null : getId(map, rule, value, compareValue);
                    } catch (ParseException e) {
                        log.error("对比失败：{}", e.getMessage());
                        e.printStackTrace();
                        return null;
                    }
                }).filter(Objects::nonNull).collect(Collectors.toList());

                if (!CollectionUtils.isEmpty(collect)) {
                    switch (source) {
                        case SOURCE_CAR:
                            carService.updateCarQrCode(collect, color);
                            break;
                        case SOURCE_EQUIP:
                            equipmentSpecificSerivce.updateEquipQrCode(collect, color);
                            break;
                        default:
                            break;
                    }
                }
            }
        }
    }

    private Map<String, String> getId (Map<String, String> map, String rule, String value, String compareValue) {
        Map<String, String> mapNew = new HashMap<>();
        CalculationRulesEnum anEnum = CalculationRulesEnum.getEnum(rule);
        switch (anEnum) {
            case EQ:
                if (compareValue.equals(value)) {
                    mapNew = map;
                }
                break;
            case GT:
                if (Integer.parseInt(compareValue) > Integer.parseInt(value)) {
                    mapNew = map;
                }
                break;
            case GE:
                if (Integer.parseInt(compareValue) >= Integer.parseInt(value)) {
                    mapNew = map;
                }
                break;
            case LE:
                if (Integer.parseInt(compareValue) <= Integer.parseInt(value)) {
                    mapNew = map;
                }
                break;
            case LT:
                if (Integer.parseInt(compareValue) < Integer.parseInt(value)) {
                    mapNew = map;
                }
                break;
            case NE:
                if (!compareValue.equals(value)) {
                    mapNew = map;
                }
                break;
            case BE:
                int number = Integer.parseInt(compareValue);
                if (NUM_RANGE_PATTERN.matcher(value).matches()) {
                    String[] pairs = value.split(",");

                    // 获取开闭区间的最小值和最大值
                    List<String> rangeNums = Arrays.stream(pairs).map(str -> str.replaceAll("[(|)|\\[|\\]]", "").trim()).collect(Collectors.toList());
                    Integer minValue = "".equals(rangeNums.get(0)) ? null : Integer.valueOf(rangeNums.get(0));
                    Integer maxValue = "".equals(rangeNums.get(1)) ? null : Integer.valueOf(rangeNums.get(1));

                    // 判定数值是否大于最小值
                    boolean minMatched = (minValue == null) || (pairs[0].startsWith("[") ? number >= minValue : number > minValue);
                    // 判定数值是否小于最大值
                    boolean maxMatched = (maxValue == null) || (pairs[1].endsWith("]") ? number <= maxValue : number < maxValue);

                    if (minMatched && maxMatched) {
                        mapNew = map;
                    }
                }
                break;
            default:
                break;
        }
        return mapNew;
    }
}
