package com.sptg.permissions.biz.service.impl;

import com.baomidou.mybatisplus.enums.SqlLike;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.sptg.common.core.beans.ResultBean;
import com.sptg.common.core.beans.ResultEnum;
import com.sptg.common.core.constant.OperationConstant;
import com.sptg.permissions.api.dto.AreaDto;
import com.sptg.permissions.api.entity.AppArea;
import com.sptg.permissions.api.entity.Area;
import com.sptg.permissions.biz.mapper.AreaMapper;
import com.sptg.permissions.biz.service.AreaServiceInterface;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.ReactiveRedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * title: AreaServiceImpl
 * package: com.sptg.permissions.biz.security.impl
 * description: 全国省市区街道-服务层实现类
 *
 *
 *
 */
@Service
@CacheConfig(cacheNames = AreaServiceInterface.SUB_AREA_CACHE_NAME)
@RequiredArgsConstructor
public class AreaServiceImpl extends ServiceImpl<AreaMapper, Area> implements AreaServiceInterface {
    private final RedisTemplate<String,String> redisTemplate;

    /**
     * 功能描述: 重写父类方法,添加过滤已被删除的记录
     * @param wrapper 查询条件
     * @return Area
     *
     *
     */
    @Override
    public Area selectOne(Wrapper<Area> wrapper) {
        wrapper.notIn("i_status", OperationConstant.MINUS_ONE);
        return super.selectOne(wrapper);
    }

    /**
     * 功能描述: 重写父类方法,添加过滤已被删除的记录
     * @param wrapper 查询条件
     * @return List<Area>
     *
     *
     */
    @Override
    public List<Area> selectList(Wrapper<Area> wrapper) {
        wrapper.notIn("i_status", OperationConstant.MINUS_ONE);
        return super.selectList(wrapper);
    }

    @Override
    @Cacheable(key = "#parentCode",unless = "#result.size() <= 0")
    public List<Area> getSubList(Serializable parentCode) {
        Wrapper<Area> wrapper = new EntityWrapper<>();
        wrapper.eq("s_parent_code",parentCode);
        return this.selectList(wrapper);
    }

    @Override
    @Cacheable(cacheNames = AreaServiceInterface.AREA_CACHE_NAME,key = "#code",unless = "null == #result")
    public Area selectByCode(Serializable code) {
        Wrapper<Area> wrapper = new EntityWrapper<>();
        wrapper.eq("s_code",code);
        return this.selectOne(wrapper);
    }

    @Override
    public Map<String ,Object> selectByNameAndLayer(AreaDto dto) {
        List<Map<String,Object>> areaList = this.baseMapper.getAreaByNameAndLayer(dto.getRegionProvince(),dto.getRegionCity(),dto.getRegionArea());
        if (null == areaList || areaList.size() == 0){
            return null;
        }
        return areaList.get(0);
    }

    private Area selectCityByName(String name){
        Wrapper<Area> wrapper = new EntityWrapper<>();
        wrapper.eq("s_name",name);
        wrapper.eq("i_layer_number",2);
        return this.selectOne(wrapper);
    }

    @Override
    public List<Area> selectCityAndProvinceByName(String name){
        //  查询城市
        Area city = this.selectCityByName(name);
        Assert.notNull(city,"城市名称不存在");
        //  查询省份
        Area province = this.selectByCode(city.getParentCode());
        Assert.notNull(province,"数据异常");

        return new ArrayList<>(Arrays.asList(province,city));
//        return this.baseMapper.selectCityAndProvinceByName(name);
    }
    @Override
    public List<AppArea> selectAll() {
        Wrapper<Area> wrapper = new EntityWrapper<>();
        List<Area> areas = baseMapper.selectList(wrapper);
        List<AppArea> appAreas = new ArrayList<>();
        for(Area area : areas){
            String layerNumber = area.getLayerNumber();
            if(layerNumber.equals("2")){
                AppArea appArea = new AppArea();
                appArea.setName(area.getName());
                appArea.setCode(area.getCode());
                appArea.setCounty(new ArrayList<>());
                appAreas.add(appArea);
            }
        }
        for(Area area : areas){
            String layerNumber = area.getLayerNumber();
            if(layerNumber.equals("3")){
                String parentCode = area.getParentCode();
                for(int i = 0; i < appAreas.size(); i++){
                    AppArea parent = appAreas.get(i);
                    if(parent.getCode().equals(parentCode)){
                        AppArea child = new AppArea();
                        child.setName(area.getName());
                        child.setCode(area.getCode());
                        parent.getCounty().add(child);
                    }
                }
            }
        }
        return appAreas;
    }
    @Override
    public ResultBean<Page<Area>> pagingQuery(AreaDto areaDto) {
        Wrapper<Area> wrapper = new EntityWrapper<>();
        wrapper.notIn("i_status",OperationConstant.MINUS_ONE);
        wrapper.like(areaDto.getCode() != null,"s_code",areaDto.getCode(), SqlLike.DEFAULT);
        wrapper.like(areaDto.getParentCode() != null,"s_parent_code",areaDto.getParentCode(), SqlLike.DEFAULT);
        wrapper.like(areaDto.getName() != null,"s_name",areaDto.getName(),SqlLike.DEFAULT);
        wrapper.like(areaDto.getZipCode() != null,"s_zip_code",areaDto.getZipCode(),SqlLike.DEFAULT);
        return new ResultBean<>(ResultEnum.SUCCESS,super.selectPage(areaDto.getPage(),wrapper));
    }
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public ResultBean<Boolean> addArea(AreaDto areaDto) {
        ValueOperations<String, String> operations = this.redisTemplate.opsForValue();
        operations.getOperations().delete(AreaServiceInterface.SUB_AREA_CACHE_NAME +"::"+ areaDto.getParentCode());
        return new ResultBean<>(ResultEnum.SUCCESS,super.insert(areaDto));
    }
    @Override
    public Area getById(Serializable id) {
        return super.selectById(id);
    }
    @Override
    @Transactional(rollbackFor = Throwable.class)
    public ResultBean<Boolean> delete(Area area) {
        ValueOperations<String, String> operations = this.redisTemplate.opsForValue();
        operations.getOperations().delete(AreaServiceInterface.SUB_AREA_CACHE_NAME +"::"+ area.getParentCode());
        area.setStatus(OperationConstant.MINUS_ONE);
        return new ResultBean<>(ResultEnum.SUCCESS,super.updateById(area));
    }
}
