package com.sckw.slope.detection.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sckw.core.exception.SystemException;
import com.sckw.core.model.constant.NumberConstant;
import com.sckw.core.model.enums.*;
import com.sckw.core.model.page.PageRes;
import com.sckw.core.utils.IdWorker;
import com.sckw.core.web.constant.HttpStatus;
import com.sckw.core.web.response.HttpResult;
import com.sckw.slope.detection.dao.mysql.*;
import com.sckw.slope.detection.dao.tdengine.InsTablesMapper;
import com.sckw.slope.detection.dao.tdengine.SlopeDataMapper;
import com.sckw.slope.detection.model.dos.mysql.KwsDevice;
import com.sckw.slope.detection.model.dos.mysql.KwsDeviceReference;
import com.sckw.slope.detection.model.dos.mysql.KwsIntegration;
import com.sckw.slope.detection.model.dos.mysql.KwsThreshold;
import com.sckw.slope.detection.model.dos.tdengine.InsTables;
import com.sckw.slope.detection.model.dos.tdengine.SlopeData;
import com.sckw.slope.detection.model.dto.DeviceDataDTO;
import com.sckw.slope.detection.model.dto.HeaderData;
import com.sckw.slope.detection.model.dto.SystemDict;
import com.sckw.slope.detection.model.param.IntegrationQuery;
import com.sckw.slope.detection.model.vo.DeviceIntegrationVo;
import com.sckw.slope.detection.model.vo.DeviceReferenceVo;
import com.sckw.slope.detection.model.vo.IntegrationVo;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author sky
 * @description 数据回溯service
 * @date 2023-10-31 10:10:27
 */
@Slf4j
@Service
public class BackTrackService {

    private static final Long equatorial_circumference = 40075020000L;

    private static final Long LATITUDE_REFERENCE = 111000000L;

    @Autowired
    CommonService commonService;

    @Autowired
    KwsDeviceMapper deviceMapper;

    @Autowired
    KwsProjectMapper projectMapper;

    @Autowired
    KwsDeviceReferenceMapper deviceReferenceMapper;

    @Autowired
    KwsDeviceIntegrationMapper deviceIntegrationMapper;

    @Autowired
    KwsThresholdMapper thresholdMapper;

    @Autowired
    SlopeDataMapper slopeDataMapper;

    @Autowired
    KwsIntegrationMapper integrationMapper;

    @Autowired
    InsTablesMapper insTablesMapper;


    public HttpResult getParts(String projectId) {
        //首先获取项目中全部设备
        List<DeviceDataDTO> list = deviceMapper.selectAllDeviceByProject(projectId);
        List<String> devicesId = list.stream().map(DeviceDataDTO::getDeviceId).toList();
        if (devicesId.size() == 0) {
            return HttpResult.ok(Collections.emptyList());
        }
        //在获取设备的要素
        List<KwsDeviceReference> references = deviceReferenceMapper.selectList(new LambdaQueryWrapper<KwsDeviceReference>()
                .in(KwsDeviceReference::getDeviceId, devicesId)
                .eq(KwsDeviceReference::getDelFlag, NumberConstant.ZERO)
                .groupBy(KwsDeviceReference::getItem)
        );
        Map<String, SystemDict> dictList = commonService.getDictList(null, new HashMap<>() {{
            put("code", DictEnum.MODEL_PART.getCodeType());
            put("type", "1");
        }});
        //获取全部集成要素单位
        Map<String, SystemDict> dictCode = commonService.getDictByDictCode(DictEnum.INTEGRATION_UNIT);

        List<DeviceReferenceVo> vo = new ArrayList<>();
        //BeanUtils.copyProperties(references, vo);
        for (KwsDeviceReference re : references) {
            for (SystemDict value : dictList.values()) {
                if (re.getItem().equals(value.getValue())) {
                    re.setUnit(value.getUrl());
                    re.setUnitNe(value.getRemark());
                    re.setItemName(value.getLabel());
                }
            }
            if(Objects.isNull(re.getItemName())){
                List<IntegrationVo> inter = integrationMapper.getDataByStringName(re.getItem());
                re.setItemName(re.getItem());
                String unit = dictCode.get(inter.get(0).getUnit()).getDescription();
                re.setUnit(unit);
                re.setUnitNe(unit);
            }
        }
        return HttpResult.ok(references);
    }

