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.*;
import com.ruoyi.demo.entity.bo.*;
import com.ruoyi.demo.entity.vo.ChannelMapAceeptVo;
import com.ruoyi.demo.mapper.*;
import com.ruoyi.demo.service.ChannelMapService;
import com.ruoyi.demo.utils.InitMapUtil;
import com.ruoyi.demo.utils.WdRedisStoreage;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
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;

@RequiredArgsConstructor
@Service
@Transactional
public class ChannelMapServiceImpl implements ChannelMapService {

    @Autowired
    private AddrCategoryDao addrCategoryDao;

    @Autowired
    private WdInfoDao originWdInfoDao;

    @Autowired
    InitMapUtil initMapUtil;


    @Autowired
    AttentionPoolDao attentionPoolDao;

    @Autowired
    WdInfoDao wdInfoDao;


    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    WdRedisStoreage wdRedisStoreage;

    @Autowired
    StoreWdDao storeWdDao;

    @Autowired
    HouseWdDao houseWdDao;

    @Autowired
    BuildWdDao buildWdDao;

    @Autowired
    TrafficWdDao trafficWdDao;

    @Autowired
    EnterpriseWdDao enterpriseWdDao;



    @Override
    public WdCount area(ChannelMapAceeptVo channelMapAceeptVo) {
        //1.根据不同级别得到 需要封装的 地区码
        List<String> addrCodeList = new ArrayList<>();
        if ("province".equals(channelMapAceeptVo.getRankType())) {
            //省码
            for (String s : channelMapAceeptVo.getAddrCode()) {
                String substring = s.substring(0, 2);
                addrCodeList.add(substring);
            }
        } else if ("city".equals(channelMapAceeptVo.getRankType())) {
            //省的所有市
            for (String s : channelMapAceeptVo.getAddrCode()) {
                String substring = s.substring(0, 2);
                addrCodeList.add(substring);
            }
        } else if ("zone".equals(channelMapAceeptVo.getRankType())) {
            //市的所有区
            for (String s : channelMapAceeptVo.getAddrCode()) {
                String substring = s.substring(0, 4);
                addrCodeList.add(substring);
            }
        } else {
            return null;
        }


        //2.找到所有需要封装的 地区信息
        QueryWrapper<AddrCategory> queryWrapper = new QueryWrapper<>();
        if ("province".equals(channelMapAceeptVo.getRankType())) {
            queryWrapper.eq("city", "");
        } else if ("city".equals(channelMapAceeptVo.getRankType())) {
            queryWrapper.eq("district", "").and(addrCategoryQueryWrapper -> {
                addrCategoryQueryWrapper.ne("city", "");
            });
        } else if ("zone".equals(channelMapAceeptVo.getRankType())) {
            queryWrapper.ne("district", "");
        }
        queryWrapper.and(addrCategoryQueryWrapper -> {
            addrCategoryQueryWrapper.or(addrCategoryQueryWrapper1 -> {
                for (String s : addrCodeList) {
                    addrCategoryQueryWrapper1.likeRight("addr_code", s).or();
                }
            });
        });
        List<AddrCategory> addrCategories = addrCategoryDao.selectList(queryWrapper);


        //3.组装地区信息
        List<WdCountBody> result = new ArrayList<>();
        HashMap<String,Integer> statistics = new HashMap<>(); //统计信息
        for (AddrCategory addrCategory : addrCategories) {
            WdCountBody wdCountBody = new WdCountBody();

            //组装
            wdCountBody.setLat(addrCategory.getLatGd());
            wdCountBody.setLng(addrCategory.getLngGd());
            wdCountBody.setAddrCode(addrCategory.getAddrCode());
            if ("province".equals(channelMapAceeptVo.getRankType())) {
                wdCountBody.setName(addrCategory.getProvince());
                statistics.put(addrCategory.getAddrCode().substring(0,2),0);
            } else if ("city".equals(channelMapAceeptVo.getRankType())) {
                wdCountBody.setName(addrCategory.getCity());
                statistics.put(addrCategory.getAddrCode().substring(0,4),0);
            } else if ("zone".equals(channelMapAceeptVo.getRankType())) {
                wdCountBody.setName(addrCategory.getDistrict());
                statistics.put(addrCategory.getAddrCode().substring(0,6),0);
            }
            result.add(wdCountBody);
        }


        //4.组装条件构造器找到网点信息网点
        //2.1 渠道、地区分类
        QueryWrapper<WdInfo> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.select("addr_code","count(*) as audit");
        queryWrapper2.in("wd_type_code", channelMapAceeptVo.getChannel()).and(originWdInfoQueryWrapper -> {
            for (String s : addrCodeList) {
                originWdInfoQueryWrapper.likeRight("addr_code", s).or();
            }
        });

        //搜索字段
        if (channelMapAceeptVo.getSearchText() != null && !channelMapAceeptVo.getSearchText().trim().equals("")) {
            queryWrapper2.and(originWdInfoQueryWrapper -> {
                originWdInfoQueryWrapper.like("wd_name", channelMapAceeptVo.getSearchText() );
            });
        }

        //城市等级分类
        if(channelMapAceeptVo.getCityTier() != null && channelMapAceeptVo.getCityTier().length > 0){
            List<String> tierCode = new ArrayList<>();
            for (String s : channelMapAceeptVo.getCityTier()) {
                List<String> list = initMapUtil.getInitCityTierListMap(s);
                if (list != null){
                    tierCode.addAll(list);
                }
            }
            queryWrapper.and(wdInfoQueryWrapper -> {
                for (String s : tierCode) {
                    wdInfoQueryWrapper.likeRight("addr_code", s).or();
                }
            });
        }
        queryWrapper2.groupBy("addr_code");

        //5.统计
        int total = 0;
        List<WdInfo> wdInfos = wdInfoDao.selectList(queryWrapper2);
        for (WdInfo wdInfo : wdInfos) {
            if("province".equals(channelMapAceeptVo.getRankType())){
                statistics.put(wdInfo.getAddrCode().substring(0,2),statistics.get(wdInfo.getAddrCode().substring(0,2))+wdInfo.getAudit());
            } else if ("city".equals(channelMapAceeptVo.getRankType())) {
                statistics.put(wdInfo.getAddrCode().substring(0,4),statistics.get(wdInfo.getAddrCode().substring(0,4))+wdInfo.getAudit());
            } else if ("zone".equals(channelMapAceeptVo.getRankType())) {
                statistics.put(wdInfo.getAddrCode().substring(0,6),statistics.get(wdInfo.getAddrCode().substring(0,6))+wdInfo.getAudit());
            }
            total+=+wdInfo.getAudit();
        }


        //5.计算radio
        for (WdCountBody wdCountBody : result) {
            String code =  null;
            if("province".equals(channelMapAceeptVo.getRankType())){
                code = wdCountBody.getAddrCode().substring(0,2);
            }else if("city".equals(channelMapAceeptVo.getRankType())){
                code = wdCountBody.getAddrCode().substring(0,4);
            }else if("zone".equals(channelMapAceeptVo.getRankType())){
                code = wdCountBody.getAddrCode().substring(0,6);
            }

            if(statistics.get(code) != null){
                wdCountBody.setCount(statistics.get(code));
            }else {
                wdCountBody.setCount(0);
            }

            if (total != 0){
                BigDecimal bigDecimal = new BigDecimal((float) wdCountBody.getCount() / total);
                float v = bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).floatValue();
                wdCountBody.setRadio(v);
            }
            else
                wdCountBody.setRadio(0.0f);
        }
        WdCount wdCount = new WdCount();
        wdCount.setWdCountBodyList(result);
        wdCount.setTotal(total);
        return wdCount;
    }


    //TODO 待测试（redis版本）
    @Override
    public HashMap list(ChannelMapAceeptVo channelMapAceeptVo) {
        //1.根据条件获取网点
        QueryWrapper<WdInfo> queryWrapper = new QueryWrapper<>();
        assembleQueryWrapper(queryWrapper,channelMapAceeptVo);

        PageHelper.startPage(channelMapAceeptVo.getPageNum(), channelMapAceeptVo.getPageSize());
        List<WdInfo> originWdInfos = wdInfoDao.selectList(queryWrapper);
        PageInfo<WdInfo> PageInfo = new PageInfo<>(originWdInfos);

        //2.获取标签并组装
        List<WdTopologicalInfoBo> result = new ArrayList<>();   //返回的封装网点数据集
        for (WdInfo wdInfo : PageInfo.getList()) {
            WdTopologicalInfoBo wdTopologicalInfoBo = new WdTopologicalInfoBo(wdInfo);
            wdTopologicalInfoBo.setAddrCodeInfo(initMapUtil.getInitAddrCodeMap(wdInfo.getAddrCode()));
            List<String> tags = wdRedisStoreage.getWdTag(wdInfo);
            wdTopologicalInfoBo.setTag(tags);
            result.add(wdTopologicalInfoBo);
        }

        //返回结果集
        PageInfo.setList(null);
        HashMap data = new HashMap();
        data.put("data",result);
        data.put("page",PageInfo);

        return data;
    }

    @Override
    public PageInfo<WdInfo> point(String[] channel, String searchText, String[] addrCode, int pageNum, int pageSize) {
        QueryWrapper<WdInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("wd_type_code", channel);
        for (String s : addrCode) {
            queryWrapper.and(originWdInfoQueryWrapper -> {
                originWdInfoQueryWrapper.eq("addr_code",s);
            });
        }
        if (searchText != null && !searchText.trim().equals("")) {
            queryWrapper.and(originWdInfoQueryWrapper -> {
                originWdInfoQueryWrapper.like("wd_name", searchText);
            });
        }
        PageHelper.startPage(pageNum, pageSize);
        List<WdInfo> originWdInfos = originWdInfoDao.selectList(queryWrapper);
        PageInfo<WdInfo> PageInfo = new PageInfo<>(originWdInfos);
        return PageInfo;
    }

    @Override
    public WdInfo getWdInfo(String wdId) {
        QueryWrapper<WdInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("wd_id",wdId);

        WdInfo wdInfo = wdInfoDao.selectOne(queryWrapper);
        if(wdInfo == null)
            return wdInfo;

        if("1".equals(wdInfo.getWdTypeCode())){
            QueryWrapper<StoreWd> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.eq("wd_id",wdId);
            StoreWd storeWd = storeWdDao.selectOne(queryWrapper1);
            StoreWdInfoBo storeWdInfoBo = new StoreWdInfoBo(wdInfo);
            storeWdInfoBo.setStoreWd(storeWd);
            storeWdInfoBo.setTags(wdRedisStoreage.getWdTag(wdInfo));
            storeWdInfoBo.setAddrCode(initMapUtil.getInitAddrCodeMap(storeWdInfoBo.getAddrCode()));
            return storeWdInfoBo;
        }else if("2".equals(wdInfo.getWdTypeCode())){
            QueryWrapper<HouseWd> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.eq("wd_id",wdId);
            HouseWd houseWd = houseWdDao.selectOne(queryWrapper1);
            HouseWdInfoBo houseWdInfoBo = new HouseWdInfoBo(wdInfo);
            houseWdInfoBo.setHouseWd(houseWd);
            houseWdInfoBo.setTags(wdRedisStoreage.getWdTag(wdInfo));
            houseWdInfoBo.setAddrCode(initMapUtil.getInitAddrCodeMap(houseWdInfoBo.getAddrCode()));
            return houseWdInfoBo;
        }else if("3".equals(wdInfo.getWdTypeCode())){
            QueryWrapper<BuildWd> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.eq("wd_id",wdId);
            BuildWd buildWd = buildWdDao.selectOne(queryWrapper1);
            BuildWdInfoBo buildWdInfoBo = new BuildWdInfoBo(wdInfo);
            buildWdInfoBo.setBuildWd(buildWd);
            buildWdInfoBo.setTags(wdRedisStoreage.getWdTag(wdInfo));
            buildWdInfoBo.setAddrCode(initMapUtil.getInitAddrCodeMap(buildWdInfoBo.getAddrCode()));
            return buildWdInfoBo;
        }else if("4".equals(wdInfo.getWdTypeCode())){
            QueryWrapper<TrafficWd> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.eq("wd_id",wdId);
            TrafficWd trafficWd = trafficWdDao.selectOne(queryWrapper1);
            TrafficWdInfoBo trafficWdInfoBo = new TrafficWdInfoBo(wdInfo);
            trafficWdInfoBo.setTrafficWd(trafficWd);
            trafficWdInfoBo.setTags(wdRedisStoreage.getWdTag(wdInfo));
            trafficWdInfoBo.setAddrCode(initMapUtil.getInitAddrCodeMap(trafficWdInfoBo.getAddrCode()));
            return trafficWdInfoBo;
        }else if("5".equals(wdInfo.getWdTypeCode())){
            QueryWrapper<EnterpriseWd> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.eq("wd_id",wdId);
            EnterpriseWd enterpriseWd = enterpriseWdDao.selectOne(queryWrapper1);
            EnterpriseWdInfoBo enterpriseWdInfoBo = new EnterpriseWdInfoBo(wdInfo);
            enterpriseWdInfoBo.setEnterpriseWd(enterpriseWd);
            enterpriseWdInfoBo.setTags(wdRedisStoreage.getWdTag(wdInfo));
            enterpriseWdInfoBo.setAddrCode(initMapUtil.getInitAddrCodeMap(enterpriseWdInfoBo.getAddrCode()));
            return enterpriseWdInfoBo;
        }

        return wdInfo;
    }

    public void assembleQueryWrapper(QueryWrapper<WdInfo> queryWrapper,ChannelMapAceeptVo channelMapAceeptVo){
        //1.根据不同级别得到需要查询的 地区码
        List<String> addrCodeList = new ArrayList<>();
        if ("province".equals(channelMapAceeptVo.getRankType())) {
            //省码
            for (String s : channelMapAceeptVo.getAddrCode()) {
                String substring = s.substring(0, 2);
                addrCodeList.add(substring);
            }
        } else if ("city".equals(channelMapAceeptVo.getRankType())) {
            //省的所有市
            for (String s : channelMapAceeptVo.getAddrCode()) {
                String substring = s.substring(0, 2);
                addrCodeList.add(substring);
            }
        } else if ("zone".equals(channelMapAceeptVo.getRankType())) {
            //市的所有区
            for (String s : channelMapAceeptVo.getAddrCode()) {
                String substring = s.substring(0, 4);
                addrCodeList.add(substring);
            }
        } else if ("district".equals(channelMapAceeptVo.getRankType())){
            //区的所有街道
            for (String s : channelMapAceeptVo.getAddrCode()) {
                String substring = s.substring(0, 6);
                addrCodeList.add(substring);
            }
        }

        queryWrapper.in("wd_type_code", channelMapAceeptVo.getChannel()).and(originWdInfoQueryWrapper -> {
            for (String s : addrCodeList) {
                originWdInfoQueryWrapper.likeRight("addr_code", s).or();
            }
        });

        //搜索字段
        if (channelMapAceeptVo.getSearchText() != null && !channelMapAceeptVo.getSearchText() .trim().equals("")) {
            queryWrapper.and(originWdInfoQueryWrapper -> {
                originWdInfoQueryWrapper.like("wd_name", channelMapAceeptVo.getSearchText() );
            });
        }

        //城市等级分类
        if(channelMapAceeptVo.getCityTier() != null && channelMapAceeptVo.getCityTier().length > 0){
            List<String> tierCode = new ArrayList<>();
            for (String s : channelMapAceeptVo.getCityTier()) {
                List<String> list = initMapUtil.getInitCityTierListMap(s);
                if (list != null){
                    tierCode.addAll(list);
                }
            }
            queryWrapper.and(wdInfoQueryWrapper -> {
                for (String s : tierCode) {
                    wdInfoQueryWrapper.likeRight("addr_code", s).or();
                }
            });
        }

        //排序字段查询
        if (channelMapAceeptVo.getOrderby() != null && !channelMapAceeptVo.getOrderby().trim().equals("")) {
            PageHelper.orderBy(channelMapAceeptVo.getOrderby());
        }

    }


}
