package com.xzzn.ems.utils;


import com.xzzn.common.annotation.Excel;
import com.xzzn.common.constant.RedisKeyConstants;
import com.xzzn.common.core.redis.RedisCache;
import com.xzzn.common.enums.PointType;
import com.xzzn.common.utils.StringUtils;
import com.xzzn.ems.domain.EmsPointEnumMatch;
import com.xzzn.ems.domain.EmsPointMatch;
import com.xzzn.ems.domain.vo.DevicePointMatchInfo;
import com.xzzn.ems.enums.DeviceMatchTable;
import com.xzzn.ems.mapper.EmsDevicesSettingMapper;
import com.xzzn.ems.mapper.EmsPointEnumMatchMapper;
import com.xzzn.ems.mapper.EmsPointMatchMapper;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class DevicePointMatchDataProcessor {

    private static final Logger log = LoggerFactory.getLogger(DevicePointMatchDataProcessor.class);

    private DevicePointMatchInfo devicePointMatchInfo;

    @Autowired
    private EmsDevicesSettingMapper emsDevicesSettingMapper;
    @Autowired
    private EmsPointMatchMapper emsPointMatchMapper;
    @Autowired
    private EmsPointEnumMatchMapper emsPointEnumMatchMapper;

    @Autowired
    private RedisCache redisCache;

    /**
     * 初始化加载设备匹配点位配置数据
     */
//    @PostConstruct
//    public void init()
//    {
//        try {
//            ClassPathResource classPathResource = new ClassPathResource("biz/configData/DevicePointMatch.json");
//            String configJson = DataUtils.getJSONFromFile(classPathResource.getInputStream());
//            devicePointMatchInfo = JSONObject.parseObject(configJson, DevicePointMatchInfo.class);
//            log.info("初始化设备匹配点位配置数据成功。"+ JSON.toJSONString(devicePointMatchInfo));
//        } catch (Exception ex) {
//            log.error("OcrMedicalStdHandler 设置mapping数据异常。", ex);
//        }
//    }

    /**
     * 获取字段注解信息
     */
    public static String getFieldAnnotation(Class<?> clazz, String filedName)
    {
        List<Field> tempFields = new ArrayList<>();
        tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
        for (Field field : tempFields) {
            if (StringUtils.equals(filedName, field.getName()) && field.isAnnotationPresent(Excel.class))
            {
                Excel column = field.getAnnotation(Excel.class);
                return column.name();
            }
        }
        return null;
    }

    public List<EmsPointMatch> getDeviceDefaultPointMatch(String siteId, String deviceCategory) {
        List<EmsPointMatch> pointMatchList = redisCache.getCacheList(getPointMacthCacheKey(siteId, null, deviceCategory));
        if (CollectionUtils.isEmpty(pointMatchList)) {
            pointMatchList = emsPointMatchMapper.getDevicePointMatchList(siteId, null,  deviceCategory);
        }
        return pointMatchList;
    }

    public List<EmsPointMatch> getDevicePointMatch(String siteId, String deviceId, String deviceCategory) {
        return getDevicePointMatch(siteId, deviceId, deviceCategory, false);
    }

    public List<EmsPointMatch> getDeviceAlarmPointMatch(String siteId, String deviceId, String deviceCategory) {
        return getDevicePointMatch(siteId, deviceId, deviceCategory, true);
    }

    private List<EmsPointMatch> getDevicePointMatch(String siteId, String deviceId, String deviceCategory, boolean isAlarm) {
//        List<EmsPointMatch> pointMatchList = new ArrayList<>();
//        EmsDevicesSetting devicesSetting = emsDevicesSettingMapper.getDeviceBySiteAndDeviceId(deviceId, siteId);
//        if (devicesSetting == null) {
//            log.info("未找到设备配置信息，siteId: " + siteId + ", deviceId: "+ deviceId);
//            return pointMatchList;
//        }
        List<EmsPointMatch> pointMatchList = redisCache.getCacheList(getPointMacthCacheKey(siteId, deviceId, deviceCategory));
        if (CollectionUtils.isEmpty(pointMatchList)) {
            pointMatchList = emsPointMatchMapper.getDevicePointMatchList(siteId, deviceId, deviceCategory);
        }
        if (CollectionUtils.isNotEmpty(pointMatchList)) {
           Map<Integer, List<EmsPointMatch>> map = pointMatchList.stream().collect(Collectors.groupingBy(EmsPointMatch::getIsAlarm));
            if (isAlarm) {
                pointMatchList = map.get(PointType.YES.getCode());
            } else {
                pointMatchList = map.get(PointType.NO.getCode());
            }
        }

        return pointMatchList;
    }

    public List<EmsPointEnumMatch> getPointEnumMatchList(String siteId, String deviceCategory) {
        List<EmsPointEnumMatch> pointEnumMatchList = redisCache.getCacheList(getPointEnumMacthCacheKey(siteId, deviceCategory));

        if (CollectionUtils.isEmpty(pointEnumMatchList)) {
            pointEnumMatchList = emsPointEnumMatchMapper.selectList(siteId, deviceCategory, null);
        }

        return pointEnumMatchList;
    }

    public Map<String, List<EmsPointEnumMatch>> getPointEnumMatchMap(String siteId, String deviceCategory) {
        List<EmsPointEnumMatch> pointEnumMatchList = getPointEnumMatchList(siteId, deviceCategory);
        if (CollectionUtils.isEmpty(pointEnumMatchList)) {
            return new HashMap<>();
        }
        return pointEnumMatchList.stream()
                .filter(Objects::nonNull)
                .filter(data -> StringUtils.isNotEmpty(data.getMatchField()))
                .collect(Collectors.groupingBy(data -> StringUtils.toCamelCase(data.getMatchField())));
    }

    public void saveDevicePointMatch(String siteId, String deviceId, DeviceMatchTable pointMatchType, String dataDevice) {
//        EmsDevicesSetting devicesSetting = emsDevicesSettingMapper.getDeviceBySiteAndDeviceId(deviceId, siteId);
//        if (devicesSetting == null) {
//            return;
//        }
//        String deviceCategory = devicesSetting.getDeviceCategory();
        String deviceCategory = pointMatchType.getCode();
        Map<String, String> devicePintointMtachInfo = this.getDevicePointMtachInfo(pointMatchType, dataDevice);
        if (devicePintointMtachInfo.isEmpty()) {
            return;
        }

        try {
            devicePintointMtachInfo.forEach((key, value) -> {
                // 查询点位是否存在
                EmsPointMatch dbPoint = emsPointMatchMapper.getOnePointMatch(siteId, deviceId, deviceCategory, value);
                if (!Objects.isNull(dbPoint)) {
                    return;
                }
                EmsPointMatch pointMatch = new EmsPointMatch();
                pointMatch.setSiteId(siteId);
                pointMatch.setDeviceCategory(deviceCategory);
                pointMatch.setMatchTable(DeviceMatchTable.getMatchTableByCode(deviceCategory));
                pointMatch.setMatchField(StringUtils.toUnderScoreCase(key));
                pointMatch.setDataPoint(value);
                pointMatch.setPointName(getFieldAnnotation(DeviceMatchTable.getClassByTable(pointMatch.getMatchTable()), StringUtils.toCamelCase(pointMatch.getMatchField())));
                pointMatch.setDataDevice(dataDevice);
//            pointMatch.setDataPointName("");
//            pointMatch.setDataUnit("");
                pointMatch.setCreateBy("system");
                pointMatch.setUpdateBy("system");
                emsPointMatchMapper.insertEmsPointMatch(pointMatch);
            });
        } catch (Exception e) {
            log.info("保存设备点位匹配信息异常，siteId: " + siteId + ", deviceId: "+ deviceId + "异常信息：" + e.getMessage());
        }
    }

    private Map<String, String> getDevicePointMtachInfo(DeviceMatchTable pointMatchType, String dataDevice) {
        switch (pointMatchType) {
            case PCS:
                return devicePointMatchInfo.getPcs();
            case BRANCH:
                return devicePointMatchInfo.getBranch();
            case STACK:
                return devicePointMatchInfo.getStack();
            case CLUSTER:
                return devicePointMatchInfo.getCluster();
            case BATTERY:
                return devicePointMatchInfo.getBattery();
            case AMMETER:
                if (dataDevice.equals("LOAD")) {
                    return devicePointMatchInfo.getAmmeterLoad();
                } else {
                    return devicePointMatchInfo.getAmmeterMete();
                }
            case COOLING:
                return devicePointMatchInfo.getCooling();
            case DH:
                return devicePointMatchInfo.getDh();
            case XF:
                return devicePointMatchInfo.getXf();
            case BATTERY_GROUP:
                return devicePointMatchInfo.getBatteryGroup();
            default:
                return new HashMap<>();
        }
    }

    /**
     * 设置点位缓存key
     * @param siteId
     * @param deviceCategory
     * @return 点位缓存key
     */
    public static String getPointMacthCacheKey(String siteId, String deviceId, String deviceCategory)
    {
        if (StringUtils.isEmpty(deviceId)) {
            return RedisKeyConstants.POINT_MATCH + deviceCategory + "_" + siteId;
        } else {
            return RedisKeyConstants.POINT_MATCH + deviceCategory + "_" + siteId + "_" + deviceId;
        }
    }

    /**
     * 设置点位枚举缓存key
     * @param siteId
     * @param deviceCategory
     * @return 点位枚举缓存key
     */
    public static String getPointEnumMacthCacheKey(String siteId, String deviceCategory)
    {
        return RedisKeyConstants.POINT_ENUM_MATCH + deviceCategory + "_" + siteId;
    }

    /**
     * 转换字段值为配置枚举值
     */
    public void convertFieldValueToEnumMatch(String siteId, String deviceCategory, Object entity) {
        if (entity == null) {
            return;
        }

        Map<String, List<EmsPointEnumMatch>> pointEnumMatchMap = this.getPointEnumMatchMap(siteId, deviceCategory);
        if (pointEnumMatchMap == null || pointEnumMatchMap.isEmpty()) {
            return;
        }
        Field[] fields = entity.getClass().getDeclaredFields();
        for (Field field : fields) {
            String fieldName = field.getName();
            if (pointEnumMatchMap.containsKey(fieldName)) {
                // 处理匹配的字段名，并设置值
                field.setAccessible(true); // 允许访问私有字段
                try {
                    // 从原始数据中获取匹配值
                    Object matchValue = field.get(entity);
                    List<EmsPointEnumMatch> pointEnumMatchList = pointEnumMatchMap.get(fieldName);
                    if (CollectionUtils.isNotEmpty(pointEnumMatchList) && matchValue != null) {
                        String finalMatchValue = String.valueOf(matchValue).replace(".0", "");
                        Optional<EmsPointEnumMatch> enumMatch = pointEnumMatchList.stream()
                                .filter(Objects::nonNull)
                                .filter(data -> Objects.equals(data.getDataEnumCode(), finalMatchValue))
                                .findFirst();
                        if (enumMatch.isPresent()) {
                            matchValue = enumMatch.get().getEnumCode();
                        }
                    }
                    if (matchValue == null) {
                        continue;
                    }

                    // 设置字段值
                    field.set(entity, matchValue);
                } catch (IllegalAccessException e) {
                    log.warn("convertFieldValueToEnumMatch 设置字段值时出错", e);
                }
            }
        }
    }

}
