package com.gyee.dataadapter.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.gyee.dataadapter.cache.MqttCache;
import com.gyee.dataadapter.dao.MyWebClient;
import com.gyee.dataadapter.entity.*;
import com.gyee.dataadapter.service.IAdapterService;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.springframework.http.*;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import javax.net.ssl.SSLContext;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


@Service
public class AdapterServiceImpl implements IAdapterService {

    private RestTemplate restTemplate = createRestTemplateWithSSLDisabled();

    @Resource
    private MyWebClient myWebClient;


    /**
     * 请求历史数据
     *
     * @param start      开始时间
     * @param end        结束时间
     * @param sampleType 采样类型。0瞬时值，1原始值，2最大值，3最小值，4平均值。
     * @param sampleRate 采样频率，单位秒。
     * @param paths      要查询的变量（数据、测点）名。
     * @param pageIndex  真分页页码，可不填，不填表示不分页。
     * @param pageSize   真分页页长，可不填，不填表示不分页。
     * @param isDesc     是否倒序，bool。
     * @return 历史数据
     */
    @Override
    public TotalPointData getTotalData(String start, String end, Integer sampleType, Integer sampleRate, String paths,
                                       String pageIndex, String pageSize, Boolean isDesc) {
        DateTime startTime = DateUtil.parse(start);
        DateTime endTime = DateUtil.parse(end);
        return getTotalData(startTime, endTime, sampleType, sampleRate, paths, pageIndex, pageSize, isDesc);
    }


    @Override
    public TotalPointData getTotalData(Date start, Date end, Integer sampleType, Integer sampleRate, String paths, String pageIndex, String pageSize, Boolean isDesc) {
//        start = DateUtil.offsetHour(start, -8);
//        end = DateUtil.offsetHour(end, -8);

        String uStart = DateUtil.formatDateTime(start);
        String uEnd = DateUtil.formatDateTime(end);

        StringBuilder sb = new StringBuilder();
        sb.append("/scadarest/api/SA/HistoryQuerySdb?start=").append(uStart).append("&end=").append(uEnd)
                .append("&sampleType=").append(sampleType).append("&paths=").append(paths);
        sb.append("&sampleRate=");
        if (sampleRate != null){
            sb.append(sampleRate);
        }else {
            long jg = (end.getTime()-start.getTime())/1000;
            sb.append(jg);
        }
        sb.append("&pageIndex=");
        if (StrUtil.isNotBlank(pageIndex)){
            sb.append(pageIndex);
        }else {
            sb.append(1);
        }
        sb.append("&pageSize=");
        if (StrUtil.isNotBlank(pageSize)){
            sb.append(pageSize);
        }else {
            sb.append(90000);
        }
        sb.append("&isDesc=");
        if (isDesc == null) isDesc = false;
        sb.append(isDesc);

        Mono<String> mono2 = myWebClient.webClient.get().uri(sb.toString())
                .header("Authorization", "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6WyJhZG1pbkBzY2FkYS5jb20iLCJhZG1pbkBzY2FkYS5jb20iXSwic3ViIjoiOGNiYjhlZTQtNjY5MS00M2ZlLTk0ZjktM2MxMDk1Mzg5Y2ZkIiwianRpIjoiNDUwMDFjYzAtYThjZC00YjgyLTgwM2YtMWZjMjVjYTFkZjU4IiwiaWF0IjoxNzMwOTY2MjEzLCJ1c2VyX2lkIjoiOGNiYjhlZTQtNjY5MS00M2ZlLTk0ZjktM2MxMDk1Mzg5Y2ZkIiwiYmluZGluZ190eXBlIjoiTm9uZSIsInJvbGVfaWQiOiI1NTM0NWEwOC1lY2QwLTRlMWUtYjM1MC0yYTQzZjM3Y2NiNmMiLCJuYmYiOjE3MzA5NjYyMTMsImV4cCI6MjA0NjMyNjIxMywiaXNzIjoiU2NhZGFQb3J0YWwiLCJhdWQiOiJTY2FkYVBvcnRhbFdlYkFQSSJ9.x2XOXFhNeSaBk0wxzdThVIkFg-sQRaGQxBjWoKKiZpEeyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6WyJhZG1pbkBzY2FkYS5jb20iLCJhZG1pbkBzY2FkYS5jb20iXSwic3ViIjoiOGNiYjhlZTQtNjY5MS00M2ZlLTk0ZjktM2MxMDk1Mzg5Y2ZkIiwianRpIjoiYmMzYjMyZjYtYTI2Mi00Y2ZmLTkxZDEtOTczMGE3MjFhNDQyIiwiaWF0IjoxNzMwOTcxODM5LCJ1c2VyX2lkIjoiOGNiYjhlZTQtNjY5MS00M2ZlLTk0ZjktM2MxMDk1Mzg5Y2ZkIiwiYmluZGluZ190eXBlIjoiTm9uZSIsInJvbGVfaWQiOiI1NTM0NWEwOC1lY2QwLTRlMWUtYjM1MC0yYTQzZjM3Y2NiNmMiLCJuYmYiOjE3MzA5NzE4MzksImV4cCI6MjA0NjMzMTgzOSwiaXNzIjoiU2NhZGFQb3J0YWwiLCJhdWQiOiJTY2FkYVBvcnRhbFdlYkFQSSJ9.3SGqyBHcIiHnreYqBhdp24YVoXTOhG2kXFL7y17PliI")
                .retrieve().bodyToMono(String.class);

//        String url = "https://10.220.1.5:5300/portalrest/api/Account/Login";
//        HttpHeaders headers = new HttpHeaders();
//        headers.setContentType(MediaType.APPLICATION_JSON);
//        Map<String, String> requestBody = new HashMap<>();
//        requestBody.put("Username", "admin@scada.com");
//        requestBody.put("Password", "Scada135}+?");
//        ObjectMapper objectMapper = new ObjectMapper();
//        ResponseEntity<Login> responseEntity = null;
//        try {
//            String jsonRequest = objectMapper.writeValueAsString(requestBody);
//            // 创建HttpEntity对象
//            HttpEntity<String> entity = new HttpEntity<>(jsonRequest, headers);
//             responseEntity = restTemplate.exchange(
//                    url,
//                    HttpMethod.POST,
//                    entity,
//                    Login.class
//            );
//        } catch (Exception e) {
//            e.printStackTrace();
//        }

//        Mono<String> mono2 = myWebClient.webClient.get().uri(sb.toString())
//                .header("Authorization", "Bearer " + responseEntity.getBody().getToken())
//                .retrieve().bodyToMono(String.class);
        String block = mono2.block();
        return JSON.parseObject(block, TotalPointData.class);
    }


