package com.njcn.roma.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.baomidou.mybatisplus.extension.toolkit.SqlRunner;
import com.huawei.it.eip.ump.client.producer.Producer;
import com.huawei.it.eip.ump.client.producer.SendResult;
import com.huawei.it.eip.ump.common.exception.UmpException;
import com.huawei.it.eip.ump.common.message.Message;
import com.njcn.influx.base.InfluxDbBaseMapper;
import com.njcn.influx.imapper.DataVMapper;
import com.njcn.influx.pojo.po.DataV;
import com.njcn.influx.service.IDataVService;
import com.njcn.roma.client.ClientHandler;
import com.njcn.roma.mapper.EleEpdPqdMapper;
import com.njcn.roma.mapper.PmsHistoryDataMapper;
import com.njcn.roma.pojo.EleEpdPqd;
import com.njcn.roma.pojo.PmsHistoryDataPO;
import com.njcn.roma.server.WebSocketServer;
import com.njcn.roma.utils.JsonValueFluctuator;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.ColumnMapRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * roma
 *
 * @author cdf
 * @date 2024/6/20
 */
@RestController
@RequiredArgsConstructor
public class TestController {

    private final ClientHandler clientHandler;

    private final WebSocketServer webSocketServer;

    public String topicMsg = "{\"HRPhV_H14_phsC\":\"0.0000\",\"HRPhV_H14_phsB\":\"0.0000\",\"HRPhV_H14_phsA\":\"0.0000\",\"HRPhV_H2_phsB\":\"0.0100\",\"HRPhV_H2_phsA\":\"0.0100\",\"HRPhV_H2_phsC\":\"0.0100\",\"HRPhV_H15_phsA\":\"0.0120\",\"TotW\":\"19771.1367\",\"HRPhV_H15_phsB\":\"0.0120\",\"HRPhV_H15_phsC\":\"0.0120\",\"FreqDev\":\"0.0000\",\"PPV_phsAB\":\"384.0318\",\"A_phsC\":\"60.7116\",\"TotPF\":\"0.4946\",\"A_phsA\":\"60.7123\",\"A_phsB\":\"60.7111\",\"PPV_phsBC\":\"383.3656\",\"HRPhV_H25_phsB\":\"0.0080\",\"HRPhV_H25_phsC\":\"0.0080\",\"HRPhV_H25_phsA\":\"0.0080\",\"DataTag\":\"0\",\"HRPhV_H20_phsA\":\"0.0000\",\"HRPhV_H20_phsB\":\"0.0000\",\"HRPhV_H20_phsC\":\"0.0000\",\"PPV_phsCA\":\"383.3637\",\"HRPhV_H3_phsB\":\"0.0640\",\"HRPhV_H3_phsC\":\"0.0640\",\"HRPhV_H9_phsC\":\"0.0220\",\"ThdPhV_phsA\":\"0.0913\",\"HRPhV_H9_phsB\":\"0.0220\",\"HRPhV_H9_phsA\":\"0.0220\",\"ThdPhV_phsB\":\"0.0913\",\"ThdPhV_phsC\":\"0.0913\",\"HRPhV_H19_phsC\":\"0.0100\",\"HRPhV_H19_phsB\":\"0.0100\",\"HRPhV_H19_phsA\":\"0.0100\",\"HRPhV_H16_phsA\":\"0.0000\",\"HRPhV_H13_phsA\":\"0.0140\",\"HRPhV_H16_phsC\":\"0.0000\",\"HRPhV_H13_phsB\":\"0.0140\",\"HRPhV_H16_phsB\":\"0.0000\",\"TotVA\":\"39977.2305\",\"HRPhV_H13_phsC\":\"0.0140\",\"HRPhV_H6_phsB\":\"0.0026\",\"HRPhV_H3_phsA\":\"0.0640\",\"HRPhV_H6_phsA\":\"0.0026\",\"HRPhV_H10_phsA\":\"0.0026\",\"HRPhV_H10_phsB\":\"0.0026\",\"HRPhV_H6_phsC\":\"0.0026\",\"HRPhV_H10_phsC\":\"0.0026\",\"ImbNgV\":\"0.0012\",\"TotVar\":\"34745.9492\",\"HRPhV_H7_phsC\":\"0.0280\",\"HRPhV_H7_phsB\":\"0.0280\",\"HRPhV_H22_phsC\":\"0.0000\",\"HRPhV_H22_phsB\":\"0.0000\",\"ImbZroV\":\"0.0012\",\"HRPhV_H22_phsA\":\"0.0000\",\"HRPhV_H7_phsA\":\"0.0280\",\"HRPhV_H8_phsA\":\"0.0026\",\"HRPhV_H23_phsB\":\"0.0080\",\"PhV_phsA\":\"221.9935\",\"HRPhV_H8_phsB\":\"0.0026\",\"HRPhV_H23_phsC\":\"0.0080\",\"HRPhV_H8_phsC\":\"0.0026\",\"PhV_phsB\":\"221.9947\",\"PhV_phsC\":\"221.9979\",\"HRPhV_H23_phsA\":\"0.0080\",\"PstPhV_phsC\":\"3.2942\",\"PstPhV_phsA\":\"3.3086\",\"PstPhV_phsB\":\"3.2987\",\"Freq\":\"50.0000\",\"HRPhV_H11_phsA\":\"0.0180\",\"HRPhV_H11_phsB\":\"0.0180\",\"HRPhV_H17_phsC\":\"0.0100\",\"HRPhV_H11_phsC\":\"0.0180\",\"HRPhV_H17_phsB\":\"0.0100\",\"HRPhV_H17_phsA\":\"0.0100\",\"SeqV_C2\":\"0.0715\",\"HRPhV_H4_phsB\":\"0.0050\",\"SeqV_C1\":\"60.4601\",\"HRPhV_H4_phsA\":\"0.0050\",\"SeqV_C0\":\"0.0714\",\"PhVDev_phsC\":\"0.0119\",\"HRPhV_H5_phsA\":\"0.0400\",\"HRPhV_H5_phsB\":\"0.0400\",\"HRPhV_H5_phsC\":\"0.0400\",\"PhVDev_phsB\":\"0.0119\",\"HRPhV_H12_phsC\":\"0.0010\",\"PltPhV_phsA\":\"0.0000\",\"PhVDev_phsA\":\"0.0119\",\"HRPhV_H12_phsB\":\"0.0010\",\"HRPhV_H4_phsC\":\"0.0050\",\"HRPhV_H18_phsB\":\"0.0000\",\"HRPhV_H18_phsC\":\"0.0000\",\"HRPhV_H12_phsA\":\"0.0010\",\"HRPhV_H18_phsA\":\"0.0000\",\"HFundPhV_phsC\":\"220.8052\",\"HRPhV_H21_phsC\":\"0.0080\",\"HRPhV_H21_phsB\":\"0.0080\",\"HRPhV_H24_phsC\":\"0.0000\",\"HFundPhV_phsA\":\"220.8056\",\"HRPhV_H21_phsA\":\"0.0080\",\"HFundPhV_phsB\":\"220.8055\",\"HRPhV_H24_phsB\":\"0.0000\",\"PltPhV_phsC\":\"0.0000\",\"HRPhV_H24_phsA\":\"0.0000\",\"PltPhV_phsB\":\"0.0000\",\"time\":\"20240816T150000Z\"}";

