package com.ningdatech.carapi.irs.task;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.carapi.car.vehicle.model.NdVehicleBaseInfo;
import com.ningdatech.carapi.car.vehicle.service.IVehicleBaseInfoService;
import com.ningdatech.carapi.common.constant.MissCertEnum;
import com.ningdatech.carapi.common.constant.ViolationTypeEnum;
import com.ningdatech.carapi.driver.entity.DriverInfo;
import com.ningdatech.carapi.driver.service.IDriverInfoService;
import com.ningdatech.carapi.irs.model.entity.VehicleViolationIrsData;
import com.ningdatech.carapi.irs.service.CarService;
import com.ningdatech.carapi.irs.service.IVehicleViolationIrsDataService;
import com.ningdatech.carapi.safe.entity.NdVehicleViolation;
import com.ningdatech.carapi.safe.service.INdVehicleViolationService;
import com.ningdatech.carapi.scheduler.contants.TaskConstant;
import com.ningdatech.carapi.sys.entity.Company;
import com.ningdatech.carapi.sys.helper.RegionsCacheHelper;
import com.ningdatech.carapi.sys.service.CompanyService;
import com.ningdatech.file.utils.StrPool;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.date.StopWatch;
import cn.hutool.core.io.FileUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
 * @author CMM
 * @description
 * @since 2023/05/21 15:38
 */
@Component
@Slf4j
@Data
public class MyVehicleIllegalQueryTask implements Runnable {

    private final IVehicleBaseInfoService vehicleBaseInfoService;
    private final CarService carService;
    private final IVehicleViolationIrsDataService violationIrsDataService;
    private final CompanyService companyService;
    private final RegionsCacheHelper regionsCacheHelper;
    private final INdVehicleViolationService vehicleViolationService;
    private final IDriverInfoService driverInfoService;

    /**
     * 无驾驶证违法行为code列表
     */
    private static final List<String> NO_DRIVING_LICENSE_LIST =
        Arrays.asList("5075", "5072", "5077", "5057", "10159", "1082", "70619", "6018", "7503", "7504", "7006", "70069",
            "1015", "16444", "1644", "50411", "60182", "8005", "80059", "8605", "5603", "5703", "1610", "5041", "60541",
            "1110", "7061", "10050", "10051", "10052", "10059", "1006", "1010", "10109", "1013", "1014", "6086", "5006",
            "1005", "56031", "60181", "57021", "57031", "1704", "1701");

    /**
     * 无行驶证违法行为code列表
     */
    private static final List<String> NO_VEHICLE_LICENSE_LIST = Arrays.asList("5071", "5069", "1088", "5702", "5705",
        "7216", "7218", "1109", "6085", "5003", "57051", "50031", "57021", "5009", "5015");

    /**
     * 闯红灯(违反交通信号灯)
     */
    private static final List<String> VIOLATION_TRAFFIC_LIGHTS_LIST = Arrays.asList("13029", "1625", "16259", "1302");

    /**
     * 违规时段行驶
     */
    private static final List<String> VIOLATION_TIME_LIST = Arrays.asList("8025");

    /**
     * 违规路段行驶
     */
    private static final List<String> VIOLATION_ROAD_LIST =
        Arrays.asList("1048", "10489", "40099", "8004", "8803", "11229", "8005J", "8002", "8048", "4009", "10393",
            "10397", "1045", "10459", "1310", "13109", "1023", "10239", "8005", "8001C", "1122", "8014");

    /**
     * 接口访问次数限制
     */
    private Integer BIGGEST_ACCESS_NUM = 2950;
    /**
     * 存储数据下标的文件名
     */
    private String VEHICLE_ILLEGAL_QUERY_INDEX_FILE = "vehicleIllegalIndex.txt";
    /**
     * 上次中断的车牌号下标
     */
    private Long lastIndex = 0L;
    /**
     * 上次执行的次数
     */
    private Integer lastCount = 0;
    /**
     * 是否继续执行任务
     */
    private boolean isRunning = true;

