package com.ruoyi.benyun.utils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.benyun.constant.RedisContant;
import com.ruoyi.benyun.entity.WdInfo;
import com.ruoyi.benyun.mapper.WdInfoDao;
//import com.ruoyi.benyun.service.WriteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;

@Component
public class WdRedisStoreage {
    @Autowired
    private  RedisTemplate redisTemplate;

    @Autowired
    public WdInfoDao wdInfoDao;

    @Autowired
    @Qualifier("executor")
    private ExecutorService executorService;




    //@Autowired
    //WriteService writeService;


    /***
     * 获取中心网点的周边标签
     * @param wdInfo 中心网点信息
     * @return
     */
    public  List<String> getWdTag(WdInfo wdInfo){
        List<String> tag = (List<String>) redisTemplate.boundValueOps(RedisContant.WD_TAG+"_"+wdInfo.getWdId()).get();
        System.out.println(RedisContant.WD_TAG+"_"+wdInfo.getWdId());
        System.out.println(tag);
        return tag;
    }

    public  List<List<String>> getWdTagList(List<String> key){
        List<List<String>>  list = redisTemplate.opsForValue().multiGet(key);
        return list;
    }

    /***
     * 分析网点周边标签，并把分析结果存入redis（默认范围：1km）
     * @param wdInfo 中心网点信息
     * @return
     */
    public  List<String> wdTagAnalyse(WdInfo wdInfo){
        //1. 找到距离中心网点半径1km的所有网点Id
        Distance distance = new Distance(1, RedisGeoCommands.DistanceUnit.KILOMETERS);
        GeoResults<RedisGeoCommands.GeoLocation<Object>> radius = redisTemplate.boundGeoOps(wdInfo.getAddrCode().substring(0, 4)).radius(wdInfo.getWdId(), distance);
        List<GeoResult<RedisGeoCommands.GeoLocation<Object>>> content = radius.getContent();
        List<String> aroundWdId = content.stream().map(item -> {
            String name = (String) item.getContent().getName();
            return name;
        }).collect(Collectors.toList());

        //2. 查询周边网点标签的Set集
        QueryWrapper<WdInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("type_name_by")
                .in("wd_id",aroundWdId)
                    .groupBy("type_name_by");
        List<WdInfo> wdInfos = wdInfoDao.selectList(queryWrapper);
        //释放内存
        aroundWdId = null;
        aroundWdId = null;

        //3. 打标签
        List<String> tag = new ArrayList<>();
        wdInfos.stream().forEach(item -> {
            if(item != null){
                String typeNameBy = item.getTypeNameBy();
                if(typeNameBy != null && !typeNameBy.equals("")){
                    String[] split = typeNameBy.split(":");
                    if (split.length > 0)
                        tag.add(split[split.length-1]);
                }
            }
        });
        redisTemplate.boundValueOps(RedisContant.WD_TAG+"_"+wdInfo.getWdId()).set(tag);

        return tag;
    }

