package com.mosty.wzzx.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mosty.base.model.dto.qwzx.TbQwXfbbVo;
import com.mosty.base.model.dto.wzzx.AppLocationReceiveDto;
import com.mosty.base.model.dto.wzzx.LocationInfo;
import com.mosty.base.model.dto.yjzl.TbZlxxInsertDto;
import com.mosty.base.model.dto.yjzl.TbZlxxZxrDtoInsertDto;
import com.mosty.base.model.entity.qwzx.TbQwXfbb;
import com.mosty.base.model.entity.wzzx.TbWzRywz;
import com.mosty.base.model.entity.wzzx.TbWzSswz;
import com.mosty.base.model.entity.wzzx.TbWzXfwz;
import com.mosty.base.model.entity.yjzl.TbYjxx;
import com.mosty.base.model.vo.base.DeptInfoVo;
import com.mosty.base.utils.*;
import com.mosty.common.core.util.http.HttpUtils;
import com.mosty.common.redis.service.RedisService;
import com.mosty.wzzx.mapper.TbWzRywzMapper;
import com.mosty.wzzx.mapper.TbWzXfwzMapper;
import com.mosty.wzzx.remote.TbBaseAdaptRemoteService;
import com.mosty.wzzx.remote.TbQwzxAdaptRemoteService;
import com.mosty.wzzx.remote.TbYjzlAdaptRemoteService;
import com.mosty.wzzx.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.C;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class LocationInfoServiceImpl extends ServiceImpl<TbWzXfwzMapper, TbWzXfwz> implements LocationInfoService {


    private final TbWzRywzMapper tbWzRywzMapper;
    private final TbQwXfbbService tbQwXfbbService;
    private final TbWzSswzService tbWzSswzService;
    private final TbWzLswzService tbWzLswzService;
    private final TbSjCyjlService tbSjCyjlService;
    private final RedisService redisService;
    private final TbBaseAdaptRemoteService tbBaseAdaptRemoteService;
    private final TbQwzxAdaptRemoteService tbQwzxAdaptRemoteService;
    private final TbYjzlAdaptRemoteService tbYjzlAdaptRemoteService;



    public void locationReceive(LocationInfo locationInfo) {
        long startTime = System.currentTimeMillis();
        long rytime = 0;
        long bbtime = 0;
        long xftime = 0;
        long sswzTime = 0;
        long lswzTime = 0;
        long xfbbTime = 0;


        //经度、纬度为空不接收数据
        try {
            if (locationInfo.getLng() == null && locationInfo.getLat() == null) {
                return;
            }

            // 绵阳存在问题 后台结束报备以后 app没有更新报备id 一直上传位置
            if (StringUtils.isNotEmpty(locationInfo.getBbid()) || !"null".equals(locationInfo.getBbid())) {
                int getsfbb = tbQwXfbbService.getsfbb(locationInfo.getBbid());
                if (getsfbb < 1) {
                    locationInfo.setBbid(null);
                }
            }

            if (StringUtils.isBlank(locationInfo.getBbid()) || "null".equals(locationInfo.getBbid())) {
                locationInfo.setBbid(null);
                locationInfo.setJzid(null);
                locationInfo.setJzmc(null);
                //保存人员位置
                TbWzRywz oldRywz = this.saveRywz(locationInfo);
                // 保存实时位置
                this.tbWzSswzService.saveSswz(locationInfo, oldRywz);
                // 保存历史位置
                this.tbWzLswzService.saveLswz(locationInfo, oldRywz);
            } else {
                String bbid, jzid, jzmc;
                String[] bbidList = locationInfo.getBbid().split("\\(__\\)");
                String[] jzidList = null;
                String[] jzmcList = null;
                if (StringUtils.isNoneBlank(locationInfo.getJzid())) {
                    jzidList = locationInfo.getJzid().split("\\(__\\)");
                }
                if (StringUtils.isNoneBlank(locationInfo.getJzmc())) {
                    jzmcList = locationInfo.getJzmc().split("\\(__\\)");
                }
                for (int i = 0; i < bbidList.length; i++) {
                    bbid = bbidList[i];
                    if (jzidList != null) {
                        jzid = jzidList[i];
                        locationInfo.setJzid(jzid);
                    }
                    if (jzmcList != null) {
                        jzmc = jzmcList[i];
                        locationInfo.setJzmc(jzmc);
                    }
                    locationInfo.setBbid(bbid);

                    // 保存人员位置
                    TbWzRywz oldRywz = this.saveRywz(locationInfo);
                    rytime = System.currentTimeMillis() - startTime;
                    //警务通采集经纬度为辅
                    TbQwXfbb bb = this.tbQwzxAdaptRemoteService.getBbxxInfo(locationInfo.getBbid());
                    bbtime = System.currentTimeMillis() - startTime;
                    // 保存巡防位置
                    Integer lc = this.saveXfwz(bb, locationInfo, oldRywz);
                    xftime = System.currentTimeMillis() - startTime;
//                    log.info("TbQwXfbb ：{}", System.currentTimeMillis() - startTime);
                    // 查询巡组实时位置,如果5分钟没有GPS信号，则保存设备的位置信息 （直接判断bb是否在线 在线不添加 不在线 写入数据）
//                    if (bb.getXfzt().equals("2")) {

                    // 保存实时位置
                    tbWzSswzService.saveSswz(locationInfo, oldRywz);
                    sswzTime = System.currentTimeMillis() - startTime;
                    // 保存历史位置
                    tbWzLswzService.saveLswz(locationInfo, oldRywz);
                    lswzTime = System.currentTimeMillis() - startTime;
                    // 修改巡防报备的坐标
                    tbQwXfbbService.updateXfbb(bb, locationInfo, oldRywz, lc);
                    xfbbTime = System.currentTimeMillis() - startTime;
                }

            }
            long zsc = System.currentTimeMillis() - startTime;
            if (zsc > 1000) {
                System.out.println("位置服务上报保存时长{" + zsc + "}----保存人员位置{" + rytime + "}---" +
                        "报备查询{" + bbtime + "}---保存巡防位置{" + xftime + "}-----用户{" + locationInfo.getUserId() + "}----" +
                        "保存实时位置{" + sswzTime + "}---保存历史位置{" + lswzTime + "}---修改巡防报备的坐标{" + xfbbTime + "}-----用户{" + locationInfo.getUserId() + "}");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 生成指令信息
    private void createdZl(LocationInfo item, TbQwXfbb bb) {
        String key = Constant.LZYJ_DATA_QKSD;
        List<TbYjxx> yjxxList = this.redisService.getCacheList(key);
        if (yjxxList != null && yjxxList.size() > 0) {
            // 依图人像（脸）
            List<TbYjxx> ytList = yjxxList.stream().filter(yjxx -> {
                // 判断相似度大于等于95%
                if (yjxx.getXsd() == null) return false;
                int a = yjxx.getXsd().compareTo(new BigDecimal("95"));
                if (a < 0) return false;
                // 预警时间半小时之内
                if (new Date().getTime() - yjxx.getYjSj().getTime() > 30 * 60 * 1000) return false;
                // 当前位置500米范围内
                double jl = Kit.getDistance(item.getLng(), item.getLat(), yjxx.getJd().doubleValue(), yjxx.getWd().doubleValue());
                return !(jl >= 500.0);
            }).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(ytList)) {
                // 发送指令到巡组
                this.sendZl(ytList, bb);
            }
            // 旅店网吧
            List<TbYjxx> ldList = yjxxList.stream().filter(yjxx -> {
                if (yjxx.getXsd() != null) return false;
                // 预警时间两小时之内
                if (new Date().getTime() - yjxx.getYjSj().getTime() > 120 * 60 * 1000) return false;
                // 当前位置2000米范围内
                double jl = Kit.getDistance(item.getLng(), item.getLat(), yjxx.getJd().doubleValue(), yjxx.getWd().doubleValue());
                return !(jl >= 2000);
            }).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(ldList)) {
                // 发送指令到巡组
                this.sendZl(ldList, bb);
            }
        }
    }

    // 发送指令到巡组
    private void sendZl(List<TbYjxx> yjxxList, TbQwXfbb bb) {
        if (bb != null) {
            yjxxList.forEach(yjxx -> {
                TbZlxxInsertDto zl = new TbZlxxInsertDto();
                zl.setId(UUIDGenerator.getUUID()).setYwId(yjxx.getId()).setZllx("02").setZlly("02").setZlzxlx("1")
                        .setZlbt("请核查" + yjxx.getYjBt()).setZlnr(yjxx.getYjNr() + "请核查！")
                        .setZldj(yjxx.getYjJb()).setJd(yjxx.getJd()).setWd(yjxx.getWd()).setZlfsddxzqh(yjxx.getYjDzXzqh())
                        .setZlfsdd(yjxx.getYjDz()).setZltp(yjxx.getYjTp());
                zl.setZljsdx("03");
                zl.setSsbmid(bb.getSsbmid());
                List<TbZlxxZxrDtoInsertDto> zxrDtoList = new ArrayList<>();
                TbZlxxZxrDtoInsertDto zxr = new TbZlxxZxrDtoInsertDto();
                zxr.setZlId(zl.getId()).setZxrLx("03").setZxrXzid(bb.getId());
                zxrDtoList.add(zxr);
                yjxx.setBz("范围内500米查询到巡组《" + bb.getJzMc() + "》，已下发");
                zl.setZxrDtoList(zxrDtoList);
                this.tbYjzlAdaptRemoteService.addZl(zl);
                // 修改预警信息相关信息
                this.tbYjzlAdaptRemoteService.updateYjxxSffszl(yjxx.getId());
            });
        }
    }

    public TbWzRywz saveRywz(LocationInfo locationInfo) {
        BigDecimal jd = BigDecimal.valueOf(locationInfo.getLng());
        BigDecimal wd = BigDecimal.valueOf(locationInfo.getLat());
        String redisKey = Constant.WZ_RYWZ + locationInfo.getUserId() + "-"
                + DateUtils.getQueryDateString(new Date(), "01");
        TbWzRywz rywz = redisService.getCacheObject(redisKey);
//        TbWzRywz oldRywz = redisService.getCacheObject(redisKey);
        if (rywz == null) {
            rywz = new TbWzRywz();
        }
        rywz.setYhId(locationInfo.getYhid());
        rywz.setYhXm(locationInfo.getUserName());
        rywz.setYhSfzh(locationInfo.getUserId());
        List<BigDecimal[]> list = rywz.getZbList();
        if (CollectionUtils.isEmpty(list)) {
            list = new ArrayList<>();
        }
        Date oldTime = null;
        if (locationInfo.getLastTime() != null) {
            oldTime = locationInfo.getLastTime();
        }

        Integer lc = DistanceUtils.getLc(rywz.getLc(), rywz.getJd(), rywz.getWd(), jd, wd);
        Integer sc = DistanceUtils.getSc(oldTime);
        BigDecimal[] decimals = new BigDecimal[2];
        decimals[0] = jd;
        decimals[1] = wd;
        list.add(decimals);
        if (list.size() == 1) {
            list.add(decimals);
        }
        if (list.size() >= 3) {
            BigDecimal[] decimal0 = list.get(0);
            BigDecimal[] decimal1 = list.get(1);
            if (decimal0 == decimal1) {
                list.remove(0);
            }
        }
        rywz.setLc(lc);
        rywz.setSc(sc);
        rywz.setZb(JtsUtils.createLine(list));
        rywz.setZbsl(list.size());
        rywz.setJd(jd);
        rywz.setWd(wd);
        rywz.setXtSjly("1");
        if (StringUtils.isBlank(rywz.getSsbm())) {
            DeptInfoVo dept = this.tbBaseAdaptRemoteService.getOrgByDeptId(locationInfo.getDeptId());
            if (dept != null) {
                rywz.setSsbm(dept.getDeptname());
                rywz.setSsbmdm(dept.getDeptcode());
                rywz.setSsbmid(dept.getDeptid());
                rywz.setSsxgaj(dept.getFxjname());
                rywz.setSsxgajid(dept.getFxjid());
                rywz.setSsxgajdm(dept.getFxjcode());
                rywz.setSssgajid(dept.getDszid());
                rywz.setSssgaj(dept.getDszname());
                rywz.setSssgajdm(dept.getDszcode());
            }
        }
        if (StringUtils.isBlank(rywz.getId())) {
            rywz.setKssj(new Date());
            rywz.setDwrq(new Date());
            tbWzRywzMapper.insertEntity(rywz);
        } else {
            tbWzRywzMapper.updateEntity(rywz);
        }
        rywz.setZb(null);
        rywz.setZbList(list);
        redisService.setCacheObject(redisKey, rywz);
        return rywz;
    }

    public Integer saveXfwz(TbQwXfbb bb, LocationInfo locationInfo, TbWzRywz rywz) {
        if (ObjectUtils.isEmpty(locationInfo) && ObjectUtils.isEmpty(rywz) && ObjectUtils.isEmpty(rywz.getJd()))
            return 0;
        String redisKey = Constant.WZ_XFWZ + locationInfo.getBbid();
        //直接去redis存在问题 20240307
        TbWzXfwz xfwz = redisService.getCacheObject(redisKey);
        Integer lc = 0;
//        TbWzXfwz xfwz = this.baseMapper.queryByBbid(locationInfo.getBbid());
        if (ObjectUtils.isEmpty(xfwz)) {
            xfwz = new TbWzXfwz();
        }

//        else {
//            List<BigDecimal[]> list = JtsUtils.getz(xfwz.getZb());
//            if (CollectionUtils.isEmpty(list)) {
//                list = new ArrayList<>();
//            }
//            if (list.size() >= 3) {
//                BigDecimal[] decimal0 = list.get(0);
//                BigDecimal[] decimal1 = list.get(1);
//                if (decimal0 == decimal1) {
//                    list.remove(0);
//                }
//            }
//            xfwz.setZb(null);
//            xfwz.setZbList(list);
//
//        }
        // 查询位置人员是否为改报备巡组的报备人员，
        // 如果是则直接添加修改位置
        // 查询巡防位置
//        TbQwXfbb bb = this.tbQwzxAdaptRemoteService.getBbxxInfo(locationInfo.getBbid());
        boolean flag = false;
        if ((bb != null && bb.getFzrSfzh().equals(locationInfo.getUserId()))) {
            // 是报备负责人
            flag = true;
        } else {
            // 如果redis中没得数据，则直接添加数据
            if (xfwz.getKssj() == null) {
                flag = true;
            } else {
                // 不是报备本人。需要判断之前的时间是否超过5分钟，超过就更新位置数据，不超过
                // 就不需要更新
                Date kssj = xfwz.getKssj();
                if (new Date().getTime() - kssj.getTime() > 5 * 60 * 1000) {
                    flag = true;
                }
            }
        }
        if (flag) {
            BigDecimal jd = BigDecimal.valueOf(locationInfo.getLng());
            BigDecimal wd = BigDecimal.valueOf(locationInfo.getLat());
            lc = DistanceUtils.getLc(bb.getXflc(), xfwz.getJd(), xfwz.getWd(), jd, wd);
            xfwz.setBbId(locationInfo.getBbid());
            xfwz.setYhId(locationInfo.getYhid());
            xfwz.setYhSfzh(locationInfo.getUserId());
            xfwz.setYhXm(locationInfo.getUserName());
            xfwz.setJzId(locationInfo.getJzid());
            xfwz.setJzMc(locationInfo.getJzmc());
            xfwz.setSc(rywz.getSc());
            xfwz.setLc(rywz.getLc());
            List<BigDecimal[]> list = new ArrayList<>();
            if (!CollectionUtils.isEmpty(xfwz.getZbList())) {
                list = xfwz.getZbList();
            }
            BigDecimal[] decimals = new BigDecimal[2];
            decimals[0] = jd;
            decimals[1] = wd;
            list.add(decimals);
            if (list.size() == 1) {
                list.add(decimals);
            }
            if (list.size() >= 3) {
                BigDecimal[] decimal0 = list.get(0);
                BigDecimal[] decimal1 = list.get(1);
                if (decimal0 == decimal1) {
                    list.remove(0);
                }
            }
            xfwz.setZb(JtsUtils.createLine(list));
            xfwz.setZbsl(list.size());
            xfwz.setDwrq(new Date());
            xfwz.setKssj(new Date());
            xfwz.setJd(jd);
            xfwz.setWd(wd);
            xfwz.setZhgxsj(new Date());
            xfwz.setXtSjly("1");
            if (ObjectUtils.isNotEmpty(rywz)) {
                xfwz.setSsbm(rywz.getSsbm());
                xfwz.setSsbmdm(rywz.getSsbmdm());
                xfwz.setSsbmid(rywz.getSsbmid());
                xfwz.setSsxgaj(rywz.getSsxgaj());
                xfwz.setSsxgajid(rywz.getSsxgajid());
                xfwz.setSsxgajdm(rywz.getSsxgajdm());
                xfwz.setSssgajid(rywz.getSssgajid());
                xfwz.setSssgaj(rywz.getSssgaj());
                xfwz.setSssgajdm(rywz.getSssgajdm());
            } else {
                DeptInfoVo dept = this.tbBaseAdaptRemoteService.getOrgByDeptId(locationInfo.getDeptId());
                if (dept != null) {
                    xfwz.setSsbm(dept.getDeptname());
                    xfwz.setSsbmdm(dept.getDeptcode());
                    xfwz.setSsbmid(dept.getDeptid());
                    xfwz.setSsxgaj(dept.getFxjname());
                    xfwz.setSsxgajid(dept.getFxjid());
                    xfwz.setSsxgajdm(dept.getFxjcode());
                    xfwz.setSssgajid(dept.getDszid());
                    xfwz.setSssgaj(dept.getDszname());
                    xfwz.setSssgajdm(dept.getDszcode());

                }
            }

            xfwz.setZxzt("1");
            if (StringUtils.isBlank(xfwz.getId())) {
                xfwz.setId(UUIDGenerator.getUUID());
                this.baseMapper.insert(xfwz);
            } else {
                this.baseMapper.update(xfwz);
            }
            xfwz.setZb(null);
            xfwz.setZbList(list);
            redisService.setCacheObject(redisKey, xfwz);
        }
        return lc;
    }
}
