package com.yeejoin.equipmanage.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yeejoin.equipmanage.common.entity.Car;
import com.yeejoin.equipmanage.common.entity.CarSpeedWarningRecord;
import com.yeejoin.equipmanage.common.entity.WlCarMileage;
import com.yeejoin.equipmanage.fegin.IotFeign;
import com.yeejoin.equipmanage.mapper.CarMapper;
import com.yeejoin.equipmanage.mapper.WlCarSpeedWaringRecordMapper;
import com.yeejoin.equipmanage.service.ICarService;
import com.yeejoin.equipmanage.service.IWlCarMileageService;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.component.emq.EmqKeeper;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

@Service
public class JxiopCarIotListerServiceImpl {
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private final String GUIDE_KEY = "8d2ab194d72e88d3636e9d721814333a";
    private final String GUIDE_URL = "https://restapi.amap.com/v3/geocode/regeo?";
    Logger logger = LoggerFactory.getLogger(JxiopCarIotListerServiceImpl.class);
    @Autowired
    private IWlCarMileageService iWlCarMileageService;
    @Autowired
    private CarMapper carMapper;
    @Autowired
    private IotFeign iotFeign;
    @Autowired
    private WlCarSpeedWaringRecordMapper wlCarSpeedWaringRecordMapper;
    @Value("${mileage.clippingtime:600000}")
    private Long clipping_time;
    @Value("${default.maxspeed:70.0}")
    private Double defaultMaxSpeed;
    @Autowired
    private EmqKeeper emqkeeper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private static ConcurrentHashMap<String,Object> cache = new ConcurrentHashMap<>();


    //    @Async("equipAsyncExecutor")
    public void processMessage(String topic, MqttMessage message) {
        String measurement = topic.split("/")[0];
        String deviceName = topic.split("/")[1];
        //根据topic 组装iotCode
        String iotCode = measurement + deviceName;
        //处理并发
        if(cache.get(iotCode)!=null)
        {
            return;
        }
        cache.put(iotCode,iotCode);
        try{
            JSONObject jsonObject = JSONObject.parseObject(message.toString());
            //判断是否有效坐标
            if (!ObjectUtils.isEmpty(jsonObject.get("FireCar_Longitude")) && !ObjectUtils.isEmpty(jsonObject.get("FireCar_Latitude"))) {
                // 获取开始坐标
                double startLongitude = jsonObject.getDoubleValue("FireCar_Longitude");
                double startLatitude = jsonObject.getDoubleValue("FireCar_Latitude");
                if(startLongitude==0||startLatitude==0)
                {
                    logger.info("新增数据无效坐标：：" + JSONObject.toJSONString(jsonObject));
                    return;
                }
                //判断是否存在未结束进程，如果不存在，则进入判断插入开始节点
                if (iWlCarMileageService.getUncompleteMileagByIotCode(iotCode)) {
                    WlCarMileage wlCarMileage = new WlCarMileage();
                    wlCarMileage.setIotCode(iotCode);
                    wlCarMileage.setDate(new Date());
                    // String currentTime = "20"+jsonObject.getString("currentTime");
                    wlCarMileage.setStartLongitude(startLongitude);
                    wlCarMileage.setStartLatitude(startLatitude);
                    // Date startTime = UTCToCST();
                    //时间值被mysql自动转换
                    Date startTime = new Date();
                    wlCarMileage.setStartTime(startTime);
                    wlCarMileage.setStartName(getAddress(startLongitude, startLatitude));
                    wlCarMileage.setStartSpeed(Double.valueOf(jsonObject.getDoubleValue("FireCar_Speed")).intValue());
                    logger.info("新增数据信息如下：：" + JSONObject.toJSONString(wlCarMileage));
                    try {
                        iWlCarMileageService.save(wlCarMileage);
                    } catch (Exception e) {
                        e.printStackTrace();
                        iWlCarMileageService.save(wlCarMileage);
                    }
                }
                this.updateCarLocation(jsonObject, iotCode);
                String coordinate = jsonObject.getString("FireCar_Longitude") + "," + jsonObject.getString("FireCar_Latitude");
                if (ObjectUtils.isEmpty(redisTemplate.opsForValue().get(iotCode))) {
                    redisTemplate.opsForValue().set(iotCode, coordinate, 5, TimeUnit.MINUTES);
                    //logger.info("首次入库redis:{}", iotCode);
                } else {
                    if (!String.valueOf(redisTemplate.opsForValue().get(iotCode)).equals(coordinate)) {
                        // logger.info("更新入库redis:{},旧:{},新:{}", iotCode, redisTemplate.opsForValue().get(iotCode), coordinate);
                        redisTemplate.opsForValue().set(iotCode, coordinate, 5, TimeUnit.MINUTES);
                    }
                }
            }
        }
        finally
        {
            cache.remove(iotCode);
        }
    }

