package com.songhua.web.quzrtz;


import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.songhua.common.constant.Constants;
import com.songhua.common.core.domain.AjaxResult;
import com.songhua.common.core.redis.RedisCache;
import com.songhua.system.domain.GPSEquipment;
import com.songhua.system.domain.HistoryGpsData;
import com.songhua.system.domain.dto.ShipSaveDTO;
import com.songhua.system.service.IBasicCruiseShipService;
import com.songhua.system.service.ICruiseShipMappingService;
import com.songhua.system.service.ISysConfigService;
import com.songhua.system.service.impl.BasicCruiseShipServiceImpl;
import com.songhua.web.controller.utils.MD5Encryptor;
import com.songhua.web.controller.utils.URLEncodeExampleUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.songhua.common.core.domain.AjaxResult.error;
import static com.songhua.common.core.domain.AjaxResult.success;


@Slf4j
@Component("gpsJob")
public class gpsJob {

    @Autowired
    private ICruiseShipMappingService cruiseShipMappingService;
    @Autowired
    private ISysConfigService configService;
    @Autowired
    private IBasicCruiseShipService basicCruiseShipService;
    @Autowired
    private RedisCache redisCache;
    private final List<String> keys = Arrays.asList("gps_address", "app_key", "app_secret", "account", "password");

    /**
     * 获取访问令牌
     */
    public AjaxResult getToken() {
        Date date = new Date();
        String format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
        String dateStr = format.replace(" ", "%20");
        Map<String, String> configMap = getStringStringMap();
        String password = MD5Encryptor.md5EncryptToLowercase(configMap.get("password"));
        String sign = MD5Encryptor.md5EncryptToUppercase(configMap.get("app_secret") +
                "account" + configMap.get("account") +
                "app_key" + configMap.get("app_key") +
                "formatjsonmethodwicare.user.access_token" +
                "password" + password +
                "sign_methodmd5" +
                "timestamp" + dateStr +
                "type2v2.0" +
                configMap.get("app_secret"));
        String apiUrl = configMap.get("gps_address") +
                "account=" + configMap.get("account") +
                "&app_key=" + configMap.get("app_key") +
                "&format=json&method=wicare.user.access_token&" +
                "password=" + password +
                "&sign_method=md5&" +
                "timestamp=" + dateStr +
                "&type=2&v=2.0&" +
                "sign=" + sign;
        try {
            // 创建 URL 对象
            URL url = new URL(apiUrl);
            // 打开连接
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            // 设置请求方法
            connection.setRequestMethod("GET");
            // 获取响应状态码
            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                // 读取响应内容
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                String line;
                StringBuilder response = new StringBuilder();
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
                reader.close();
                // 存入redis中
                redisCache.setCacheObject("access_token", JSONObject.parseObject(response.toString()).get("access_token"), Constants.GPS_ACCESS_TOKEN_EXPIRATION, TimeUnit.MINUTES);
                return success(JSONObject.parseObject(response.toString()).get("access_token"));
            } else {
                log.error("获取访问令牌接口返回错误代码:{}", responseCode);
            }
            // 关闭连接
            connection.disconnect();
        } catch (Exception e) {
            log.error("获取访问令牌接口失败:{}", e);
            e.printStackTrace();
        }
        return error("获取访问令牌接口失败");
    }

    /**
     * 获取单个设备或多个设备的信息
     */