    public HttpResult getDeviceByParts(String parts, String projectId) {
        //获取项目中的设备
        List<DeviceDataDTO> listDevice = deviceMapper.selectAllDeviceByProject(projectId);
        List<String> devicesId = listDevice.stream().map(DeviceDataDTO::getDeviceId).toList();
        //在获取设备的要素
        String[] arr = parts.split(",");
        List<String> list = Arrays.asList(arr);
        List<KwsDeviceReference> references = deviceReferenceMapper.selectList(new LambdaQueryWrapper<KwsDeviceReference>()
                .in(KwsDeviceReference::getItem, list)
                .in(KwsDeviceReference::getDeviceId, devicesId)
                .eq(KwsDeviceReference::getDelFlag, NumberConstant.ZERO)
        );
        //获取对应的设备
        List<Long> devicesIds = references.stream().map(KwsDeviceReference::getDeviceId).toList();
        if (Objects.isNull(devicesIds)) {
            return HttpResult.ok(Collections.emptyList());
        }
        List<KwsDevice> devices = deviceMapper.selectList(new LambdaQueryWrapper<KwsDevice>()
                .in(KwsDevice::getId, devicesIds)
                .eq(KwsDevice::getDelFlag, NumberConstant.ZERO)
        );
        return HttpResult.ok(devices);
    }

    public HttpResult getDeviceChart(String devicesId, String snCode, String parts, String dateStart, String dateEnd, Integer original, HttpServletRequest response) throws ParseException {
        //先查询设备
        KwsDevice deviceHas = deviceMapper.selectOne(new LambdaQueryWrapper<KwsDevice>()
                .eq(KwsDevice::getSnCode, snCode));
        String[] arr = parts.split(",");



        if (!DeviceEnum.ALREADY_REFERRED_TO.getStatus().equals(deviceHas.getStatus().toString())) {//未基准
            try {
                InsTables insTables = insTablesMapper.selectTableIsExit("device_" + snCode);
                if (insTables == null) {
                    //insTablesMapper.createTable("device_" + snCode);
                    return HttpResult.ok(Collections.emptyList());
                }
            } catch (Exception e) {
                return HttpResult.ok(Collections.emptyList());
            }
            List<SlopeData> selectedData = slopeDataMapper.selectLineListByArray(snCode, arr, dateStart, dateEnd);
            Map<String, List<Object>> map = new HashMap<>();

            if (Objects.isNull(selectedData)) {
                map = commonService.getDateByNull(dateStart, dateEnd, arr);
                return HttpResult.ok(map);
            }
            Collections.reverse(selectedData);
            for (SlopeData slop : selectedData) {
                if (slop.getLine().equals(DictItemEnum.getData(slop.getLine()).getValue())) {
                    List<Object> list = new ArrayList<>();
                    list.add(slop);
                    if (map.containsKey(slop.getLine())) {
                        map.get(slop.getLine()).add(slop);
                    } else {
                        map.put(slop.getLine(), list);
                    }

                }
            }
            List<Object> listm =  new ArrayList<>();
            //首先获取集成要数的数据
            List<DeviceIntegrationVo> intergData = deviceIntegrationMapper.selectListParamsAndInterNameByDeviceId(Long.parseLong(devicesId));
            if(Objects.nonNull(intergData)){
                for (DeviceIntegrationVo listvo : intergData){
                    listm = commonService.returnIntegrationDataArray(snCode,dateStart,dateEnd,listvo,"rawId","val");
                    Collections.reverse(listm);
                    map.put(listvo.getIntegrationName(),listm);

                }
            }
            return HttpResult.ok(map);
        }

        Map<String, Object> returnData = new HashMap<>();
        //在获取设备的要素
        List<KwsDeviceReference> references = deviceReferenceMapper.selectList(new LambdaQueryWrapper<KwsDeviceReference>()
                .eq(KwsDeviceReference::getDeviceId, devicesId)
                .eq(KwsDeviceReference::getDelFlag, NumberConstant.ZERO)

        );
        //获取基准值的纬度，X轴偏移量需要
        double angleInRadians = 0;
        for (KwsDeviceReference element : references) {
            if (DictItemEnum.LATITUDE_Y.getValue().equals(element.getItem())) {
                if (!Objects.isNull(element.getCurrentValue())) {
                    angleInRadians = element.getCurrentValue().doubleValue();
                }

            }
        }

        //获取设备的全部阈值
        List<KwsThreshold> kwsThresholds = thresholdMapper.selectList(new LambdaQueryWrapper<KwsThreshold>()
                .eq(KwsThreshold::getDelFlag, 0)
                .eq(KwsThreshold::getDeviceId, devicesId)
        );

        //获取偏移量
        Map<String, Object> mapList = new HashMap<>();
        for (String st : arr) {
            mapList.put(st, "");
        }
        for (KwsDeviceReference element : references) {
            int index = Arrays.binarySearch(arr, element.getItem());
            if (index <= 0) {
                //continue;
            }

            BigDecimal currentValue = new BigDecimal("0.00");
            if (original == 1) {
                currentValue = element.getOriginalValue();//以原始基准参考
            } else {
                currentValue = element.getCurrentValue();//以当前基准参考
            }

            BigDecimal offsetValue = new BigDecimal("0.00");
            List<Object> datemap = new ArrayList<>();
            Date date = new Date();
            List<SlopeData> selected = slopeDataMapper.selectLineList(snCode, element.getItem(), dateStart, dateEnd);
            if (!Objects.isNull((selected))) {
                for (SlopeData message : selected) {
                    String line = message.getLine();
                    String val1 = message.getVal();
                    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String key = format.format(message.getRawId());
                    BigDecimal subtract = new BigDecimal(val1).subtract(currentValue);
                    if (DictItemEnum.LONGITUDE_X.getValue().equals(element.getItem())) {//如果是X轴
                        double cosValue = Math.cos(Math.toRadians(angleInRadians));
                        double doubleValue = subtract.divide(new BigDecimal("360"), 11, BigDecimal.ROUND_HALF_UP).doubleValue();
                        offsetValue = new BigDecimal(equatorial_circumference).multiply(new BigDecimal(cosValue)).multiply(new BigDecimal(doubleValue));
                    } else if (DictItemEnum.LATITUDE_Y.getValue().equals(element.getItem())) {//如果是Y轴
                        offsetValue = new BigDecimal(LATITUDE_REFERENCE).multiply(subtract);
                    } else if (DictItemEnum.ALTITUDE_Z.getValue().equals(element.getItem())) {//如果是z轴
                        offsetValue = new BigDecimal(val1).divide(new BigDecimal(1000), 9, BigDecimal.ROUND_HALF_UP);
                    } else {//如果是其他
                        offsetValue = subtract;
                    }
                    double number = offsetValue.doubleValue();
                    DecimalFormat decimalFormat = new DecimalFormat("#.00");
                    String result = decimalFormat.format(number);
                    Map<String, Object> temp = new HashMap<>();
                    temp.put("time", key);
                    temp.put("offset", result);
                    datemap.add(temp);
                }
                Collections.reverse(datemap);
            }
            mapList.put(element.getItem(), datemap);
        }
        List<Object> listm =  new ArrayList<>();
        //首先获取集成要数的数据
        List<DeviceIntegrationVo> intergData = deviceIntegrationMapper.selectListParamsAndInterNameByDeviceId(Long.parseLong(devicesId));
        if(Objects.nonNull(intergData)){
            for (DeviceIntegrationVo listvo : intergData){
                listm = commonService.returnIntegrationDataArray(snCode,dateStart,dateEnd,listvo,"time","offset");
                Collections.reverse(listm);
                mapList.put(listvo.getIntegrationName(),listm);
            }
        }
        returnData.put("references", references);
        returnData.put("threshold", kwsThresholds);
        returnData.put("chart", mapList);
        return HttpResult.ok(returnData);
    }


