package com.unis.module.system.service.arealevel;

import cn.hutool.core.util.ObjectUtil;
import com.github.yitter.idgen.YitIdHelper;
import com.unis.framework.security.core.LoginUser;
import com.unis.framework.security.core.util.SecurityFrameworkUtils;
import com.unis.module.system.dal.dataobject.user.AdminUserDO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

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

import com.unis.module.system.controller.admin.arealevel.vo.*;
import com.unis.module.system.dal.dataobject.arealevel.AreaLevelDO;
import com.unis.framework.common.pojo.PageResult;
import com.unis.framework.common.pojo.PageParam;
import com.unis.framework.common.util.object.BeanUtils;

import com.unis.module.system.dal.mysql.arealevel.AreaLevelMapper;

import static com.unis.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.unis.module.system.enums.ErrorCodeConstants.*;

/**
 * 行政区划 Service 实现类
 *
 * @author 超级管理员
 */
@Slf4j
@Service
@Validated
public class AreaLevelServiceImpl implements AreaLevelService {

    @Resource
    private AreaLevelMapper areaLevelMapper;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    private static final String ALL_AREA_LEVEL_KEY = "all_area_levels";

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createAreaLevel(AreaLevelSaveReqVO createReqVO) {
        try {
            // 插入
            AreaLevelDO areaLevel = BeanUtils.toBean(createReqVO, AreaLevelDO.class);
            areaLevel.setId(YitIdHelper.nextId());
            areaLevelMapper.insert(areaLevel);

            // 删除缓存
            redisTemplate.delete(ALL_AREA_LEVEL_KEY);

            // 重新获取并设置缓存
            List<AreaLevelDO> allAreaLevels = areaLevelMapper.selectList();
            // 将数据存入 Redis，设置过期时间为不过期
            AreaLevelDO areaLevelDO = new AreaLevelDO();
            areaLevelDO.setAreaLevel(0);
            areaLevelDO.setAreaCode("0");
            areaLevelDO.setAreaName("国家粮食交易中心");
            areaLevelDO.setId(0L);
            allAreaLevels.add(areaLevelDO);
            redisTemplate.opsForValue().set(ALL_AREA_LEVEL_KEY, allAreaLevels);

            // 返回
            return areaLevel.getId();
        } catch (Exception e) {
            // 发生异常时回滚数据库事务
            throw e;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAreaLevel(AreaLevelSaveReqVO updateReqVO) {
        try {
            // 校验存在
            validateAreaLevelExists(updateReqVO.getId());
            // 更新
            AreaLevelDO updateObj = BeanUtils.toBean(updateReqVO, AreaLevelDO.class);
            areaLevelMapper.updateById(updateObj);

            // 删除缓存
            redisTemplate.delete(ALL_AREA_LEVEL_KEY);

            // 重新获取并设置缓存
            List<AreaLevelDO> allAreaLevels = areaLevelMapper.selectList();
            // 将数据存入 Redis，设置过期时间为不过期
            AreaLevelDO areaLevelDO = new AreaLevelDO();
            areaLevelDO.setAreaLevel(0);
            areaLevelDO.setAreaCode("0");
            areaLevelDO.setAreaName("国家粮食交易中心");
            areaLevelDO.setId(0L);
            allAreaLevels.add(areaLevelDO);
            redisTemplate.opsForValue().set(ALL_AREA_LEVEL_KEY, allAreaLevels);
        } catch (Exception e) {
            // 发生异常时回滚数据库事务
            throw e;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAreaLevel(Long id) {
        try {
            // 校验存在
            validateAreaLevelExists(id);
            // 删除
            areaLevelMapper.deleteById(id);

            // 删除缓存
            redisTemplate.delete(ALL_AREA_LEVEL_KEY);

            // 重新获取并设置缓存
            List<AreaLevelDO> allAreaLevels = areaLevelMapper.selectList();
            // 将数据存入 Redis，设置过期时间为不过期
            AreaLevelDO areaLevelDO = new AreaLevelDO();
            areaLevelDO.setAreaLevel(0);
            areaLevelDO.setAreaCode("0");
            areaLevelDO.setAreaName("国家粮食交易中心");
            areaLevelDO.setId(0L);
            allAreaLevels.add(areaLevelDO);
            redisTemplate.opsForValue().set(ALL_AREA_LEVEL_KEY, allAreaLevels);
        } catch (Exception e) {
            // 发生异常时回滚数据库事务
            throw e;
        }
    }

    private void validateAreaLevelExists(Long id) {
        if (areaLevelMapper.selectById(id) == null) {
            throw exception(AREA_LEVEL_NOT_EXISTS);
        }
    }

    @Override
    public AreaLevelDO getAreaLevel(Long id) {
        AreaLevelDO resp = new AreaLevelDO();

        List<AreaLevelDO> allAreaLevels = (List<AreaLevelDO>) redisTemplate.opsForValue().get(ALL_AREA_LEVEL_KEY);
        if (allAreaLevels != null) {
            for (AreaLevelDO allAreaLevel : allAreaLevels) {
                if (Objects.equals(id, allAreaLevel.getId())) {
                    resp = allAreaLevel;
                    break;
                }
            }
        }else {
            resp = areaLevelMapper.selectById(id);
        }
        return resp;
    }

    @Override
    public List<AreaLevelDO> getAreaShengLevel() {
        List<AreaLevelDO> respList;

        List<AreaLevelDO> allAreaLevels = (List<AreaLevelDO>) redisTemplate.opsForValue().get(ALL_AREA_LEVEL_KEY);
        if (allAreaLevels != null) {
            respList = allAreaLevels.stream().filter(areaLevelDO -> areaLevelDO.getAreaLevel() == 1).collect(Collectors.toList());
        }else {
            respList = areaLevelMapper.selectShengLevel();
        }
        return respList;

    }

    @Override
    public List<AreaLevelDO> getAreaListByParentCode(String parentCode) {
        List<AreaLevelDO> respList;

        List<AreaLevelDO> allAreaLevels = (List<AreaLevelDO>) redisTemplate.opsForValue().get(ALL_AREA_LEVEL_KEY);
        if (allAreaLevels != null) {
            respList = allAreaLevels.stream().filter(areaLevelDO -> parentCode.equals(areaLevelDO.getParentCode())).collect(Collectors.toList());
        }else {
            respList = areaLevelMapper.selectListByParentCode(parentCode);
        }
        return respList;
    }

    @Override
    public List<AreaLevelDO> getAreaLevelListAll(AdminUserDO user) {
        // 尝试从 Redis 中获取所有行政区划数据
        List<AreaLevelDO> allAreaLevels = (List<AreaLevelDO>) redisTemplate.opsForValue().get(ALL_AREA_LEVEL_KEY);
        if (allAreaLevels == null) {
            // 如果 Redis 中没有数据，则从数据库中获取
            allAreaLevels = areaLevelMapper.selectList();
            // 将数据存入 Redis，设置过期时间为不过期
            AreaLevelDO areaLevelDO = new AreaLevelDO();
            areaLevelDO.setAreaLevel(0);
            areaLevelDO.setAreaCode("0");
            areaLevelDO.setAreaName("国家粮食交易中心");
            areaLevelDO.setId(0L);
            allAreaLevels.add(areaLevelDO);
            redisTemplate.opsForValue().set(ALL_AREA_LEVEL_KEY, allAreaLevels);
        }

        // 国家局或者管理员
        if (ObjectUtil.isEmpty(user.getAreaLevel()) || user.getAreaLevel() == 0) {
            return allAreaLevels;
        }
        // 省一级用户
        else if (user.getAreaLevel() == 1) {
            AreaLevelDO areaLevelDO = getAreaLevelFromList(allAreaLevels, user.getAreaCode());
            List<AreaLevelDO> temp = getSubAreasRecursivelyFromList(allAreaLevels, user.getAreaCode());
            if (areaLevelDO != null) {
                temp.add(areaLevelDO);
            }
            return temp;
        }
        // 市一级用户
        else if (user.getAreaLevel() == 2) {
            AreaLevelDO areaLevelDO = getAreaLevelFromList(allAreaLevels, user.getAreaCode());
            List<AreaLevelDO> temp = getSubAreasRecursivelyFromList(allAreaLevels, user.getAreaCode());
            if (areaLevelDO != null) {
                temp.add(areaLevelDO);
            }
            return temp;
        }
        // 县一级用户
        else if (user.getAreaLevel() == 3) {
            // 县级是最低级别，只返回自身
            AreaLevelDO areaLevelDO = getAreaLevelFromList(allAreaLevels, user.getAreaCode());
            if (areaLevelDO != null) {
                return Collections.singletonList(areaLevelDO);
            }
        }
        // 返回空列表或其他默认行为
        return Collections.emptyList();
    }

    private AreaLevelDO getAreaLevelFromList(List<AreaLevelDO> allAreaLevels, String areaCode) {
        for (AreaLevelDO areaLevel : allAreaLevels) {
            if (areaCode.equals(areaLevel.getAreaCode())) {
                return areaLevel;
            }
        }
        return null;
    }

    private List<AreaLevelDO> getSubAreasRecursivelyFromList(List<AreaLevelDO> allAreaLevels, String parentCode) {
        List<AreaLevelDO> subAreas = new ArrayList<>();
        for (AreaLevelDO areaLevel : allAreaLevels) {
            if (parentCode.equals(areaLevel.getParentCode())) {
                subAreas.add(areaLevel);
                subAreas.addAll(getSubAreasRecursivelyFromList(allAreaLevels, areaLevel.getAreaCode()));
            }
        }
        return subAreas;
    }

    @Override
    public List<AreaLevelDO> getLoginUserXzqhConcise(String areaCode) {
        List<AreaLevelDO> respList;

        List<AreaLevelDO> allAreaLevels = (List<AreaLevelDO>) redisTemplate.opsForValue().get(ALL_AREA_LEVEL_KEY);
        if (allAreaLevels != null) {
            respList = allAreaLevels.stream().filter(areaLevelDO -> areaCode.equals(areaLevelDO.getParentCode())).collect(Collectors.toList());
        }else {
            respList = areaLevelMapper.selectListByParentCode(areaCode);
        }

        return respList;
    }

    @Override
    public PageResult<AreaLevelDO> getAreaLevelPage(AreaLevelPageReqVO pageReqVO) {
        return areaLevelMapper.selectPage(pageReqVO);
    }

}