    public MyVehicleIllegalQueryTask(IVehicleBaseInfoService vehicleBaseInfoService, CarService carService,
        IVehicleViolationIrsDataService violationIrsDataService, CompanyService companyService,
        RegionsCacheHelper regionsCacheHelper, INdVehicleViolationService vehicleViolationService,
        IDriverInfoService driverInfoService) {
        this.vehicleBaseInfoService = vehicleBaseInfoService;
        this.carService = carService;
        this.violationIrsDataService = violationIrsDataService;
        this.companyService = companyService;
        this.regionsCacheHelper = regionsCacheHelper;
        this.vehicleViolationService = vehicleViolationService;
        this.driverInfoService = driverInfoService;
    }

    @Override
    public void run() {
        log.info("========== 根据IRS更新车辆违法数据 ==========任务开始");
        // 判断当前执行任务的时间是否为月初的1号 如果是月初1号,任务应该从下标1重新开始跑
        LocalDateTime now = LocalDateTime.now();
        int dayOfMonth = now.getDayOfMonth();
        if (TaskConstant.Data.MONTH_VALUE_ONE.equals(dayOfMonth)){
            // 重置文件中的下标
            saveLastIndex(1L, 0);
        }
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        while (isRunning) {
            // 读取上次中断的数据下标和和已经执行的次数
            readLastIndex();
            log.info("读取到的下标为{}", lastIndex);
            log.info("已访问接口次数{}", lastCount);
            Map<Long, String> infoMap =
                    vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class)
                                    .select(NdVehicleBaseInfo::getId,NdVehicleBaseInfo::getCarPlate))
                            .stream().collect(Collectors.toMap(NdVehicleBaseInfo::getId, NdVehicleBaseInfo::getCarPlate));
            OptionalLong maxKey = infoMap.keySet().stream().mapToLong(Long::longValue).max();
            Long maxIndex = null;
            if (maxKey.isPresent()){
                maxIndex = maxKey.getAsLong();
            }
            // 校验文件中存储的下标对应的车牌号是否一致
            String carNo;
            carNo = infoMap.get(lastIndex);
            while (Objects.isNull(carNo)) {
                log.error("车辆id{}不存在,请检查该车辆信息是否已经被删除!", lastIndex);
                // 查找下一个车辆信息,直到车辆信息存在
                lastIndex++;
                if (Objects.nonNull(maxIndex) && lastIndex.compareTo(maxIndex) > 0){
                    log.info("系统中没有待查询的车牌号");
                    return;
                }
                carNo = infoMap.get(lastIndex);
            }

