package com.jiayue.insu.inclientqn.pushData;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.jiayue.insu.inclientqn.constant.CommonStant;
import com.jiayue.insu.inclientqn.entity.BackForeUsForecastData;
import com.jiayue.insu.inclientqn.entity.Record;
import com.jiayue.insu.inclientqn.entity.Station;
import com.jiayue.insu.inclientqn.inenum.QNHLEnum;
import com.jiayue.insu.inclientqn.inenum.StatusEnum;
import com.jiayue.insu.inclientqn.model.ResponseVo;
import com.jiayue.insu.inclientqn.service.BackForeUsForecastDataService;
import com.jiayue.insu.inclientqn.service.RecordService;
import com.jiayue.insu.inclientqn.util.DateTimeUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;

@Slf4j
@RefreshScope
@Component
public class PushForecastData implements IPushForecastData {

    @Autowired
    private RecordService recordService;
    @Autowired
    private BackForeUsForecastDataService backForeUsForecastDataService;

    /**
     * 推送原始超短期数据给一体化云端
     *
     * @return
     */
    @Override
    public boolean pushUltraShortTermDataWX(Station station,LocalDateTime signTime) {

        // 获取场站编号
         String stationCode = station.getStationCode();
        Record record = new Record();
        record.setStationCode(station.getStationCode());
        record.setTime(signTime);
        record.setCreateTime(LocalDateTime.now());
        record.setType(CommonStant.RECORD_TYPE_PUSH_INIT);
        record.setContent(QNHLEnum.DATA_ORIGINALCDQ_TYPE.getCode());
        log.info("开始给一体化云端推送原始超短期数据 --> {}" + station.getStationCode());
        // 如果场站编号为空，则返回
        if (stationCode == null || "".equals(stationCode)) {
            record.setState(StatusEnum.STATION_CODE_NULL.getSign());
            record.setStateContent(StatusEnum.STATION_CODE_NULL.getMsg());
            recordService.save(record);
            return false;
        }

        // 指定时区，例如系统默认时区
        ZoneId zoneId = ZoneId.systemDefault();

        // 将 LocalDateTime 转换为 ZonedDateTime
        ZonedDateTime zonedDateTime = signTime.atZone(zoneId);

        // 将 ZonedDateTime 转换为 Instant，Instant 可以获取到时间戳
        Instant instant = zonedDateTime.toInstant();

        // 获取时间戳（毫秒）
        long timestamp = instant.toEpochMilli();

        List<DataPointDTO> list = new ArrayList<>();

        // 查询超短期数据
        List<BackForeUsForecastData> usForecastDataList = backForeUsForecastDataService.findBySignTime(signTime);
        if (usForecastDataList.size() > 0) {
            for (BackForeUsForecastData backForeUsForecastData : usForecastDataList) {
                DataPointDTO dto = new DataPointDTO();
                zonedDateTime = backForeUsForecastData.getForecastTime().atZone(ZoneId.systemDefault());
                // 将ZonedDateTime转换为Instant
                instant = zonedDateTime.toInstant();
                // 获取时间戳（毫秒）
                long forecastTime = instant.toEpochMilli();
                dto.setForecastTime(String.valueOf(forecastTime));
                dto.setFpValue(String.valueOf(backForeUsForecastData.getForecastValue()));
                list.add(dto);
            }
        }
        if (list.size() < 16){
            log.error("原始超短期数据为：{}条，不进行原始数据上送",list.size());
            return false;
        }
        WXPushCDqDataParamsDto wxPushCDqDataParamsDto = new WXPushCDqDataParamsDto(stationCode,String.valueOf(timestamp),list);
        JSONObject json = JSONUtil.parseObj(wxPushCDqDataParamsDto, false);
        String body = json.toString();
        try {
            String credentials = station.getUsername() + ":" + station.getPassword();
            // Base64编码
            String encodedCredentials = Base64.getEncoder().encodeToString(credentials.getBytes());
            String response;
            HttpRequest httpRequest = HttpRequest.post(station.getBackurl())
                    .header("Content-Type", "application/json")
                    .header("Authorization","Basic "+encodedCredentials);
            httpRequest.setGlobalTimeout(20000);
            response = httpRequest.body(body).execute().body();

            ResponseVo responseVo = JSONUtil.toBean(response, ResponseVo.class);
            if (responseVo.getRetCode().equals("200")) {
                record.setState(StatusEnum.SUCCESS.getSign());
                record.setStateContent("嘉越云"+responseVo.getRetMsg());
                log.info("=========={}:{} ==>上送超短期原始数据成功  {}条==========", station.getName(), station.getStationCode(), list.size());
                log.info("{} 原始数据:{}", stationCode, body);
                recordService.save(record);
                return true;
            } else {
                log.error("=========={}:{} ==>上送数据失败 失败标识:{} ,失败原因：{} ==========", station.getName(), station.getStationCode(), responseVo.getRetCode(), responseVo.getRetMsg());
                log.info("{} 原始数据:{}", stationCode, body);
                record.setState(StatusEnum.FILE_NULL.getSign());
                record.setStateContent(responseVo.getRetMsg());
                recordService.save(record);
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }


    @Data
    public class WXPushCDqDataParamsDto {

        public WXPushCDqDataParamsDto(String stationIds, String genDate, List<DataPointDTO> data) {
            this.stationIds = stationIds;
            this.genDate = genDate;
            this.data = data;
        }

        /**
         * id
         */
        private String stationIds;
        /**
         * 生成日期
         */
        private String genDate;

        /**
         * 预测时间和数据
         */
        private List<DataPointDTO> data;

    }

    @Data
    public static class DataPointDTO {
        private String fpValue;
        private String forecastTime;
    }
}