
package com.tmerclub.cloud.delivery.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.tmerclub.cloud.common.cache.constant.CacheNames;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.order.vo.AreaVO;
import com.tmerclub.cloud.common.order.dto.AreaDTO;
import com.tmerclub.cloud.delivery.mapper.AreaMapper;
import com.tmerclub.cloud.delivery.model.Area;
import com.tmerclub.cloud.delivery.service.AreaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 省市区地区信息
 *
 * @author YXF
 * @date 2020-11-25 14:48:52
 */
@Service
public class AreaServiceImpl implements AreaService {

    @Autowired
    private AreaMapper areaMapper;

    @Override
    public List<AreaVO> list(AreaDTO areaDTO) {
        return areaMapper.list(areaDTO);
    }

    @Override
    @Cacheable(cacheNames = CacheNames.AREA_INFO_KEY, key = "'areaList'", sync = true)
    public List<AreaVO> getAreaListInfo() {
        List<AreaVO> list = areaMapper.getAreaListInfo();
        Map<Long, List<AreaVO>> areaMap = list.stream().collect(Collectors.groupingBy(AreaVO::getParentId));
        List<AreaVO> regionList = areaMap.get(0L);
        if (CollUtil.isEmpty(regionList)) {
            return new ArrayList<>(0);
        }
        List<AreaVO> areaList = new ArrayList<>(Constant.INITIAL_CAPACITY);

        Iterator<AreaVO> iterator = regionList.iterator();
        while (iterator.hasNext()) {
            AreaVO areaVO = iterator.next();
            List<AreaVO> provinceList = areaMap.get(areaVO.getAreaId());
            if (CollUtil.isEmpty(provinceList)) {
                iterator.remove();
                continue;
            }
            extracted(provinceList, areaMap);
            for (AreaVO province : provinceList) {
                List<Long> cityIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
                for (AreaVO city : province.getAreas()) {
                    cityIds.add(city.getAreaId());
                    List<Long> areaIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
                    for (AreaVO area : city.getAreas()) {
                        areaIds.add(area.getAreaId());
                    }
                    city.setAreaIds(areaIds);
                }
                province.setAreaIds(cityIds);
            }
            areaList.addAll(provinceList);
        }
        return areaList;
    }

    @Override
    @Cacheable(cacheNames = CacheNames.AREA_INFO_KEY, key = "'listAreaOfEnable'", sync = true)
    public List<AreaVO> listAreaOfEnable() {
        List<AreaVO> list = areaMapper.listAreaOfEnable();
        Map<Long, List<AreaVO>> areaMap = list.stream().collect(Collectors.groupingBy(AreaVO::getParentId));
        list = list.stream().filter(areaVO -> Objects.equals(areaVO.getLevel(), 1)).collect(Collectors.toList());
        extracted(list, areaMap);
        return list;
    }

    private void extracted(List<AreaVO> list, Map<Long, List<AreaVO>> areaMap) {
        if (CollUtil.isEmpty(list)) {
            return;
        }
        Iterator<AreaVO> iterator = list.iterator();
        while (iterator.hasNext()) {
            AreaVO areaVO = iterator.next();
            if (!areaMap.containsKey(areaVO.getAreaId())) {
                iterator.remove();
                continue;
            }
            List<AreaVO> cityList = new ArrayList<>(Constant.INITIAL_CAPACITY);
            List<Long> areaids = new ArrayList<>(Constant.INITIAL_CAPACITY);
            for (AreaVO city : areaMap.get(areaVO.getAreaId())) {
                if (!areaMap.containsKey(city.getAreaId())) {
                    continue;
                }
                city.setAreas(areaMap.get(city.getAreaId()));
                List<Long> areaIdsList = new ArrayList<>(Constant.INITIAL_CAPACITY);
                city.getAreas().forEach(s -> areaIdsList.add(s.getAreaId()));
                city.setAreaIds(areaIdsList);
                cityList.add(city);
                areaids.add(city.getAreaId());
            }
            if (CollUtil.isEmpty(cityList)) {
                iterator.remove();
                continue;
            }
            areaVO.setAreas(cityList);
            areaVO.setAreaIds(areaids);
        }
    }

    @Override
    public Integer countByNameAndParentId(String areaName, Integer level, Long parentId, Long areaId) {
        return areaMapper.countByNameAndParentId(areaName, level, parentId, areaId);
    }

    @Override
    public List<AreaVO> listByAreaIdList(List<Long> areIdList) {
        return areaMapper.listByAreaIdList(areIdList);
    }

    @Override
    public AreaVO getByAreaId(Long areaId) {
        return areaMapper.getByAreaId(areaId);
    }

    @Override
    public void save(Area area) {
        areaMapper.save(area);
    }

    @Override
    public void update(Area area) {
        areaMapper.update(area);
    }

    @Override
    public void deleteById(Long areaId) {
        int areaNum = areaMapper.countByAreaId(areaId);
        if (areaNum > 0) {
            throw new LuckException("请先删除子地区");
        }
        areaMapper.deleteById(areaId);
    }

    @Override
    @Cacheable(cacheNames = CacheNames.AREA_KEY, key = "'list:' + #pid")
    public List<AreaVO> listByPid(Long pid) {
        return areaMapper.listByPid(pid);
    }

    @Override
    @Caching(evict = {
            @CacheEvict(cacheNames = CacheNames.AREA_INFO_KEY, key = "'areaList'"),
            @CacheEvict(cacheNames = CacheNames.AREA_INFO_KEY, key = "'listAreaOfEnable'"),
            @CacheEvict(cacheNames = CacheNames.AREA_KEY, key = "'list:' + #pid")
    })
    public void removeAllCache(Long pid) {

    }

    @Override
    @Caching(evict = {
            @CacheEvict(cacheNames = CacheNames.AREA_KEY, key = "'list:' + #pid"),
            @CacheEvict(cacheNames = CacheNames.AREA_INFO_KEY, key = "'areaList'"),
            @CacheEvict(cacheNames = CacheNames.AREA_INFO_KEY, key = "'listAreaOfEnable'")
    })
    public void removeAreaCacheByParentId(Long pid) {

    }
}
