package com.iailab.module.data.ind.collection.handler;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.iailab.framework.common.constant.CommonConstant;
import com.iailab.module.data.common.enums.ItemTypeEnum;
import com.iailab.module.data.common.enums.JsErrorCode;
import com.iailab.module.data.common.utils.JavaScriptHandler;
import com.iailab.module.data.ind.item.entity.IndItemEntity;
import com.iailab.module.data.ind.item.service.IndItemCalService;
import com.iailab.module.data.ind.item.service.IndItemService;
import com.iailab.module.data.ind.item.vo.IndItemCalVO;
import com.iailab.module.data.ind.item.vo.IndItemValueVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

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

/**
 * @author PanZhibao
 * @Description
 * @createTime 2024年10月04日
 */
@Slf4j
@Component
public class CalItemHandler {

    @Resource
    private JavaScriptHandler javaScriptHandler;

    public static final String regex = "[+\\-\\*\\/\\(\\)\\&\\|\\>\\<]";

    @Autowired
    private IndItemCalService indItemCalService;

    @Autowired
    private AtomItemHandler atomItemHandler;

    @Autowired
    private DerItemHandler derItemHandler;

    @Autowired
    private IndItemService indItemService;

    public List<IndItemValueVO> queryValue(String itemId) {
        List<IndItemValueVO> result = new ArrayList<IndItemValueVO>();
        try {
            IndItemCalVO indItem = indItemCalService.getByItemId(itemId);
            String expression = indItem.getExpression();
            if (StringUtils.isBlank(expression)) {
                return result;
            }
            String[] arr = expression.split(regex);
            int dataLength = 0;
            List<List<IndItemValueVO>> valueMix = new ArrayList<>();
            for (int i = 0; i < arr.length; i++) {
                String s = arr[i];
                if (StringUtils.isBlank(s)) {
                    continue;
                }
                IndItemEntity subItem = indItemService.getInfoByNo(s);
                ItemTypeEnum itemType = ItemTypeEnum.getEumByCode(subItem.getItemType());
                List<IndItemValueVO> vl = new ArrayList<>();
                switch (itemType) {
                    case ATOM:
                        vl = atomItemHandler.queryValue(subItem.getId());
                        break;
                    case DER:
                        vl = derItemHandler.queryValue(subItem.getId());
                        break;
                    default:
                        break;
                }
                if (!CollectionUtils.isEmpty(vl)) {
                    vl.forEach(vi -> {
                        vi.setItemNo(s);
                    });
                }
                valueMix.add(vl);
            }
            dataLength = valueMix.get(0).size();

            for (int i = 0; i < dataLength; i++) {
                Map<String, IndItemValueVO> dataMap = new HashMap<>();
                for (int j = 0; j < valueMix.size(); j++) {
                    IndItemValueVO valueDTO = valueMix.get(j).get(i);
                    dataMap.put(valueDTO.getItemNo(), valueDTO);
                }
                IndItemValueVO itemValue = this.singleCompute(indItem, dataMap);
                result.add(itemValue);
            }

        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return result;
    }

    public List<IndItemValueVO> queryValue(String itemId, Date startTime, Date endTime) {
        List<IndItemValueVO> result = new ArrayList<IndItemValueVO>();
        try {
            IndItemCalVO indItem = indItemCalService.getByItemId(itemId);
            String expression = indItem.getExpression();
            if (StringUtils.isBlank(expression)) {
                return result;
            }
            String[] arr = expression.split(regex);
            int dataLength = 0;
            List<List<IndItemValueVO>> valueMix = new ArrayList<>();
            for (int i = 0; i < arr.length; i++) {
                String s = arr[i];
                if (StringUtils.isBlank(s)) {
                    continue;
                }
                IndItemEntity subItem = indItemService.getInfoByNo(s);
                ItemTypeEnum itemType = ItemTypeEnum.getEumByCode(subItem.getItemType());
                List<IndItemValueVO> vl = new ArrayList<>();
                switch (itemType) {
                    case ATOM:
                        vl = atomItemHandler.queryValue(subItem.getId());
                        break;
                    case DER:
                        vl = derItemHandler.queryValue(subItem.getId(), startTime, endTime);
                        break;
                    default:
                        break;
                }
                if (!CollectionUtils.isEmpty(vl)) {
                    vl.forEach(vi -> vi.setItemNo(s));
                }
                valueMix.add(vl);
            }
            dataLength = valueMix.get(0).size();

            for (int i = 0; i < dataLength; i++) {
                Map<String, IndItemValueVO> dataMap = new HashMap<>();
                for (int j = 0; j < valueMix.size(); j++) {
                    IndItemValueVO valueDTO = valueMix.get(j).get(i);
                    dataMap.put(valueDTO.getItemNo(), valueDTO);
                }
                log.info("dataMap:" + dataMap);
                IndItemValueVO itemValue = this.singleCompute(indItem, dataMap);
                result.add(itemValue);
            }

        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return result;
    }

    private IndItemValueVO singleCompute(IndItemCalVO dto, Map<String, IndItemValueVO> dataMap) {
        IndItemValueVO resultDto = new IndItemValueVO();
        String dataTime = "";
        BigDecimal dataValue = CommonConstant.ZERO_VALUE;
        String expression = dto.getExpression();
        String[] arr = expression.split(regex);

        for (int i = 0; i < arr.length; i++) {
            String s = arr[i];
            if (StringUtils.isNotBlank(s) && dataMap.containsKey(s)) {
                dataTime = dataMap.get(s).getDataTime();
                if (dataMap.get(s) == null || dataMap.get(s).getDataValue() == null) {
                    resultDto.setDataTime(dataTime);
                    return resultDto;
                }
                expression = expression.replace(s, dataMap.get(s).getDataValue().toString());
            }
        }
        expression = expression.replace("&", "&&");
        expression = expression.replace("|", "||");
        expression = expression.replace("False", "false");
        expression = expression.replace("True", "true");
        log.info("ItemId=" + dto.getItemId() + ";expression=" + expression);
        String result = javaScriptHandler.eval(expression);
        log.info("result=" + result);
        if (result == null) {
            return null;
        } else if (result.contains(JsErrorCode.Infinity.name()) ||
                result.contains(JsErrorCode.NaN.name())) {
            log.info("计算异常,使用默认值");
        } else {
            dataValue = new BigDecimal(result);
        }
        resultDto.setDataTime(dataTime);
        resultDto.setDataValue(dataValue);
        return resultDto;
    }
}