package com.ruoyi.benyun.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.benyun.mapper.StoreWdDao;
import com.ruoyi.benyun.mapper.WdInfoDao;
import com.ruoyi.benyun.service.TopologicalStoreWdService;
import com.ruoyi.benyun.entity.ManageType;
import com.ruoyi.benyun.entity.StoreWd;
import com.ruoyi.benyun.entity.TopologicalStoreWd;
import com.ruoyi.benyun.entity.WdInfo;
import com.ruoyi.benyun.entity.bo.StoreWdCategoryCount;
import com.ruoyi.benyun.entity.bo.StoreWdCategoryCountBody;
import com.ruoyi.benyun.entity.vo.TopologicalWdAceeptVo;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ruoyi.benyun.utils.InitMapUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Distance;
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.Service;

import java.math.BigDecimal;
import java.util.*;

@Service
public class TopologicalStoreWdServiceImpl implements TopologicalStoreWdService {

    @Autowired
    WdInfoDao wdInfoDao;

    @Autowired
    StoreWdDao storeWdDao;

    @Autowired
    InitMapUtil initMapUtil;

    @Autowired
    RedisTemplate redisTemplate;

    //TODO 待测试
    @Override
    public List<TopologicalStoreWd> list(TopologicalWdAceeptVo topologicalWdAceeptVo) {
        //1.根据中心网点Id找到网点详细信息
        QueryWrapper<WdInfo> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("wd_id",topologicalWdAceeptVo.getCenterWdId());
        WdInfo wdInfo1 = wdInfoDao.selectOne(queryWrapper1);

        //2.根据中心网点找到周边网点Id
        // 以经纬度为中心，获取半径不超过最大距离的所有元素
        Point point = new Point(wdInfo1.getLng().doubleValue(),wdInfo1.getLat().doubleValue());
        //半径范围
        Distance distance = new Distance(topologicalWdAceeptVo.getRadius(), RedisGeoCommands.DistanceUnit.METERS);
        //圆
        Circle circle = new Circle(point, distance);
        RedisGeoCommands.GeoRadiusCommandArgs geoRadiusCommandArgs = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();
        geoRadiusCommandArgs.includeDistance();
        GeoResults<RedisGeoCommands.GeoLocation<Object>> radius = redisTemplate.boundGeoOps(wdInfo1.getAddrCode().substring(0, 4)).radius(circle,geoRadiusCommandArgs);
        //周边网点Id
        List<String> aroundWdId = new ArrayList<>();
        HashMap<String,Double> hashMap = new HashMap<>();
        radius.getContent().stream().forEach(item -> {
            //记录网点坐标及距离
            aroundWdId.add((String) item.getContent().getName());
            hashMap.put((String) item.getContent().getName(), item.getDistance().getValue());
        });


        //4.分页查找网点信息
        QueryWrapper<WdInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("wd_type_code","1")
            .and(wdInfoQueryWrapper -> {
                wdInfoQueryWrapper.in("wd_id", aroundWdId);
        });

        //5.查询周边网点结果
        PageHelper.startPage(1, topologicalWdAceeptVo.getSize());
        List<WdInfo> wdInfos = wdInfoDao.selectList(queryWrapper);
        PageInfo<WdInfo> pageInfo = new PageInfo<>(wdInfos);


        //6.组装结果集
        List<TopologicalStoreWd> list = new ArrayList<>();  //返回结果集
        for (WdInfo wdInfo : pageInfo.getList()) {
            TopologicalStoreWd topologicalStoreWd = new TopologicalStoreWd(wdInfo);
            topologicalStoreWd.setAddrCodeInfo(initMapUtil.getInitAddrCodeMap(topologicalStoreWd.getAddrCode()));
            BigDecimal bigDecimal = new BigDecimal(hashMap.get(wdInfo.getWdId()));
            topologicalStoreWd.setDistance(bigDecimal.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue());
            list.add(topologicalStoreWd);
        }

        return list;
    }