    /**
     * 将网点数据库 导入 redis
     * */
    public void writeWdGeoRedis(){
        //清重
        //clearSql2();

        //将所有网点坐标导入redis
        //writeWdGeoRedis1("2023-09-25");

        //给网点打标签并存入redis中
        //writeWdGeoRedis2();
    }
//
//    public void clearSql2(){
//        List<String> wdId = new ArrayList<>();
//        List<String> storeId = new ArrayList<>();
//        List<String> houseId = new ArrayList<>();
//        List<String> buildId = new ArrayList<>();
//        List<String> trafficId = new ArrayList<>();
//        List<String> enterpriseId = new ArrayList<>();
//        long start = System.currentTimeMillis();
//
//        try{
//            System.out.println("开始清理");
//
//            QueryWrapper<WdInfo> wdInfoOriginQueryWrapper = new QueryWrapper<>();
//            wdInfoOriginQueryWrapper.select("hash", "count(hash) as audit").groupBy("hash").having("count(hash) >= 2");
//            List<WdInfo> wdInfoOrigins = wdInfoDao.selectList(wdInfoOriginQueryWrapper);
//
//            HashMap<String, Integer> hashMap = new HashMap<>();
//            for (WdInfo wdInfo : wdInfoOrigins) {
//                hashMap.put(wdInfo.getHash(), wdInfo.getAudit());
//            }
//
//
//            HashMap<String,Integer> hashMap1 = new HashMap<>();
//            hashMap1.put("total",1);
//            CompletableFuture<Void> future = null;
//            for (String s : hashMap.keySet()) {
//                FutureTask
//                future = CompletableFuture.runAsync(()->{
//                    synchronized (this){
//                        if(hashMap1.get("total")%1000 == 0){
//                            writeService.clearSql2(wdId,storeId,houseId,buildId,trafficId,enterpriseId);
//                            wdId.clear();
//                            storeId.clear();
//                            houseId.clear();
//                            buildId.clear();
//                            trafficId.clear();
//                            enterpriseId.clear();
//                        }
//                    }
//
//                    QueryWrapper<WdInfo> queryWrapper = new QueryWrapper<>();
//                    queryWrapper.eq("hash",s);
//                    queryWrapper.orderByDesc("collect_time");
//                    queryWrapper.last("limit " + (hashMap.get(s) - 1));
//                    List<WdInfo> wdInfos = wdInfoDao.selectList(queryWrapper);
//                    for (WdInfo wdInfo : wdInfos) {
//                        wdId.add(wdInfo.getWdId());
//
//                        switch (wdInfo.getWdTypeCode()){
//                            case "1":
//                                storeId.add(wdInfo.getWdId());
//                                break;
//                            case "2":
//                                houseId.add(wdInfo.getWdId());
//                                break;
//                            case "3":
//                                buildId.add(wdInfo.getWdId());
//                                break;
//                            case "4":
//                                trafficId.add(wdInfo.getWdId());
//                                break;
//                            case "5":
//                                enterpriseId.add(wdInfo.getWdId());
//                                break;
//                            default:
//                                break;
//                        }
//                    }
//                    System.out.println("进度："+wdInfoOrigins.size()+"/"+hashMap1.get("total"));
//                    hashMap1.put("total",hashMap1.get("total")+1);
//                },executorService);
//            }
//            future.get();
//        }catch (Exception e){
//            e.printStackTrace();
//        }finally {
//            //删除
//            writeService.clearSql2(wdId,storeId,houseId,buildId,trafficId,enterpriseId);
//            long end = System.currentTimeMillis();
//            System.out.println("完成清理 "+(end-start)/(1000*60));
//        }
//
//
//    }

    public void writeWdGeoRedis1(String time){
        //1.将网点坐标存入redis中
        long start = System.currentTimeMillis();
        System.out.println("开始将网点坐标存入redis");
        QueryWrapper<WdInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("wd_id","addr_code","lng","lat");
        queryWrapper.ge("collect_time",time);

        Hashtable<String,Integer> hashtable = new Hashtable<>();
        hashtable.put("total",0);
        List<CompletableFuture<Void>> completableFutureList = new ArrayList<>();
        List<WdInfo> wdInfos = wdInfoDao.selectList(queryWrapper);
        for (WdInfo wdInfo : wdInfos) {
            //开启线程
            completableFutureList.add(CompletableFuture.runAsync(()->{
                redisTemplate.boundGeoOps(wdInfo.getAddrCode().substring(0,4)).add(new Point(wdInfo.getLng().doubleValue(),wdInfo.getLat().doubleValue()),wdInfo.getWdId());
                wdTagAnalyse(wdInfo);
                System.out.println("进度："+wdInfos.size()+"/"+hashtable.get("total"));
                hashtable.put("total",hashtable.get("total")+1);
            },executorService));
        }
        CompletableFuture.allOf(completableFutureList.toArray(new CompletableFuture[0])).join();
        long end = System.currentTimeMillis();
        System.out.println("完成存入 "+(end-start)/(1000*60));

    }

    public void writeWdGeoRedis2(String[] wdTypeCodes){
        //对所有网点坐标进行分析打标签
        long start = System.currentTimeMillis();
        System.out.println("开始打标签");

        //开始
        QueryWrapper<WdInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("wd_id","addr_code");
        queryWrapper.in("wd_type_code", wdTypeCodes);
        List<WdInfo> wdInfos = wdInfoDao.selectList(queryWrapper);

        ArrayList<CompletableFuture<Void>> list = new ArrayList<>();
        Hashtable<String,Integer> hashtable = new Hashtable<>();
        hashtable.put("total",1);
        for (WdInfo wdInfo : wdInfos) {
            //开启线程
            CompletableFuture<Void> future = CompletableFuture.runAsync(()->{
                wdTagAnalyse(wdInfo);
                System.out.println("进度："+wdInfos.size()+"/"+hashtable.get("total"));
                hashtable.put("total",hashtable.get("total")+1);
            },executorService);
            list.add(future);
        }
        CompletableFuture.allOf(list.toArray(new CompletableFuture[list.size()])).join();
        long end = System.currentTimeMillis();
        System.out.println("完成打标签 "+(end-start)/(1000*60));

    }


}