    @Override
    public TotalPointData getTotalData(Date start, Date end, Integer sampleType, String paths) {
        start = DateUtil.offsetHour(start, -8);
        end = DateUtil.offsetHour(end, -8);
        String uStart = DateUtil.formatDateTime(start);
        String uEnd = DateUtil.formatDateTime(end);
        long jg = (end.getTime()-start.getTime())/1000;

        StringBuilder sb = new StringBuilder();
        sb.append("/scadarest/api/SA/HistoryQuerySdb?start=").append(uStart).append("&end=").append(uEnd)
                .append("&sampleType=").append(sampleType).append("&paths=").append(paths);
        sb.append("&sampleRate=").append(jg);
        sb.append("&pageIndex=1");
        sb.append("&pageSize=90000");
        sb.append("&isDesc=false");

        Mono<String> mono2 = myWebClient.webClient.get().uri(sb.toString())
                .header("Authorization", "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6WyJhZG1pbkBzY2FkYS5jb20iLCJhZG1pbkBzY2FkYS5jb20iXSwic3ViIjoiOGNiYjhlZTQtNjY5MS00M2ZlLTk0ZjktM2MxMDk1Mzg5Y2ZkIiwianRpIjoiNDUwMDFjYzAtYThjZC00YjgyLTgwM2YtMWZjMjVjYTFkZjU4IiwiaWF0IjoxNzMwOTY2MjEzLCJ1c2VyX2lkIjoiOGNiYjhlZTQtNjY5MS00M2ZlLTk0ZjktM2MxMDk1Mzg5Y2ZkIiwiYmluZGluZ190eXBlIjoiTm9uZSIsInJvbGVfaWQiOiI1NTM0NWEwOC1lY2QwLTRlMWUtYjM1MC0yYTQzZjM3Y2NiNmMiLCJuYmYiOjE3MzA5NjYyMTMsImV4cCI6MjA0NjMyNjIxMywiaXNzIjoiU2NhZGFQb3J0YWwiLCJhdWQiOiJTY2FkYVBvcnRhbFdlYkFQSSJ9.x2XOXFhNeSaBk0wxzdThVIkFg-sQRaGQxBjWoKKiZpEeyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6WyJhZG1pbkBzY2FkYS5jb20iLCJhZG1pbkBzY2FkYS5jb20iXSwic3ViIjoiOGNiYjhlZTQtNjY5MS00M2ZlLTk0ZjktM2MxMDk1Mzg5Y2ZkIiwianRpIjoiYmMzYjMyZjYtYTI2Mi00Y2ZmLTkxZDEtOTczMGE3MjFhNDQyIiwiaWF0IjoxNzMwOTcxODM5LCJ1c2VyX2lkIjoiOGNiYjhlZTQtNjY5MS00M2ZlLTk0ZjktM2MxMDk1Mzg5Y2ZkIiwiYmluZGluZ190eXBlIjoiTm9uZSIsInJvbGVfaWQiOiI1NTM0NWEwOC1lY2QwLTRlMWUtYjM1MC0yYTQzZjM3Y2NiNmMiLCJuYmYiOjE3MzA5NzE4MzksImV4cCI6MjA0NjMzMTgzOSwiaXNzIjoiU2NhZGFQb3J0YWwiLCJhdWQiOiJTY2FkYVBvcnRhbFdlYkFQSSJ9.3SGqyBHcIiHnreYqBhdp24YVoXTOhG2kXFL7y17PliI")
                .retrieve().bodyToMono(String.class);

        String block = mono2.block();
        return JSON.parseObject(block, TotalPointData.class);
    }