    //TODO 待测试
    @Override
    public List<StoreWdCategoryCount> category(TopologicalWdAceeptVo topologicalWdAceeptVo) {
        //1.根据中心网点Id找到网点详细信息
        QueryWrapper<WdInfo> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("wd_id",topologicalWdAceeptVo.getCenterWdId());
        WdInfo wdInfo1 = wdInfoDao.selectOne(queryWrapper1);

        //2.根据中心网点找到周边网点Id
        // 以经纬度为中心，获取半径不超过最大距离的所有元素
        Point point = new Point(wdInfo1.getLng().doubleValue(),wdInfo1.getLat().doubleValue());
        //半径范围
        Distance distance = new Distance(topologicalWdAceeptVo.getRadius(), RedisGeoCommands.DistanceUnit.METERS);
        //圆
        Circle circle = new Circle(point, distance);
        GeoResults<RedisGeoCommands.GeoLocation<Object>> radius = redisTemplate.boundGeoOps(wdInfo1.getAddrCode().substring(0, 4)).radius(circle);
        //周边网点Id
        List<String> aroundWdId = new ArrayList<>();
        radius.getContent().stream().forEach(item -> {
            //记录网点坐标及距离
            aroundWdId.add((String) item.getContent().getName());
        });


        QueryWrapper<StoreWd> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("manage_type_code","count(*) as comment_count")
            .in("wd_id",aroundWdId)
            .groupBy("manage_type_code");

        //5.查询周边网点结果，并统计
        List<StoreWd> wdInfos = storeWdDao.selectList(queryWrapper);
        HashMap<String,StoreWdCategoryCount> hashMap = new HashMap<>();
        for (StoreWd wdInfo : wdInfos) {
            if(wdInfo.getManageTypeCode() == null || wdInfo.getManageTypeCode().equals(""))
                continue;

            String s = wdInfo.getManageTypeCode().substring(0, 4) + "00";
            StoreWdCategoryCount storeWdCategoryCount = hashMap.get(s);

            ManageType initManageType = initMapUtil.getInitManageType(wdInfo.getManageTypeCode());
            if (storeWdCategoryCount == null){
                StoreWdCategoryCountBody storeWdCategoryCountBody = new StoreWdCategoryCountBody();
                if(initManageType.getSubCategory() != null && !initManageType.getSubCategory().equals("")){
                    storeWdCategoryCountBody.setName(initManageType.getSubCategory());
                }else if(initManageType.getMidCategory() != null && !initManageType.getMidCategory().equals("")){
                    storeWdCategoryCountBody.setName(initManageType.getMidCategory());
                }else if (initManageType.getBigCategory() != null && !initManageType.getBigCategory().equals("")){
                    storeWdCategoryCountBody.setName(initManageType.getBigCategory());
                }
                storeWdCategoryCountBody.setManageTypeCode(wdInfo.getManageTypeCode());
                storeWdCategoryCountBody.setCount(wdInfo.getCommentCount());

                StoreWdCategoryCount storeWdCategoryCount1 = new StoreWdCategoryCount();
                storeWdCategoryCount1.setManageTypeCode(s);
                storeWdCategoryCount1.setName(initMapUtil.getInitManageType(s).getMidCategory());
                storeWdCategoryCount1.setCount(wdInfo.getCommentCount());
                ArrayList<StoreWdCategoryCountBody> list = new ArrayList<>();
                list.add(storeWdCategoryCountBody);
                storeWdCategoryCount1.setStoreWdCategoryCountBodyList(list);
                hashMap.put(s,storeWdCategoryCount1);
            }else {
                StoreWdCategoryCountBody storeWdCategoryCountBody = new StoreWdCategoryCountBody();
                if(initManageType.getSubCategory() != null && !initManageType.getSubCategory().equals("")){
                    storeWdCategoryCountBody.setName(initManageType.getSubCategory());
                }else if(initManageType.getMidCategory() != null && !initManageType.getMidCategory().equals("")){
                    storeWdCategoryCountBody.setName(initManageType.getMidCategory());
                }else if (initManageType.getBigCategory() != null && !initManageType.getBigCategory().equals("")){
                    storeWdCategoryCountBody.setName(initManageType.getBigCategory());
                }
                storeWdCategoryCountBody.setManageTypeCode(wdInfo.getManageTypeCode());
                storeWdCategoryCountBody.setCount(wdInfo.getCommentCount());

                storeWdCategoryCount.getStoreWdCategoryCountBodyList().add(storeWdCategoryCountBody);
                storeWdCategoryCount.setCount(storeWdCategoryCountBody.getCount()+storeWdCategoryCount.getCount());
                //hashMap.put(s,storeWdCategoryCount);
            }
        }


        //6.组装结果集
        List<StoreWdCategoryCount> storeWdCategoryCounts = new ArrayList<>();
        for (String s : hashMap.keySet()) {
            storeWdCategoryCounts.add(hashMap.get(s));
        }

        return storeWdCategoryCounts;
    }
}