    public String devId = "暂无数据";

    private final PmsHistoryDataMapper pmsHistoryDataMapper;

    private final EleEpdPqdMapper eleEpdPqdMapper;


    private final IDataVService iDataVService;


    @GetMapping("send")
    public void TestProducer() {

        try {
            Producer producer = new Producer();
            producer.setUmpNamesrvUrls("25.36.190.3:19776"); // 设置MQS的服务器地址
            producer.setAppId("X_DNZLXT"); // 设置客户端账号
            producer.setAppSecret("IoKU7u47seGwzO4CqGmCaQ=="); // 设置客户端密钥
            producer.setTopic("T_DNZLXT"); // 设置Topic Name
            producer.setEncryptTransport(false); // 设置是否需要加密传输
            producer.start();
            // 启动消息生产者，建议在应用程序启动时调用（即执行此代码）
            // 发送消息的业务逻辑
            Message message = new Message();
            message.setBusinessId("id-123456789"); // 设置消息业务标示，便于追踪消息轨迹
            message.setTags("tag-1"); // 设置消息标签

            try {
                byte[] tem = "body_test_cdfcdfcdfcdf".getBytes("UTF-8");
                message.setBody(tem);
                // 消息体，推荐使用
                //JSON.toJSONString(message).getBytes("UTF-8");
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e);
            }


            //注：MQS不对二进制消息进行转换，Producer和Consumer需协商好序列化和反序列化方式
            try {
                SendResult sendResult = producer.send(message);

                //2019-10-21 华为保密信息,未经授权禁止扩散 第 9 页, 共 11 页
                if (sendResult.isSuccess()) {
                    // 发送成功的逻辑处理
                    System.out.println("succeed .........");
                } else {
                    // 发送失败的逻辑处理
                }
            } catch (UmpException e) {
                // 异常处理
                producer.shutdown(); // 关闭消息生产者，建议在应用程序关闭的时候调用
            }

        } catch (Exception e) {
            System.out.println("error ............");
            e.printStackTrace();
        }
    }


    /**
     * 启动客户端
     *
     * @author cdf
     * @date 2024/7/1
     */

    @GetMapping("clientTest")
    public void TestClient() {
        clientHandler.start();
    }


    @GetMapping("list")
    @DS("sqlite")
    public List<JSONObject> list(@RequestParam("startTime") String startTime, @RequestParam("endTime") String endTime, @RequestParam("devId") String devId) {
        String sql = "select content from pms_history_data where dev_id ='" + devId + "' and time between '" + startTime + "' and '" + endTime + "'";
        List<String> list = new ArrayList<>(); //= this.jdbcTemplate.queryForList(sql, String.class);
        List<JSONObject> jsonObjectList = new ArrayList<>();
        list.forEach(item -> jsonObjectList.add(JSONObject.parseObject(item)));
        return jsonObjectList;
    }


    @DS("sqlite")
    @GetMapping("simulationWebSocket")
    public String simulationWebSocket() {
        devId = "NJCN230497";
        // 浮动范围（比如，我们希望数值在原始值的基础上最多变化10%）
        double fluctuationRange = 0.10;

        // 创建Random实例
        Random random = new Random();

        for (int i = 0; i < 30; i++) {
            JSONObject map = JSONObject.parseObject(topicMsg);
            map.put("customDevId", devId);
            double vA = Double.valueOf(map.get("PhV_phsA").toString());
            double vB = Double.valueOf(map.get("PhV_phsB").toString());
            double vC = Double.valueOf(map.get("PhV_phsC").toString());
            // 生成浮动值
            // 注意：因为我们要的是百分比，所以我们将fluctuationRange乘以originalValue得到最大浮动的绝对值
            double fluctuationA = (random.nextDouble() * 2 - 1) * (fluctuationRange * vA);
            // 计算新的数值
            double newValueA = vA + fluctuationA;

            double fluctuationB = (random.nextDouble() * 2 - 1) * (fluctuationRange * vB);
            // 计算新的数值
            double newValueB = vA + fluctuationB;
            double fluctuationC = (random.nextDouble() * 2 - 1) * (fluctuationRange * vC);
            // 计算新的数值
            double newValueC = vC + fluctuationC;
            map.put("PhV_phsA", String.valueOf(newValueA));
            map.put("PhV_phsB", String.valueOf(newValueB));
            map.put("PhV_phsC", String.valueOf(newValueC));


            double iA = Double.valueOf(map.get("A_phsA").toString());
            double iB = Double.valueOf(map.get("A_phsB").toString());
            double iC = Double.valueOf(map.get("A_phsC").toString());
            // 生成浮动值
            // 注意：因为我们要的是百分比，所以我们将fluctuationRange乘以originalValue得到最大浮动的绝对值
            double fluctuationIA = (random.nextDouble() * 2 - 1) * (fluctuationRange * vA);
            // 计算新的数值
            double newValueIA = iA + fluctuationIA;

            double fluctuationIB = (random.nextDouble() * 2 - 1) * (fluctuationRange * iB);
            // 计算新的数值
            double newValueIB = iA + fluctuationIB;
            double fluctuationIC = (random.nextDouble() * 2 - 1) * (fluctuationRange * iC);
            // 计算新的数值
            double newValueIC = iC + fluctuationIC;
            map.put("A_phsA", String.valueOf(newValueIA));
            map.put("A_phsB", String.valueOf(newValueIB));
            map.put("A_phsC", String.valueOf(newValueIC));

            String time = map.get("time").toString();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmssX");
            try {
                ZonedDateTime dateTime = ZonedDateTime.parse(time, formatter);
                long aa = 1000 - i;
                System.out.println(aa);
                dateTime = dateTime.minusMinutes(aa);
                String ten = dateTime.format(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN));
                System.out.println(ten);
                map.put("time", ten);
                webSocketServer.sendSocketMessageToAll(map.toJSONString());

                //入库influxdb
                List<DataV> poList = new ArrayList<>();
                iDataVService.insertBatch(poList);

                DataV dataV = new DataV();
                Class<?> clazz = dataV.getClass();
                Field timeInflux = clazz.getDeclaredField("time");
                timeInflux.setAccessible(true);
                timeInflux.set(dataV, dateTime.toInstant());

            /*    try {
                    PmsHistoryDataPO pmsHistoryDataPO = new PmsHistoryDataPO();
                    pmsHistoryDataPO.setTime(ten);
                    pmsHistoryDataPO.setDevId(devId);
                    pmsHistoryDataPO.setContent(map.toJSONString());
                    pmsHistoryDataMapper.insert(pmsHistoryDataPO);
                    //int ret = jdbcTemplate.update();
                }catch (Exception e){
                    System.out.println("执行sql语句错误"+e.getMessage());
                }*/

            } catch (Exception e) {
                e.printStackTrace();
            }

            try {
                Thread.sleep(1000);
                //Thread.sleep(180000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

        return "推送成功";
    }


    @GetMapping("simulationInfluxdb")
    @DS("master")
    public String simulationInfluxdb() {
        List<EleEpdPqd> eleEpdPqdList = eleEpdPqdMapper.selectList(new LambdaQueryWrapper<EleEpdPqd>().eq(EleEpdPqd::getSystemType, "pms"));
        Map<String,List<EleEpdPqd>> elePhaseMap = eleEpdPqdList.stream().collect(Collectors.groupingBy(EleEpdPqd::getPhase));

        //Map<String, EleEpdPqd> eleEpdPqdMap = eleEpdPqdList.stream().collect(Collectors.toMap(EleEpdPqd::getName, Function.identity()));
        devId = "NJCN230497";

        List<DataV> poList = new ArrayList<>();

        cn.hutool.json.JSONObject jsonObject = JsonValueFluctuator.fluctuateValuesInJson(topicMsg);


        jsonObject.put("customDevId", devId);
        elePhaseMap.forEach((phase,list)->{

            Map<String,EleEpdPqd> m = list.stream().collect(Collectors.toMap(EleEpdPqd::getName,Function.identity()));
            Map<String, Double> map = new HashMap<>();
            m.forEach((mk,mv)->{
                if(jsonObject.containsKey(mk)){
                    if(StrUtil.isNotBlank(mv.getOtherName())) {
                        map.put(mv.getOtherName(), Double.valueOf(jsonObject.get(mk).toString()));
                    }
                }
            });



            DataV dataV = new DataV();
            BeanUtil.copyProperties(map,dataV);

            dataV.setPhaseType(phase);
            dataV.setLineId(jsonObject.get("customDevId").toString());
            dataV.setValueType("CP95");
            dataV.setQualityFlag("0");
            Class<?> clazz = dataV.getClass();
            Field timeInflux = null;
            try {
                timeInflux = clazz.getDeclaredField("time");
                timeInflux.setAccessible(true);
                timeInflux.set(dataV, jsonObject.get("time"));


            } catch (NoSuchFieldException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }

            JsonValueFluctuator.setNullNumberFieldsToZero(dataV);
            poList.add(dataV);

        });
        //for (int i = 0; i < 30; i++) {
            //for (int j = 0; j < 4; j++) {


                try {
                    //入库influxdb



                    iDataVService.insertBatch(poList);
            /*    try {
                    PmsHistoryDataPO pmsHistoryDataPO = new PmsHistoryDataPO();
                    pmsHistoryDataPO.setTime(ten);
                    pmsHistoryDataPO.setDevId(devId);
                    pmsHistoryDataPO.setContent(map.toJSONString());
                    pmsHistoryDataMapper.insert(pmsHistoryDataPO);
                    //int ret = jdbcTemplate.update();
                }catch (Exception e){
                    System.out.println("执行sql语句错误"+e.getMessage());
                }*/

                } catch (Exception e) {
                    e.printStackTrace();
                }

                try {
                    Thread.sleep(1000);
                    //Thread.sleep(180000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            //}
       // }

        return "推送成功";
    }


    @GetMapping("createTable")
    public String createTable() {
        String ddl = "CREATE TABLE \"pms_history_data\" (\n" +
                "  \"time\" text(16) NOT NULL,\n" +
                "  \"dev_id\" text(10) NOT NULL,\n" +
                "  \"content\" text NOT NULL,\n" +
                "  PRIMARY KEY (\"time\", \"dev_id\")\n" +
                ");";

        return "创建pms_history_data成功";
    }

}