    @Override
    public TotalPointData getTotalData(Date start, Date end, Integer sampleType, Integer sampleRate, String paths) {
        return getTotalData(start, end, sampleType, sampleRate, paths, null, null, null);
    }

    @Override
    public List<PointData> getPointData(Date start, Date end, Integer sampleType, Integer sampleRate, String path) {
        TotalPointData totalData = getTotalData(start, end, sampleType, sampleRate, path, null, null, null);
        return totalpd2Pd(totalData);
    }

    @Override
    public List<PointData> getPointData(Date start, Date end, Integer sampleType, Integer sampleRate, String paths,
                                        String pageIndex, String pageSize, Boolean isDesc) {
        TotalPointData totalData = getTotalData(start, end, sampleType, sampleRate, paths, pageIndex, pageSize, isDesc);
        return totalpd2Pd(totalData);
    }

    @Override
    public List<PointData> getPointData2(Date start, Date end, Integer sampleType, String path) {
        TotalPointData totalData = getTotalData(start, end, sampleType, path);
        return totalpd2Pd(totalData);
    }

    private List<PointData> totalpd2Pd(TotalPointData totalData) {
        List<SourcePointData> data = totalData.getData();
        if (CollUtil.isEmpty(data)) return new ArrayList<>();
        return data.stream().map(spd -> new PointData(spd.getTime(), spd.getValue())).collect(Collectors.toList());
    }

    /**
     * 处理日期为一位或者两位的问题
     */
    private static LocalDateTime parseDateTime(String datetimeString) {
        DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-M-d HH:mm:ss");
        LocalDateTime dateTime = null;

        try {
            dateTime = LocalDateTime.parse(datetimeString, formatter1);
        } catch (Exception e1) {
            try {
                DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-d HH:mm:ss");
                dateTime = LocalDateTime.parse(datetimeString, formatter2);
            } catch (Exception e2) {
                DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                dateTime = LocalDateTime.parse(datetimeString, formatter3);
            }
        }
        return dateTime;
    }


    /**
     * 请求实时数据
     *
     * @param paths 根据逗号隔开的测点
     * @return 测点的实时数据
     */
    @Override
    public Map<String, PointInfo> getLatestData(String paths) {
        Map<String, PointInfo> map = new HashMap<>();
        if (StrUtil.isBlank(paths)) return map;
        String[] split = paths.split(",");
        for (String s : split) {
            PointInfo pintInfo = MqttCache.subData.get(s);
            map.put(s, pintInfo);
        }
        return map;
    }

    /**
     * 请求实时数据
     *
     * @param tagNames 根据逗号隔开的测点
     * @return 测点的实时数据
     */
    @Override
    public Map<String, PointData> getLatestData2(List<String> tagNames) {
        Map<String, PointData> map = new HashMap<>();
        if (CollUtil.isEmpty(tagNames)) return map;
        for (String path : tagNames) {
            PointData pd = MqttCache.subData2.get(path);
            if(pd!=null)  map.put(path, pd);
        }
        return map;
    }


    public static RestTemplate createRestTemplateWithSSLDisabled() {
        try {
            // 创建一个不验证主机名的 SSLContext
            SSLContext sslContext = SSLContextBuilder.create()
                    .loadTrustMaterial(null, (certificate, authType) -> true) // 信任所有证书
                    .build();

            // 创建一个不验证主机名的 SSLSocketFactory
            SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(
                    sslContext,
                    NoopHostnameVerifier.INSTANCE // 不验证主机名
            );

            // 创建一个使用上述 SSLSocketFactory 的 HttpClient
            CloseableHttpClient httpClient = HttpClients.custom()
                    .setSSLSocketFactory(csf)
                    .build();

            // 创建一个使用上述 HttpClient 的 HttpComponentsClientHttpRequestFactory
            HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);

            // 创建 RestTemplate 并设置请求工厂
            return new RestTemplate(requestFactory);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