    /**
     * 集成分析列表
     *
     * @param integrationQuery 请求分页
     * @param response         http流
     * @return 返回值
     */
    public PageRes getIntegrationList(IntegrationQuery integrationQuery, HttpServletRequest response) {
        PageHelper.startPage(integrationQuery.getPage(), integrationQuery.getPageSize());
        HeaderData headerData = commonService.getHeaderData(response);
        integrationQuery.setMountainId(headerData.getCompanyId());
        List<IntegrationVo> list = integrationMapper.getDataByName(integrationQuery);
        PageInfo<IntegrationVo> pageInfo = new PageInfo<>(list);
        if (CollectionUtils.isEmpty(list)) {
            return PageRes.build(pageInfo, list);
        }
        for (IntegrationVo vo : list) {
            List<Object> stringList = new ArrayList<>();

            String[] partNames = vo.getPartNames().split(",");
            for (int i = 0; i < partNames.length; i++) {
                Map<String, Object> strArray = new HashMap<>();
                if (DictItemEnum.getData(partNames[i]).getName().equals("ISNULL")) {
                    strArray.put("name", partNames[i]);
                } else {
                    strArray.put("name", DictItemEnum.getData(partNames[i]).getName());
                }

                stringList.add(strArray);
            }

            vo.setPartTrueNames(stringList);
        }


        return PageRes.build(pageInfo, list);
    }

    public HttpResult getIntegrationDetail(String integrationId) {
        KwsIntegration integration = integrationMapper.selectOne(new LambdaQueryWrapper<KwsIntegration>()
                .eq(KwsIntegration::getId, integrationId)
                .eq(KwsIntegration::getDelFlag, 0)
        );
        return HttpResult.ok(integration);
    }

