package com.lutao.cloud.oil.typhoon;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.util.DateUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.ImmutableMap;
import com.lutao.cloud.oil.pojo.entity.TyphoonInfo;
import com.lutao.cloud.oil.pojo.entity.TyphoonPointInfo;
import com.lutao.cloud.oil.service.TyphoonInfoService;
import com.lutao.cloud.oil.service.TyphoonPointInfoService;
import com.lutao.cloud.oil.typhoon.BusiConstant;
import com.lutao.cloud.oil.typhoon.DataAPIUtils;
import com.lutao.cloud.oil.typhoon.TyphoonFindBhList;
import com.lutao.cloud.oil.util.DoubleUtils;
import com.lutao.cloud.oil.util.JsonUtils;
import com.lutao.entity.ProcessParameterTag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.LocalDate;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.lutao.cloud.oil.pojo.entity.TyphoonPointInfo.REALLY_TYPE;

@Component
@Slf4j
public class TyphoonFindTyphoonSyn {

    @Resource
    private TyphoonPointInfoService typhoonPointInfoService;

    @Resource
    private TyphoonInfoService typhoonInfoService;

    @Resource(name = "redisTemplateAlias")
    private RedisTemplate redisTemplate;

    private static final String LOCK_KEY = "scheduled_task_lock:TyphoonFindTyphoonSyn";