    public String getAddress(double longitude, double lantitude) {
        StringBuilder api = new StringBuilder(GUIDE_URL);
        api.append("key=").append(GUIDE_KEY).append("&location=").append(longitude).append(",").append(lantitude).append("&radius=1000").append("&batch=false").append("&extensions=base").append("&roadlevel=0").append("&batch=false");
        StringBuilder res = new StringBuilder();
        BufferedReader in = null;
        try {
            URL url = new URL(api.toString());
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setDoOutput(true);
            conn.setRequestMethod("POST");
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
            String line;
            while ((line = in.readLine()) != null) {
                res.append(line).append("\n");
            }
            JSONObject object = JSONObject.parseObject(res.toString());
            System.out.println(object);
            JSONObject regeocode = object.getJSONObject("regeocode");
            String address = regeocode.getString("formatted_address");
            if ("[]".equals(address)) {
                logger.info("===============无效坐标:" + longitude + "," + lantitude);
                address = "无效坐标";
            }
            res = new StringBuilder(address);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return res.toString();
    }

    public Date UTCToCST(String UTCStr) throws ParseException {
        Date date = sdf.parse(UTCStr);
        System.out.println("UTC时间: " + date);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR, calendar.get(Calendar.HOUR) + 8);
        return calendar.getTime();
    }