            // 从车辆信息表中从上次执行中断的下标获取一定数量的车牌号
            int cnt = BIGGEST_ACCESS_NUM - lastCount;
            LambdaQueryWrapper<NdVehicleBaseInfo> query =
                Wrappers.lambdaQuery(NdVehicleBaseInfo.class)
                    .ge(NdVehicleBaseInfo::getId, lastIndex)
                    .last("limit " + cnt)
                    .select(NdVehicleBaseInfo::getCarPlate, NdVehicleBaseInfo::getId)
                    .isNotNull(NdVehicleBaseInfo::getCarPlate);
            List<NdVehicleBaseInfo> list = vehicleBaseInfoService.list(query);
            log.info("此次任务车辆数量为:" + list.size());
            if (CollUtil.isNotEmpty(list)) {
                List<String> carPlateList = list.stream().sorted(Comparator.comparing(NdVehicleBaseInfo::getId))
                    .map(NdVehicleBaseInfo::getCarPlate).collect(Collectors.toList());
                Map<String, Long> carMap = list.stream().collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, NdVehicleBaseInfo::getId));
                String[] carPlates = carPlateList.stream().toArray(String[]::new);
                // 执行查询任务
                executeTask(carPlates,carMap);
                // 当访问次数达到当日设定数量时,结束循环，初始化累计访问次数,并更新车辆违章数据
                if (BIGGEST_ACCESS_NUM.equals(lastCount) || lastIndex.equals(maxIndex)) {
                    isRunning = false;
                    // 任务执行完毕后保存最终的数据下标
                    TreeMap<Long, String> sortedMap = new TreeMap<>(infoMap);
                    Map.Entry<Long, String> higherEntry = sortedMap.higherEntry(lastIndex);
                    if (Objects.nonNull(higherEntry)){
                        lastIndex = higherEntry.getKey();
                    }
                    saveLastIndex(lastIndex, 0);
                    updateViolationData();
                    log.info("违法数据更新完成!");
                }
            } else {
                log.info("本月任务已查询完成!");
                return;
            }
        }
        stopWatch.stop();
        log.info("共更新车辆违法数据：" + lastCount + "条");
        log.info("========== 根据IRS更新车辆违法数据==========任务结束 {}s", stopWatch.getTotalTimeSeconds());

    }

    private void executeTask(String[] carPlates, Map<String, Long> carMap) {
        // 获取车牌号的所有违章信息
        Map<String, List<VehicleViolationIrsData>> violationIrsDataMap = violationIrsDataService.list(Wrappers.lambdaQuery(VehicleViolationIrsData.class)
                        .select(VehicleViolationIrsData::getId,VehicleViolationIrsData::getCarPlate, VehicleViolationIrsData::getViolationTime,
                                VehicleViolationIrsData::getViolationType,VehicleViolationIrsData::getViolationKind)).stream()
                .collect(Collectors.groupingBy(VehicleViolationIrsData::getCarPlate));
        for (int i = 0; i < carPlates.length; i++) {
            // 执行任务代码
            String carPlate = carPlates[i];
            String dataJsonStr;
            try {
                dataJsonStr = carService.vehicleIllegalQuery(carPlate, i);
                if (Objects.nonNull(dataJsonStr)) {
                    JSONObject jsonObject = JSON.parseObject(dataJsonStr, JSONObject.class);
                    String msg = jsonObject.getString("msg");
                    if (msg.contains("签名错误")) {
                        // 签名错误
                        lastIndex = carMap.get(carPlate);
                        lastCount++;
                        saveLastIndex(lastIndex, lastCount);
                        log.error("签名错误，任务中断时车牌号下标为{}", lastIndex);
                        break;
                    }
                }
            } catch (Exception e) {
                // 接口请求异常，结束循环
                lastIndex = carMap.get(carPlate);
                lastCount++;
                saveLastIndex(lastIndex, lastCount);
                log.error("任务中断时车牌号下标为{},中断原因：{}", lastIndex,e.getMessage());
                break;
            }
            if (Objects.isNull(dataJsonStr)) {
                // 刷新请求秘钥失败,接口调用内容返回空,任务中断，保存下标
                lastIndex = carMap.get(carPlate);
                saveLastIndex(lastIndex, lastCount);
                log.error("车辆违法查询接口调用失败,车牌号为:" + carPlate);
                break;
            }
            int index = i + 1;
            // 如果还有下一个待查询车牌号
            if (index < carPlates.length) {
                lastIndex = carMap.get(carPlates[index]);
            }else {
                // 已经是最后一个车牌号
                lastIndex = carMap.get(carPlates[i]);
            }
            log.info("下次待查询车牌号下标为:" + lastIndex);
            lastCount++;
            log.info("已访问车辆违法查询IRS接口 {} 次", lastCount);
            log.info("此次访问的违法车牌号为 {}", carPlate);
            JSONObject object = JSON.parseObject(dataJsonStr, JSONObject.class);
            String data = object.getString("datas");
            List<JSONObject> array = JSON.parseArray(data, JSONObject.class);
            if (CollUtil.isEmpty(array)) {
                log.info("该车牌号没有违法行为信息!");
                continue;
            }

            for (JSONObject jsonObject : array) {
                if (Objects.nonNull(jsonObject)) {
                    VehicleViolationIrsData vid = new VehicleViolationIrsData();
                    vid.setCarPlate(carPlate);
                    // 获取违法日期
                    Timestamp wfsj = jsonObject.getTimestamp("wfsj");
                    LocalDateTime vehicleIllegalTime = LocalDateTimeUtil.of(wfsj);
                    // 获取违法行为
                    String wfxw = jsonObject.getString("wfxw");
                    // 获取处罚种类
                    String cfzl = jsonObject.getString("cfzl");
                    String key = vehicleIllegalTime + wfxw + cfzl;
                    HashSet<String> hashSet = new HashSet<>();

                    if (violationIrsDataMap.containsKey(carPlate)) {
                        List<VehicleViolationIrsData> dataList = violationIrsDataMap.get(carPlate);
                        Map<String, VehicleViolationIrsData> dataMap = dataList.stream()
                                .filter(v -> hashSet.add(v.getViolationTime() + v.getViolationType() + v.getViolationKind()))
                                .collect(Collectors.toMap(v -> v.getViolationTime() + v.getViolationType() + v.getViolationKind(), v -> v));
                        if (dataMap.containsKey(key)) {
                            VehicleViolationIrsData irsData = dataMap.get(key);
                            // 数据已经存在
                            vid.setId(irsData.getId());
                        }
                    }
                    vid.setViolationTime(vehicleIllegalTime);
                    String jsonStr = jsonObject.toJSONString();
                    vid.setJsonStrData(jsonStr);
                    vid.setViolationType(wfxw);
                    vid.setViolationKind(cfzl);
                    vid.setCreateOn(LocalDateTime.now());
                    vid.setUpdateOn(LocalDateTime.now());
                    violationIrsDataService.saveOrUpdate(vid);
                }
            }
        }
    }

    private void saveLastIndex(Long lastIndex, Integer lastCount) {

        File directory = new File("");
        // 临时文件存储路径
        String filePath = directory.getAbsolutePath() + File.separator + "irs";
        File file = new File(filePath + File.separator + VEHICLE_ILLEGAL_QUERY_INDEX_FILE);

        try {
            FileWriter fileWriter = new FileWriter(file);
            BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);

            bufferedWriter.write(Long.toString(lastIndex));
            bufferedWriter.newLine();
            bufferedWriter.write(Integer.toString(lastCount));
            bufferedWriter.newLine();

            bufferedWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void readLastIndex() {
        File directory = new File("");
        // 临时文件存储路径
        String filePath = directory.getAbsolutePath() + File.separator + "irs";
        File file = new File(filePath + File.separator + VEHICLE_ILLEGAL_QUERY_INDEX_FILE);
        try {
            List<String> dataList = FileUtil.readLines(file, StandardCharsets.UTF_8);
            if (CollUtil.isNotEmpty(dataList) && dataList.size() == 2) {
                lastIndex = Long.valueOf(dataList.get(0));
                lastCount = Integer.valueOf(dataList.get(1));
            }
        } catch (Exception e) {
            log.info("读取下标和车牌号失败!");
            e.printStackTrace();
        }
    }

    public void updateViolationData() {

        Map<Long, String> map = violationIrsDataService
                .list(Wrappers.lambdaQuery(VehicleViolationIrsData.class)
                        .select(VehicleViolationIrsData::getId, VehicleViolationIrsData::getViolationType))
                .stream()
                .collect(Collectors.toMap(VehicleViolationIrsData::getId, VehicleViolationIrsData::getViolationType));

        List<Long> violationIdList = map.keySet().stream().filter(c -> {
            String type = map.get(c);
            return NO_DRIVING_LICENSE_LIST.contains(type) || NO_VEHICLE_LICENSE_LIST.contains(type)
                    || VIOLATION_TRAFFIC_LIGHTS_LIST.contains(type) || VIOLATION_TIME_LIST.contains(type)
                    || VIOLATION_ROAD_LIST.contains(type);
        }).collect(Collectors.toList());

        // 获取需要更新的数据
        Map<String, List<VehicleViolationIrsData>> listMap =
                violationIrsDataService.list(Wrappers.lambdaQuery(VehicleViolationIrsData.class)
                                .select(VehicleViolationIrsData::getId,VehicleViolationIrsData::getCarPlate,
                                        VehicleViolationIrsData::getJsonStrData))
                        .stream().filter(v -> violationIdList.contains(v.getId()))
                        .collect(Collectors.groupingBy(VehicleViolationIrsData::getCarPlate));

        // 获取车牌号
        Set<String> carPlateList = listMap.keySet();
        // 过滤掉不在系统中的车牌号
        List<NdVehicleBaseInfo> carPlates = vehicleBaseInfoService.list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class).select(NdVehicleBaseInfo::getCarPlate));
        List<String> carPlateLists = carPlateList.stream().filter(carPlates::contains).collect(Collectors.toList());
        // 违章数据的车牌号都不在系统中，不需要更新
        if (CollUtil.isEmpty(carPlateLists)){
            log.info("没有需要更新的数据!");
            return;
        }
        // 获取车辆基本信息
        List<NdVehicleBaseInfo> vehicleBaseInfos = vehicleBaseInfoService
                .list(Wrappers.lambdaQuery(NdVehicleBaseInfo.class)
                        .select(NdVehicleBaseInfo::getCarPlate,NdVehicleBaseInfo::getCompanyId)
                        .in(NdVehicleBaseInfo::getCarPlate, carPlateLists));
        Map<String, NdVehicleBaseInfo> vehicleBaseInfoMap =
                vehicleBaseInfos.stream().collect(Collectors.toMap(NdVehicleBaseInfo::getCarPlate, v -> v));

        // 获取企业信息
        Map<Long, Company> companyMap =
                companyService.list().stream().collect(Collectors.toMap(Company::getId, c -> c));

        // 获取已经存在的违章数据
        List<NdVehicleViolation> violationTmpVas = vehicleViolationService
                .list(Wrappers.lambdaQuery(NdVehicleViolation.class).in(NdVehicleViolation::getCarPlate, carPlateLists));
        Map<String, NdVehicleViolation> violationMap = violationTmpVas.stream()
                .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(a -> a.getCarPlate()
                        + StrPool.SEMICOLON + a.getViolationDate() + StrPool.SEMICOLON + a.getViolationType()))), ArrayList::new))
                .stream().collect(Collectors.toMap(d -> d.getCarPlate() + d.getViolationDate() + d.getViolationType() + d.getViolationAddress(), d -> d));

        for (String carPlate : carPlateLists) {
            NdVehicleBaseInfo vehicleBaseInfo = vehicleBaseInfoMap.get(carPlate);

            Long companyId = vehicleBaseInfo.getCompanyId();
            Company company = null;
            if (Objects.nonNull(companyId)) {
                company = companyMap.get(companyId);
            }

            // 获取IRS违章数据
            List<VehicleViolationIrsData> violationIrsDataList = listMap.get(carPlate);

            for (VehicleViolationIrsData violationIrsData : violationIrsDataList) {

                // 解析获取事故时间等信息
                String jsonStrData = violationIrsData.getJsonStrData();
                JSONObject jsonObject = JSON.parseObject(jsonStrData);

                NdVehicleViolation vehicleViolation = new NdVehicleViolation();

                // 获取违法日期
                Timestamp wfsj = jsonObject.getTimestamp("wfsj");
                LocalDateTime vehicleIllegalTime = LocalDateTimeUtil.of(wfsj);
                vehicleViolation.setViolationDate(vehicleIllegalTime);
                // 获取违法地址
                String wfdz = jsonObject.getString("wfdz");
                // 获取违法行为
                String wfxw = jsonObject.getString("wfxw");
                // 获取违法编号
                String wfbh = jsonObject.getString("wfbh");

                // 获取经纬度
                String longitude = jsonObject.getString("jd");
                String latitude = jsonObject.getString("wd");

                // 判断是否已经插入过
                String key = carPlate + vehicleIllegalTime + wfdz + wfxw;
                if (violationMap.containsKey(key)) {
                    NdVehicleViolation violation = violationMap.get(key);
                    vehicleViolation.setId(violation.getId());
                }
                vehicleViolation.setCarPlate(carPlate);
                // 获取行政区划
                String xzqh = jsonObject.getString("xzqh");
                // 获取区域信息
                Long regionId = regionsCacheHelper.getIdByCode(xzqh);
                String regionName = regionsCacheHelper.getDisplayName(regionId);
                vehicleViolation.setRegionId(regionId);
                vehicleViolation.setRegionName(regionName);
                // 如果是闯红灯
                if (VIOLATION_TRAFFIC_LIGHTS_LIST.contains(wfxw)) {
                    vehicleViolation.setViolationType(ViolationTypeEnum.RED_LIGHT.getCode());
                    vehicleViolation.setAddressRedLight(wfdz);
                } else if (NO_DRIVING_LICENSE_LIST.contains(wfxw)) {
                    vehicleViolation.setViolationType(ViolationTypeEnum.MISS_CERT.getCode());
                    vehicleViolation.setMissingCertificateType(MissCertEnum.DRIVER_LINCENSE.getCode());
                } else if (NO_VEHICLE_LICENSE_LIST.contains(wfxw)) {
                    vehicleViolation.setViolationType(ViolationTypeEnum.MISS_CERT.getCode());
                    vehicleViolation.setMissingCertificateType(MissCertEnum.DRIVE_PERMIT.getCode());
                } else if (VIOLATION_TIME_LIST.contains(wfxw)) {
                    vehicleViolation.setViolationType(ViolationTypeEnum.PERIOD.getCode());
                    int hour = vehicleIllegalTime.getHour();
                    int minute = vehicleIllegalTime.getMinute();
                    String period = null;
                    // 时间段暂时设置为违章时间所在小时的前后半小时
                    if (minute < 30) {
                        period = vehicleIllegalTime.minusHours(1).getHour() + TaskConstant.Data.VIOLATION_TIME_HALF
                                + StrPool.DASH + hour + TaskConstant.Data.VIOLATION_TIME_HALF;
                    } else {
                        period = hour + TaskConstant.Data.VIOLATION_TIME_START + StrPool.DASH
                                + vehicleIllegalTime.plusHours(1).getHour() + TaskConstant.Data.VIOLATION_TIME_START;
                    }
                    vehicleViolation.setViolationPeriod(period);
                    // if (hour >= TaskContant.Data.VIOLATION_TIME_SEVEN && hour <=
                    // TaskContant.Data.VIOLATION_TIME_NINE) {
                    // period = TaskContant.Data.VIOLATION_TIME_AM_START + StrPool.DASH
                    // + TaskContant.Data.VIOLATION_TIME_AM_END;
                    // vehicleViolation.setViolationPeriod(period);
                    // } else if (hour >= TaskContant.Data.VIOLATION_TIME_SIXTEEN
                    // && hour <= TaskContant.Data.VIOLATION_TIME_EIGHTEEN) {
                    // period = TaskContant.Data.VIOLATION_TIME_PM_START + StrPool.DASH
                    // + TaskContant.Data.VIOLATION_TIME_PM_END;
                    // vehicleViolation.setViolationPeriod(period);
                    // }
                } else if (VIOLATION_ROAD_LIST.contains(wfxw)) {
                    vehicleViolation.setViolationType(ViolationTypeEnum.SECTION.getCode());
                    vehicleViolation.setWaySection(wfdz);
                }
                // 获取当事人(驾驶员)
                String driverName = jsonObject.getString("dsr");

                vehicleViolation.setCompanyId(companyId);
                if (Objects.nonNull(company)) {
                    vehicleViolation.setCompanyName(company.getName());
                }
                // 驾驶员姓名和企业名称获取驾驶员信息
                List<DriverInfo> driverInfoList = driverInfoService.list(Wrappers.lambdaQuery(DriverInfo.class)
                        .eq(DriverInfo::getDriverName, driverName).eq(DriverInfo::getCompanyId, companyId));
                if (CollUtil.isEmpty(driverInfoList)) {
                    log.info("该车牌号对应的企业下没有该驾驶员信息");
                } else {
                    // 获取最后一个
                    DriverInfo driverInfo = driverInfoList.get(driverInfoList.size() - 1);
                    vehicleViolation.setDriverId(driverInfo.getId());
                }
                vehicleViolation.setDriverName(driverName);
                vehicleViolation.setLongitude(longitude);
                vehicleViolation.setLatitude(latitude);
                vehicleViolation.setViolationNo(wfbh);
                vehicleViolation.setViolationAddress(wfdz);
                vehicleViolationService.saveOrUpdate(vehicleViolation);
            }
        }
        log.info("违章数据更新完成!");
    }
}