    private boolean acquireLock() {
        // 尝试获取锁，设置超时时间为 1 分钟
        return Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(LOCK_KEY, "locked", 1, TimeUnit.MINUTES));
    }

    private void releaseLock() {
        // 释放锁
        redisTemplate.delete(LOCK_KEY);
    }

    @Scheduled(cron = "0 0 * * * ?")// 每小时执行一次
    public void run() {
        if (acquireLock()) {
            try {
                log.info("TyphoonFindTyphoonSyn run 定时任务启动");
                String year = String.valueOf(LocalDate.now().getYear());
                syncData(year);
            } catch (Exception e) {
                e.printStackTrace();
                log.error("errorMsg:{}", e.getMessage());
            } finally {
                releaseLock();
            }
        }

    }

    private Integer syncData(String str) {
        //logger.debug("threadName:{}", threadName);
        try {
            return syncDataInfo(str);
        } catch (Exception e) {
            // 仅补偿一次
            log.error("errorMsg:{}", e.getMessage());
            e.printStackTrace();
            try {
                return this.syncDataInfo(str);
            } catch (Exception e2) {
                e2.printStackTrace();
            }
            return 0;
        }
    }

    public Integer syncDataInfo(String str) throws Exception {

        //logger.debug("TyphoonFindBhListThread threadName:{}， param:{}", threadName, str);

        URL realUrl = new URL("http://" + BusiConstant.IP_59_255_61_5 + ":" + BusiConstant.PORT_9090 + "/service/api/typhoon/findBhList");

        // 打开和URL之间的连接
        HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
        conn.setRequestProperty("content-type", "application/json");
        conn.setRequestProperty("client_id", BusiConstant.APP_USER_NAME_01);
        conn.setRequestProperty("access_token", DataAPIUtils.getSyncTokenIP59255615());
        conn.setRequestMethod("POST"); // 设定请求的方法为"POST"，默认是GET
        // 发送POST请求必须设置如下两行
        conn.setReadTimeout(1000 * 60);
        conn.setConnectTimeout(1000 * 60);
        conn.setDoOutput(true); // 允许输入流，即允许下载
        conn.setDoInput(true); // 允许输出流，即允许上传

        // 获取URLConnection对象对应的输出流
        PrintWriter out = new PrintWriter(conn.getOutputStream());

        out.print(JSONUtil.toJsonStr(ImmutableMap.of("iscurrent", "-1", "year", str))); // 发送请求参数
        out.flush(); // flush输出流的缓冲

        InputStream is = conn.getInputStream();
        BufferedReader bf = new BufferedReader(new InputStreamReader(is));
        String line;
        String result = "";
        while ((line = bf.readLine()) != null) {
            result += line;
        }

        JSONObject jsonObject = JSONUtil.parseObj(result);
        JSONArray jsonArray = jsonObject.getJSONArray("data");
        List<TyphoonFindBhList> insertList = jsonArray.toList(TyphoonFindBhList.class);

        for (TyphoonFindBhList typhoonFindBhList : insertList) {
            TyphoonInfo typhoonInfo = new TyphoonInfo();
            typhoonInfo.setCode(typhoonFindBhList.getTfbh());
            typhoonInfo.setCnName(typhoonFindBhList.getCname());
            typhoonInfo.setEnName(typhoonFindBhList.getEname());
            typhoonInfo.setBeginTime(typhoonFindBhList.getBegintime());
            typhoonInfo.setEndTime(typhoonFindBhList.getEndtime());
            typhoonInfo.setYear(typhoonFindBhList.getYear());
            if (typhoonInfoService.count(Wrappers.lambdaQuery(TyphoonInfo.class).eq(TyphoonInfo::getCode, typhoonInfo.getCode())) > 0) {
                // 存在先更新
                typhoonInfoService.update(typhoonInfo, Wrappers.lambdaQuery(TyphoonInfo.class).eq(TyphoonInfo::getCode, typhoonInfo.getCode()));
            } else {
                typhoonInfoService.save(typhoonInfo);
            }
        }

        // 查询未结束台风信息
        List<TyphoonFindBhList> noEndTy = insertList.stream().filter(typhoonFindBhList -> typhoonFindBhList.getEndtime() == null).collect(Collectors.toList());

        //点位
        if (!CollectionUtils.isNotEmpty(noEndTy)) {
            return 0;
        }

        // 获取点位信息
        for (TyphoonFindBhList po : noEndTy) {
            pointInfos(po);
        }

        return insertList.size();
    }

    /**
     * @Description: 点位处理
     * @Param: [com.lutao.cloud.oil.typhoon.TyphoonFindBhList]
     * @Return: void
     * @Author: vincent.zhao
     * @Date: 2024/9/4 16:23
     */
    private void pointInfos(TyphoonFindBhList po) {

        // TODO: 2024/8/19 查询点位信息并且入库
        String url = "http://" + BusiConstant.IP_59_255_61_5 + ":" + BusiConstant.PORT_9090 + "/service/api/typhoon/findTyphoon"; // 替换为实际的 URL
        log.info(url);
        String client_id = BusiConstant.APP_USER_NAME_01;
        String access_token = DataAPIUtils.getSyncTokenIP59255615();

        Map<String, String> headers = new HashMap<>();
        headers.put("content-type", "application/json");
        headers.put("client_id", client_id);
        headers.put("access_token", access_token);
        JSONObject newRequestBody = JSONUtil.createObj().putOnce("tfbh", po.getTfbh());
        // 使用 Hutool 发送 POST 请求
        String body = HttpUtil.createPost(url)
                .header("client_id", client_id)
                .header("access_token", access_token)
                .body(newRequestBody.toString())
                .execute().body();

        JSONArray pointDataArray = JSONUtil.parseObj(body).getJSONArray("data");
        for (Object o : pointDataArray) {
            JSONObject typoint = JSONUtil.parseObj(o);
            JSONArray pointses = typoint.getJSONArray("pointses");
            if (pointses == null || pointses.size() <= 0) {
                return;
            }

            typhoonPointInfoService.remove(Wrappers.lambdaQuery(TyphoonPointInfo.class).eq(TyphoonPointInfo::getCode, typoint.getStr("tfbh")));

            // 点位列表
            List<TyphoonPointInfo> typhoonPointInfoList = Lists.newArrayList();

            for (Object points : pointses) {
                JSONObject point = JSONUtil.parseObj(points);

                TyphoonPointInfo typhoonPointInfo = new TyphoonPointInfo();
                typhoonPointInfo.setTyphoonId(po.getTfbh());
                typhoonPointInfo.setCode(po.getTfbh());
                typhoonPointInfo.setLon(point.getDouble("lng"));
                typhoonPointInfo.setLat(point.getDouble("lat"));
                typhoonPointInfo.setMoveSpeed(point.getStr("movespeed"));

                /**
                 *              "tfbh": "202409",
                 *                     "forecast": "[]",
                 *                     "lat": 27.2,
                 *                     "lng": 125.9,
                 *                     "movedir": "北",
                 *                     "movespeed": "29",
                 *                     "power": 8,
                 *                     "pressure": 998,
                 *                     "radius7": "100-200",
                 *                     "radius7quad": "{\"se\":200,\"sw\":120,\"ne\":200,\"nw\":100}",
                 *                     "radius10": null,
                 *                     "radius10quad": null,
                 *                     "radius12": null,
                 *                     "radius12quad": null,
                 *                     "remark": null,
                 *                     "speed": 18,
                 *                     "strong": "热带风暴(TS)",
                 *                     "time": "2024-08-19 18:17:00",
                 *                     "startencodedate": null,
                 *                     "startencodetime": null,
                 *                     "forecastperiod":
                 */
                typhoonPointInfo.setMoveDir(point.getStr("movedir"));
                typhoonPointInfo.setPower(point.getDouble("power"));
                typhoonPointInfo.setPressure(point.getDouble("pressure"));
                typhoonPointInfo.setRadius7(point.getStr("radius7"));
                typhoonPointInfo.setRadius10(point.getStr("radius10"));
                typhoonPointInfo.setRadius12(point.getStr("radius12"));
                typhoonPointInfo.setSpeed(point.getDouble("speed"));
                typhoonPointInfo.setStrong(point.getStr("strong"));
                typhoonPointInfo.setTime(point.getStr("time"));
                typhoonPointInfo.setType(TyphoonPointInfo.REALLY_TYPE);

                typhoonPointInfoList.add(typhoonPointInfo);

            }

            // 找到最新的预测路径
            JSONArray forecast = null; // 最新记录的未来点位
            for (Object points : pointses) {
                JSONObject point = JSONUtil.parseObj(points);
                // 保存最新的点位预测
                if (point.getJSONArray("forecast") != null && point.getJSONArray("forecast").size()>0) {
                    forecast = point.getJSONArray("forecast");
                    break;
                }
            }

            // 倒序（由远到近）
            Collections.reverse(typhoonPointInfoList);

            for (int i = 0; i < forecast.size(); i++) {

                JSONObject point = JSONUtil.parseObj(forecast.get(i));
                TyphoonPointInfo typhoonPointInfo = new TyphoonPointInfo();
                typhoonPointInfo.setTyphoonId(po.getTfbh());
                typhoonPointInfo.setCode(po.getTfbh());
                typhoonPointInfo.setLon(point.getDouble("lng"));
                typhoonPointInfo.setLat(point.getDouble("lat"));
                typhoonPointInfo.setPower(point.getDouble("power"));
                typhoonPointInfo.setPressure(point.getDouble("pressure"));
                typhoonPointInfo.setSpeed(point.getDouble("speed"));
                typhoonPointInfo.setStrong(point.getStr("strong"));
                typhoonPointInfo.setTime(point.getStr("time"));
                TyphoonPointInfo preTyphoonPointInfo = typhoonPointInfoList.get(typhoonPointInfoList.size() - 1);
                double minutes = DoubleUtils.calculateTravelTime(preTyphoonPointInfo.getLat(), preTyphoonPointInfo.getLon(), typhoonPointInfo.getLat(), typhoonPointInfo.getLon(), typhoonPointInfo.getSpeed() / 60);
                DateTime arrivedTime = DateUtil.offsetMinute(DateUtil.parseDateTime(preTyphoonPointInfo.getTime()), (int) minutes);
                typhoonPointInfo.setTime(DateUtils.format(arrivedTime, "yyyy-MM-dd HH:mm:ss"));
                typhoonPointInfoList.add(typhoonPointInfo);

            }
            typhoonPointInfoService.saveBatch(typhoonPointInfoList);
        }


    }


}