    public void updateCarLocation(JSONObject jsonObject, String iotCode) {
        if (jsonObject.containsKey("FireCar_Longitude") && jsonObject.containsKey("FireCar_Latitude")) {
            // 获取开始坐标
            double startLongitude = jsonObject.getDoubleValue("FireCar_Longitude");
            double startLatitude = jsonObject.getDoubleValue("FireCar_Latitude");
            int direction = jsonObject.getIntValue("direction");
            String waringDate = jsonObject.getString("createdTime");
            Double speed = jsonObject.getDoubleValue("fireCar_Speed") > 0 ? jsonObject.getDoubleValue("fireCar_Speed") : jsonObject.getDoubleValue("FireCar_Speed");
            Double maxSpeed = 70.0;
            Integer power = 0;
            if (jsonObject.containsKey("additionalInformations") && jsonObject.get("additionalInformations") != null) {
                JSONObject jsonObject1 = JSONObject.parseObject(jsonObject.get("additionalInformations").toString());
                if (jsonObject1 != null) {
                    JSONObject jsonObject2 = JSONObject.parseObject(jsonObject1.get("additionalInformations").toString());
                    if (jsonObject2 != null && jsonObject2.containsKey("power")) {
                        power = jsonObject2.getInteger("power");
                    }
                }
            }
            // 地图推送消息
            Car car = carMapper.selectOne(new LambdaQueryWrapper<Car>().eq(Car::getIotCode, iotCode));
            if (car != null && startLongitude != 0 && startLatitude != 0) {
                JSONArray sendArr = new JSONArray();
                JSONObject sendObj = new JSONObject();
                sendObj.put("id", String.valueOf(car.getId()));
                sendObj.put("direction", direction);
                sendObj.put("longitude", String.valueOf(startLongitude));
                sendObj.put("latitude", String.valueOf(startLatitude));
                sendObj.put("carNum", car.getCarNum());
                sendObj.put("bizOrgName", car.getBizOrgName());
                sendArr.add(sendObj);
//                MqttMessage mqttMessage = new MqttMessage();
//                mqttMessage.setPayload(sendArr.toJSONString().getBytes());

                car.setLongitude(startLongitude);
                car.setLatitude(startLatitude);
                if (!ObjectUtils.isEmpty(car.getMaxSpeed())) {
                    maxSpeed = car.getMaxSpeed();
                }
                car.setExtra2(power.toString());
                //logger.info("----------------更新车辆电池电量信息成功----------------");
                carMapper.updateById(car);
                //logger.info("车牌号：：" + car.getCarNum() + "最大车速：" + maxSpeed + "当前车速::" + speed);
                if ((speed - maxSpeed) > 0) {
                    List<CarSpeedWarningRecord> list = wlCarSpeedWaringRecordMapper.selectList(new QueryWrapper<CarSpeedWarningRecord>().eq("car_num", car.getCarNum()).
                            between("waring_date", DateUtil.offsetMinute(new Date(), -10), new Date()));
                    if (!(list.size() > 0)) {
                        CarSpeedWarningRecord carSpeedWarningRecord = new CarSpeedWarningRecord();
                        carSpeedWarningRecord.setCarNum(car.getCarNum());
                        carSpeedWarningRecord.setDriver(car.getDriver());
                        carSpeedWarningRecord.setPhone(car.getPhone());
                        carSpeedWarningRecord.setOverSpeed(speed - maxSpeed);
                        carSpeedWarningRecord.setOwnership(car.getOwnership());
                        carSpeedWarningRecord.setBizOrgName(car.getBizOrgName());
                        carSpeedWarningRecord.setWaringDate(DateUtil.parse(waringDate, DatePattern.NORM_DATETIME_PATTERN));
                        carSpeedWarningRecord.setWaringDateMinute(DateUtil.format(carSpeedWarningRecord.getWaringDate(), DatePattern.NORM_DATETIME_MINUTE_PATTERN));
                        carSpeedWarningRecord.setOverSpeedCount(1);
                        if((speed-maxSpeed)<maxSpeed){
                            wlCarSpeedWaringRecordMapper.insert(carSpeedWarningRecord);
                        }
                        logger.info("-----------触发车辆超速告警成功--------");
                    } else {
                        CarSpeedWarningRecord carSpeedWarningRecord = list.get(0);
                        if (!carSpeedWarningRecord.getWaringDateMinute().equals(DateUtil.parse(waringDate, DatePattern.NORM_DATETIME_MINUTE_PATTERN))) {
                            carSpeedWarningRecord.setOverSpeedCount(carSpeedWarningRecord.getOverSpeedCount() + 1);
                            carSpeedWarningRecord.setWaringDate(DateUtil.parse(waringDate, DatePattern.NORM_DATETIME_PATTERN));
                            carSpeedWarningRecord.setWaringDateMinute(DateUtil.format(carSpeedWarningRecord.getWaringDate(), DatePattern.NORM_DATETIME_MINUTE_PATTERN));
                            if((speed-maxSpeed)<maxSpeed){
                                carSpeedWarningRecord.setOverSpeed(speed - maxSpeed);
                            }
                            wlCarSpeedWaringRecordMapper.updateById(carSpeedWarningRecord);
                        }
                        logger.info("-----------更新车辆超速告警成功--------");
                    }
                }
              //  logger.info("-----------推送车辆位置消息到到地图成功--------");
//                try {
//                    emqkeeper.getMqttClient().publish("car/location", sendArr.toJSONString().getBytes(), 0, false);
//                } catch (MqttException e) {
//                    e.printStackTrace();
//                }
            }
        }
    }

//    //存储设备电量到扩展字段2
//    public void updateEquipBattery(JSONObject jsonObject, String iotCode) {
//        Integer power = 0;
//        if (jsonObject.containsKey("additionalInformations") && jsonObject.get("additionalInformations") != null) {
//            JSONObject jsonObject1 = JSONObject.parseObject(jsonObject.get("additionalInformations").toString());
//            if (jsonObject1 != null) {
//                JSONObject jsonObject2 = JSONObject.parseObject(jsonObject1.get("additionalInformations").toString());
//                if (jsonObject2 != null && jsonObject2.containsKey("power")) {
//                    power = jsonObject2.getInteger("power");
//                }
//            }
//        }
//
//        Car car = iCarService.getOne(new LambdaQueryWrapper<Car>().eq(Car::getIotCode, iotCode));
//        if (car != null && power != 0) {
//            car.setExtra2(power.toString());
//            iCarService.updateById(car);
//            logger.info(iotCode + "-----------更新车辆设备电池电量成功--------");
//        }
//    }
}