//    @Scheduled(cron = "0 0/2 * * * ?")
    public void getEquipment() {
        log.info("获取单个设备或多个设备的信息开始");
        AjaxResult result;
        Object obj;
        if (!redisCache.hasKey("access_token")) {
            result = getToken();
            obj = result.get("data");
        } else {
            obj = redisCache.getCacheObject("access_token");
        }

        Date date = new Date();
        String format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
        Map<String, String> configMap = getStringStringMap();
        String dateStr = format.replace(" ", "%20");
        String sign = MD5Encryptor.md5EncryptToUppercase(configMap.get("app_secret") +
                "access_token" + obj +
                "app_key" + configMap.get("app_key") +
                "dev_key59346d400236ab95e95193f35f3df6a4" +
                "fieldsdid,activeGpsDataformatjsonlimit-1mapBAIDU" +
                "methodwicare.device.listpagedidpage_no1sign_methodmd5sortsdid" +
                "timestamp" + dateStr +
                "v2.0" +
                configMap.get("app_secret"));
        log.info("singStr:{}",configMap.get("app_secret") +
                "access_token" + obj +
                "app_key" + configMap.get("app_key") +
                "dev_key59346d400236ab95e95193f35f3df6a4" +
                "fieldsdid,activeGpsDataformatjsonlimit-1mapBAIDU" +
                "methodwicare.device.listpagedidpage_no1sign_methodmd5sortsdid" +
                "timestamp" + dateStr +
                "v2.0" +
                configMap.get("app_secret"));
        log.info("sign:{}",sign);
        String apiUrl = configMap.get("gps_address") +
                "timestamp=" + dateStr +
                "&format=json&" +
                "app_key=" +
                configMap.get("app_key") +
                "&v=2.0&sign_method=md5&method=wicare.device.list&dev_key=59346d400236ab95e95193f35f3df6a4&access_token=" + URLEncodeExampleUtil.URLEncodeExample(obj) +
                "&map=BAIDU&fields=did,activeGpsData&sorts=did&page=did&page_no=1&limit=-1&sign=" +
                sign;
        log.info("apiUrl:{}",apiUrl);
        log.info("URLEncodeExampleUtil.URLEncodeExample(obj):{}",URLEncodeExampleUtil.URLEncodeExample(obj));
        try {
            // 创建 URL 对象
            URL url = new URL(apiUrl);
            // 打开连接
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            // 设置请求方法
            connection.setRequestMethod("GET");
            // 获取响应状态码
            int responseCode = connection.getResponseCode();
            log.info("connection.getResponseMessage():{}", connection.getResponseMessage());
            log.info("connection:{}", connection);
            if (responseCode == HttpURLConnection.HTTP_OK) {
                // 读取响应内容
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                String line;
                StringBuilder response = new StringBuilder();
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
                log.info("获取单个设备或多个设备的信息返回信息:{}", response);
                reader.close();
                List<GPSEquipment> objectList = JSONArray.parseArray(JSONObject.parseObject(response.toString()).getString("data").toString(), GPSEquipment.class);
                List<ShipSaveDTO> saveList = new ArrayList<>();
                for (GPSEquipment var : objectList) {
                    ShipSaveDTO saveEntity = new ShipSaveDTO();
                    saveEntity.setDid(var.getDid());
                    saveEntity.setLongitude(String.valueOf(var.getActiveGpsData().getLon()));
                    saveEntity.setLatitude(String.valueOf(var.getActiveGpsData().getLat()));
                    saveEntity.setGpsFlag(var.getActiveGpsData().getGpsFlag());
                    saveEntity.setLon(var.getActiveGpsData().get_lon());
                    saveEntity.setLat(var.getActiveGpsData().get_lat());
                    saveEntity.setSignal(var.getActiveGpsData().getSignal());
                    saveEntity.setSpeed(var.getActiveGpsData().getSpeed());
                    saveEntity.setDirect(var.getActiveGpsData().getDirect());
                    saveEntity.setMileage(var.getActiveGpsData().getMileage());
                    saveEntity.setBattery(var.getActiveGpsData().getBattery());
                    saveEntity.setPower(var.getActiveGpsData().getPower());
                    saveEntity.setStatus(String.join(",", var.getActiveGpsData().getStatus().stream().map(String::valueOf).collect(Collectors.toList())));
                    saveEntity.setAlerts(String.join(",", var.getActiveGpsData().getAlerts().stream().map(String::valueOf).collect(Collectors.toList())));
                    saveEntity.setGpsTime(var.getActiveGpsData().getGpsTime());
                    saveEntity.setRcvTime(var.getActiveGpsData().getRcvTime());
                    saveList.add(saveEntity);
                }
                if (!CollectionUtils.isEmpty(saveList)) {
                    cruiseShipMappingService.saveCruiseShipMapping(saveList);
                }
            } else {
                log.error("获取单个设备或多个设备的信息返回错误代码:{}", responseCode);
            }
            // 关闭连接
            connection.disconnect();
        } catch (Exception e) {
            log.error("获取单个设备或多个设备的信息接口失败:{}", e);
            e.printStackTrace();
        }
        log.info("获取单个设备或多个设备的信息结束");
    }

    /**
     * 获取设备历史定位数据信息
     */