    /**
     * 新增集成元素
     *
     * @param vo      请求参数
     * @param request http流
     * @return 返回值
     */
    @Transactional
    public HttpResult integrationAdd(IntegrationVo vo, HttpServletRequest request) {
        KwsIntegration has = integrationMapper.selectOne(new LambdaQueryWrapper<KwsIntegration>()
                .eq(KwsIntegration::getIntegrationName, vo.getIntegrationName())
                .eq(KwsIntegration::getDelFlag, 0)
        );
        if (!Objects.isNull(has)) {
            throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.INTEGRATION_EXISTS);
        }
        if(DictItemEnum.getHasBool(vo.getIntegrationName()) == 1){
            throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.INTEGRATION_SAME_PART_EXISTS);
        }
        HeaderData headerData = commonService.getHeaderData(request);
        KwsIntegration integration = new KwsIntegration();
        BeanUtils.copyProperties(vo, integration);
        Date now = new Date();
        long id = new IdWorker(NumberConstant.ONE).nextId();
        integration.setId(id);
        integration.setCreateBy(Long.parseLong(headerData.getCreateBy()));
        integration.setCreateTime(now);
        byte b = (byte) NumberConstant.ONE;
        byte zero = (byte) NumberConstant.ZERO;
        integration.setStatus(b);
        integration.setUpdateBy(Long.parseLong(headerData.getUpdateBy()));
        integration.setUpdateTime(now);
        integration.setDelFlag(zero);
        integration.setMountainId(headerData.getCompanyId());
        integrationMapper.insert(integration);
        Map<String, Object> logMap = new HashMap<>(NumberConstant.SIXTEEN);
        logMap.put("name", integration.getIntegrationName());
        logMap.put("type", IntegrationStatusEnum.getDestination(Byte.toUnsignedInt(integration.getStatus())));
        commonService.insertLog(MessageLogEnum.INTEGRATION_ADD, headerData, logMap, headerData.getUpdateBy() == null ? null : Long.parseLong(headerData.getUpdateBy()));
        return HttpResult.ok();
    }

    /**
     * 修改集成分析
     *
     * @param vo      请求参数
     * @param request http流
     * @return 返回值
     */
    @Transactional
    public HttpResult integrationUpdate(IntegrationVo vo, HttpServletRequest request) {
        KwsIntegration has = integrationMapper.selectOne(new LambdaQueryWrapper<KwsIntegration>()
                .eq(KwsIntegration::getId, vo.getId())
                .eq(KwsIntegration::getDelFlag, 0)
        );
        if (Objects.isNull(has)) {
            throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.INTEGRATION_NOT_EXISTS);
        }
        HeaderData headerData = commonService.getHeaderData(request);
        KwsIntegration integration = new KwsIntegration();
        BeanUtils.copyProperties(vo, integration);
        Date now = new Date();
        integration.setUpdateBy(Long.parseLong(headerData.getUpdateBy()));
        integration.setUpdateTime(now);
        integration.setRemark(StringUtils.isBlank(vo.getRemark()) ? null : vo.getRemark());
        integrationMapper.updateById(integration);
        Map<String, Object> logMap = new HashMap<>(NumberConstant.SIXTEEN);
        logMap.put("name", integration.getIntegrationName());
        logMap.put("type", IntegrationStatusEnum.getDestination(Byte.toUnsignedInt(has.getStatus())));
        commonService.insertLog(MessageLogEnum.INTEGRATION_ADD, headerData, logMap, headerData.getUpdateBy() == null ? null : Long.parseLong(headerData.getUpdateBy()));
        return HttpResult.ok();
    }

    public HttpResult getPartsByDeviceId(String deviceId) {
        //在获取设备的要素
        String[] arr = deviceId.split(",");
        List<String> list = Arrays.asList(arr);
        List<KwsDeviceReference> references = deviceReferenceMapper.selectList(new LambdaQueryWrapper<KwsDeviceReference>()
                .in(KwsDeviceReference::getDeviceId, list)
                .eq(KwsDeviceReference::getDelFlag, NumberConstant.ZERO)
                .groupBy(KwsDeviceReference::getItem)
        );

        Map<String, SystemDict> dictList = commonService.getDictList(null, new HashMap<>() {{
            put("code", DictEnum.MODEL_PART.getCodeType());
            put("type", "1");
        }});
        List<DeviceReferenceVo> vo = new ArrayList<>();
        //BeanUtils.copyProperties(references, vo);
        for (KwsDeviceReference re : references) {
            for (SystemDict value : dictList.values()) {
                if (re.getItem().equals(value.getValue())) {
                    re.setUnit(value.getUrl());
                    re.setUnitNe(value.getRemark());
                    re.setItemName(value.getLabel());
                }
            }
        }

        return HttpResult.ok(references);
    }
}
