package com.ruoyi.demo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ruoyi.demo.entity.ManageType;
import com.ruoyi.demo.entity.StoreWd;
import com.ruoyi.demo.entity.TopologicalStoreWd;
import com.ruoyi.demo.entity.WdInfo;
import com.ruoyi.demo.entity.bo.Histogram;
import com.ruoyi.demo.entity.bo.StoreWdCategoryCount;
import com.ruoyi.demo.entity.bo.StoreWdCategoryCountBody;
import com.ruoyi.demo.entity.vo.TopologicalWdAceeptVo;
import com.ruoyi.demo.mapper.StoreWdDao;
import com.ruoyi.demo.mapper.WdInfoDao;
import com.ruoyi.demo.service.TopologicalStoreWdService;
import com.ruoyi.demo.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 org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Service
@Transactional
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);
        if (wdInfo1 == null)
            return new ArrayList<>();
        //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());
        });

        if (aroundWdId.isEmpty()){
            return new ArrayList<>();
        }


        //4.分页查找网点信息
        QueryWrapper<WdInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("wd_type_code","1");
        queryWrapper.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);
        if (wdInfo1 == null)
            return new ArrayList<>();
        //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());
        });

        if (aroundWdId.isEmpty())
            return new ArrayList<>();

        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;
    }

    @Override
    public List<Histogram> storeHistogram(TopologicalWdAceeptVo topologicalWdAceeptVo) {
        //1.根据中心网点Id找到网点详细信息
        QueryWrapper<WdInfo> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("wd_id",topologicalWdAceeptVo.getCenterWdId());
        WdInfo wdInfo1 = wdInfoDao.selectOne(queryWrapper1);
        if (wdInfo1 == null)
            return new ArrayList<>();
        //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());
        });

        if (aroundWdId.isEmpty())
            return new ArrayList<>();

        QueryWrapper<WdInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("type_code_by","count(*) as audit");
        queryWrapper.and(queryWrapper2 -> {
            queryWrapper2.eq("wd_type_code","1");
        });
        queryWrapper.and(queryWrapper2 -> {
            queryWrapper2.isNotNull("type_code_by");
        });
        queryWrapper.groupBy("type_code_by");
        List<WdInfo> wdInfos = wdInfoDao.selectList(queryWrapper);

        int total = 0;
        HashMap<String,Integer> hashMap = new HashMap<>();
        for (WdInfo wdInfo : wdInfos) {
            if(wdInfo.getTypeCodeBy() == null)
                continue;
            String typeCodeBy = wdInfo.getTypeCodeBy().substring(0,2);
            Integer integer = hashMap.get(typeCodeBy);
            if (integer == null){
                hashMap.put(typeCodeBy,wdInfo.getAudit());
            }else {
                hashMap.put(typeCodeBy,hashMap.get(typeCodeBy)+wdInfo.getAudit());
            }
            total+=wdInfo.getAudit();
        }

        ArrayList<Histogram> list = new ArrayList<>();
        for (String s : hashMap.keySet()) {
            Integer integer = hashMap.get(s);
            String initTypeByMap = initMapUtil.getInitTypeByMap(s + "0000").replace(":","");
            Histogram histogram = new Histogram();
            histogram.setName(initTypeByMap);
            histogram.setCount(integer);
            list.add(histogram);
        }

        return list;
    }

    @Override
    public List<Histogram> perCapitaConsumpHistogram(TopologicalWdAceeptVo topologicalWdAceeptVo) {
        //1.根据中心网点Id找到网点详细信息
        QueryWrapper<WdInfo> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("wd_id",topologicalWdAceeptVo.getCenterWdId());
        WdInfo wdInfo1 = wdInfoDao.selectOne(queryWrapper1);
        if (wdInfo1 == null)
            return new ArrayList<>();
        //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());
        });

        if (aroundWdId.isEmpty())
            return new ArrayList<>();

        QueryWrapper<WdInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("wd_id");
        queryWrapper.and(queryWrapper2 -> {
            queryWrapper2.eq("wd_type_code","1");
        });
        List<StoreWd> storeWds = storeWdDao.perCapitaConsumpAnalyse(queryWrapper);
        HashMap<String, Integer> hashMap = new HashMap<>();
        hashMap.put("0~20",0);
        hashMap.put("20~50",0);
        hashMap.put("50~100",0);
        hashMap.put("100~200",0);
        hashMap.put("200以上",0);
        for (StoreWd storeWd : storeWds) {
            if (storeWd.getPerCapitaConsumption() != null){
                if (storeWd.getPerCapitaConsumption() >= 0 && storeWd.getPerCapitaConsumption()<20){
                    hashMap.put("0~20",hashMap.get("0~20")+1);
                }else if(storeWd.getPerCapitaConsumption() >= 20 && storeWd.getPerCapitaConsumption()<50){
                    hashMap.put("20~50",hashMap.get("20~50")+1);
                }else if(storeWd.getPerCapitaConsumption() >= 50 && storeWd.getPerCapitaConsumption()< 100){
                    hashMap.put("50~100",hashMap.get("50~100")+1);
                }else if(storeWd.getPerCapitaConsumption() >= 100 && storeWd.getPerCapitaConsumption()< 200){
                    hashMap.put("100~200",hashMap.get("100~200")+1);
                }else {
                    hashMap.put("200以上",hashMap.get("200以上")+1);
                }
            }
        }

        ArrayList<Histogram> list = new ArrayList<>();
        for (String s : hashMap.keySet()) {
            Histogram histogram = new Histogram();
            histogram.setName(s);
            histogram.setCount(hashMap.get(s));
            list.add(histogram);
        }
        return list;
    }
}