//    @Scheduled(cron = "0 0/1 * * * ?")
    public void getShipLocation() {
        log.info("获取设备历史定位数据信息开始");
        AjaxResult result;
        Object obj;
        if (!redisCache.hasKey("access_token")) {
            result = getToken();
            obj = result.get("data");
        } else {
            obj = redisCache.getCacheObject("access_token");
        }
        Date date = new Date();
        String format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
        Map<String, String> configMap = getStringStringMap();
        String dateStr = format.replace(" ", "%20");
        List<Long> didList = basicCruiseShipService.selectDidList();
        for (Long var : didList){
            log.info("获取" + var + "设备历史定位数据信息开始");
            String sign = MD5Encryptor.md5EncryptToUppercase(configMap.get("app_secret") +
                    "access_token" + obj +
                    "app_key" + configMap.get("app_key") +
                    "dev_key59346d400236ab95e95193f35f3df6a4" +
                    "did" + var +
                    "fieldsdid,lon,lat,speed,direct,gpsTime,rcvTimeformatjsonlimit-1mapBAIDUmethodwicare.gpsdata.listpagedidpage_no1sign_methodmd5sortsdid" +
                    "timestamp" + dateStr +
                    "v2.0" +
                    configMap.get("app_secret"));
            String apiUrl = configMap.get("gps_address") +
                    "timestamp=" + dateStr +
                    "&format=json&" +
                    "app_key=" + configMap.get("app_key") +
                    "&v=2.0&sign_method=md5&method=wicare.gpsdata.list&dev_key=59346d400236ab95e95193f35f3df6a4&" +
                    "access_token=" + obj +
                    "&map=BAIDU&fields=did,lon,lat,speed,direct,gpsTime,rcvTime&sorts=did&page=did&page_no=1&limit=-1&" +
                    "sign=" + sign +
                    "&did=" + var;
            try {
                // 创建 URL 对象
                URL url = new URL(apiUrl);
                // 打开连接
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                // 设置请求方法
                connection.setRequestMethod("GET");
                // 获取响应状态码
                int responseCode = connection.getResponseCode();
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    // 读取响应内容
                    BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                    String line;
                    StringBuilder response1 = new StringBuilder();
                    while ((line = reader.readLine()) != null) {
                        response1.append(line);
                    }
                    reader.close();
                    List<HistoryGpsData> objectList = JSONArray.parseArray(JSONObject.parseObject(response1.toString()).getString("data").toString(), HistoryGpsData.class);
                    if (!CollectionUtils.isEmpty(objectList)) {
                        int totalCount = objectList.size();
                        int batchSize = 500;  // 每次批量操作的数量
                        int roundCount = (totalCount + batchSize - 1) / batchSize;

                        for (int i = 0; i < roundCount; i++) {
                            int startIndex = i * batchSize;
                            int endIndex = Math.min((i + 1) * batchSize, totalCount);
                            List<HistoryGpsData> batchUserList = objectList.subList(startIndex, endIndex);
                            cruiseShipMappingService.saveEquipmentHistoryLocation(batchUserList);
                        }
                    }
                } else {
                    log.error("获取设备历史定位数据信息返回错误代码:{}", responseCode);
                }
                // 关闭连接
                connection.disconnect();
            } catch (Exception e) {
                log.error("获取设备历史定位数据信息接口失败:{}", e);
                e.printStackTrace();
            }
        }
        log.info("获取设备历史定位数据信息结束");
    }

    /**
     * 根据参数编号获取详细信息
     *
     * @return
     */
    private Map<String, String> getStringStringMap() {
        Map<String, String> configMap = configService.getConfigMap(keys);
        return configMap;
    }

}
