package com.ruoyi.project.business.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static com.ruoyi.common.constant.CacheConstants.AREA_KEY;
import static com.ruoyi.common.utils.LocalUtils.localAreaNameFun;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.enums.DelFlag;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.project.business.domain.TbArea;
import com.ruoyi.project.business.domain.TpElevatorModel;
import com.ruoyi.project.business.domain.vo.country.AreaWithCountriesVo;
import com.ruoyi.project.business.domain.vo.selectParam.AreaParam;
import com.ruoyi.project.business.mapper.TbAgentMapper;
import com.ruoyi.project.business.mapper.TbAreaMapper;
import com.ruoyi.project.business.mapper.TbCountryAreaMapper;
import com.ruoyi.project.business.mapper.TcAccountMapper;
import com.ruoyi.project.business.service.ITbAreaService;
import com.ruoyi.project.business.mapper.TpElevatorModelMapper;
import com.ruoyi.project.common.service.ICommonService;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


/**
 * 区域Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-04-15
 */
@Service
@CacheConfig(cacheManager = "concurrentMapCacheManager")
public class TbAreaServiceImpl implements ITbAreaService
{
    @Autowired
    private TbAreaMapper tbAreaMapper;

    @Resource
    private ICommonService commonService;

    @Resource
    private TbCountryAreaMapper tbCountryAreaMapper;

    @Resource
    private TcAccountMapper tcAccountMapper;

    @Resource
    private TbAgentMapper tbAgentMapper;
    
    @Resource
    private TpElevatorModelMapper tpElevatorModelMapper;

    /**
     * 查询区域
     * 
     * @param areaId 区域主键
     * @return 区域
     */
    @Override
    @Cacheable(value = AREA_KEY, key = "#areaId", cacheManager = "concurrentMapCacheManager")
    public TbArea selectTbAreaByAreaId(Long areaId)
    {
        // 校验数据是否已被删除
        TbArea tbArea = tbAreaMapper.selectTbAreaByAreaId(areaId);
        if (DelFlag.YES.getCode().equals(tbArea.getDelFlag())) {
            throw new ServiceException(MessageUtils.message("business.data.deleted"));
        }
        return tbArea;
    }

    /**
     * 查询区域列表
     * 
     * @param tbArea 区域
     * @return 区域
     */
    @Override
    public List<TbArea> selectTbAreaList(AreaParam tbArea)
    {
        if (StringUtils.isNotEmpty(tbArea.getAreaName())) {
            tbArea.setAreaName(tbArea.getAreaName().replaceAll("%", "/%").replaceAll("_", "/_"));
        }
        if (StringUtils.isNotEmpty(tbArea.getAreaNameUS())) {
            tbArea.setAreaNameUS(tbArea.getAreaNameUS().replaceAll("%", "/%").replaceAll("_", "/_"));
        }
        if (StringUtils.isNotEmpty(tbArea.getAreaNameRU())) {
            tbArea.setAreaNameRU(tbArea.getAreaNameRU().replaceAll("%", "/%").replaceAll("_", "/_"));
        }
        if (StringUtils.isNotEmpty(tbArea.getAreaNameES())) {
            tbArea.setAreaNameES(tbArea.getAreaNameES().replaceAll("%", "/%").replaceAll("_", "/_"));
        }
        return tbAreaMapper.selectTbAreaList(tbArea);
    }

    @Override
    public List<AreaWithCountriesVo> selectTbAreaWithCountriesList(TbArea tbArea) {
        return tbAreaMapper.selectTbAreaWithCountriesList(tbArea);
    }
    
    /**
     * 查询区域列表（导出用）
     *
     * @param tbArea 区域
     * @return 区域
     */
    @Override
    public List<TbArea> selectTbAreaListExport(AreaParam tbArea)
    {
        return tbAreaMapper.selectTbAreaListExport(tbArea);
    }

    /**
     * 新增区域
     * 
     * @param tbArea 区域
     * @return 结果
     */
    @Override
    @Transactional
    @CacheEvict(value = AREA_KEY, allEntries = true)
    public int insertTbArea(TbArea tbArea)
    {
        // 校验区域名称
        int count = tbAreaMapper.selectTbAreaByAreaName(tbArea.getAreaName(), null);
        if (count > 0) {
           throw new ServiceException(MessageUtils.message("area.name.repeat"));
        }
        // 判断是否有上级区域
        if (tbArea.getParentArea() == null) {
            tbArea.setParentArea(0L);
        }
        // 区域ID采番
        tbArea.setAreaId(commonService.getCommonID("seq_area_agent"));
        // 数据权限字符
        tbArea.setPermissionChar(handlePermissionChar(tbArea));
        tbArea.setCreateBy(SecurityUtils.getUserId().toString());
        tbArea.setCreateTime(DateUtils.getNowDate());
        tbArea.setUpdateTime(DateUtils.getNowDate());
        int result = tbAreaMapper.insertTbArea(tbArea);
        // 插入国家区域关联表
        if (StringUtils.isNotEmpty(tbArea.getCountryIds())) {
            String[] countryIds = tbArea.getCountryIds().split(",");
            for (String countryId : countryIds) {
                tbCountryAreaMapper.bindCountryArea(tbArea.getAreaId(), Long.parseLong(countryId));
            }
        }
        return result;
    }

    /**
     * 拼接数据权限字符
     *
     * @param tbArea 区域
     * @return 数据权限字符
     */
    private String handlePermissionChar(TbArea tbArea) {
        String permissionChar;
        if (tbArea.getParentArea() == 0L) {
            permissionChar = "," + tbArea.getAreaId() + ",0,";
        } else {
            TbArea parentArea = tbAreaMapper.selectTbAreaByAreaId(tbArea.getParentArea());
            permissionChar = "," + tbArea.getAreaId() + parentArea.getPermissionChar();
        }
        return permissionChar;
    }

    /**
     * 修改区域
     * 
     * @param tbArea 区域
     * @return 结果
     */
    @Override
    @Transactional
    @CacheEvict(value = AREA_KEY, allEntries = true)
    public int updateTbArea(TbArea tbArea)
    {
        // 校验区域名称
        int count = tbAreaMapper.selectTbAreaByAreaName(tbArea.getAreaName(), tbArea.getAreaId());
        if (count > 0) {
            throw new ServiceException(MessageUtils.message("area.name.repeat"));
        }
        // 判断是否有上级区域
        if (tbArea.getParentArea() == null) {
            tbArea.setParentArea(0L);
        }
        // 数据权限字符
        tbArea.setPermissionChar(handlePermissionChar(tbArea));
        tbArea.setUpdateBy(SecurityUtils.getUserId().toString());
        tbArea.setUpdateTime(DateUtils.getNowDate());
        int result = tbAreaMapper.updateTbArea(tbArea);
        // 修改国家区域关系表
        tbCountryAreaMapper.deleteTbCountryAreaByAreaId(tbArea.getAreaId());
        if (StringUtils.isNotEmpty(tbArea.getCountryIds())) {
            String[] countryIds = tbArea.getCountryIds().split(",");
            for (String countryId : countryIds) {
                tbCountryAreaMapper.bindCountryArea(tbArea.getAreaId(), Long.parseLong(countryId));
            }
        }
        return result;
    }

    /**
     * 批量删除区域
     * 
     * @param areaIds 需要删除的区域主键
     * @return 结果
     */
    @Override
    @Transactional
    @CacheEvict(value = AREA_KEY, allEntries = true)
    public int deleteTbAreaByAreaIds(Long[] areaIds)
    {
        // 校验 当前区域若存在下级区域数据则无法删除
        int count = tbAreaMapper.selectTbAreaByParentAreas(areaIds);
        if (count > 0) {
            throw new ServiceException(MessageUtils.message("area.has.child"));
        }
        // 校验是否有客户使用
        int num = tcAccountMapper.selectCountByAreaIds(areaIds);
        if (num > 0) {
            throw new ServiceException(MessageUtils.message("account.cannot.delete"));
        }
        // 校验是否有代理商使用
        int agentCount = tbAgentMapper.selectCountByAreaIds(areaIds);
        if (agentCount > 0) {
            throw new ServiceException(MessageUtils.message("agent.cannot.delete"));
        }
        // 校验是否有区域电梯配置使用
        boolean existsed = tpElevatorModelMapper.exists(Wrappers.lambdaQuery(TpElevatorModel.class).in(TpElevatorModel::getAreaId, Arrays.asList(areaIds)));
        if (existsed) {
            throw new ServiceException(MessageUtils.message("area.existElevatorModel.cannot.delete"));
        }
        // 同时批量删除国家区域关系表信息
        tbCountryAreaMapper.deleteTbCountryAreaByAreaIds(areaIds);
        return tbAreaMapper.deleteTbAreaByAreaIds(areaIds);
    }

    /**
     * 删除区域信息
     * 
     * @param areaId 区域主键
     * @return 结果
     */
    @Override
    @CacheEvict(value = AREA_KEY, allEntries = true)
    public int deleteTbAreaByAreaId(Long areaId)
    {
        // 同时删除国家区域关系表信息
        tbCountryAreaMapper.deleteTbCountryAreaByAreaId(areaId);
        return tbAreaMapper.deleteTbAreaByAreaId(areaId);
    }

    /**
     * 获取所有区域列表
     * @return 结果
     */
    @Override
    public List<TbArea> getAllAreaList() {
        return tbAreaMapper.getAllAreaList();
    }

    /**
     * 根据区域等级获取区域列表
     * @return 结果
     */
    @Override
    public List<TbArea> getAreaListByLevel(String level) {
        return tbAreaMapper.getAreaListByLevel(level);
    }

    /**
     * 获取所有区域列表
     * @return 结果
     */
    @Override
    public List<Tree<Long>> getAllAreaTree() {
        List<TbArea> areas = tbAreaMapper.getAllAreaList();
        
        // 如果不存在全球跟节点，手动添加
        boolean existRoot = areas.stream().anyMatch(area -> area.getAreaId() == 0L);
        if (!existRoot) {
            // 添加根节点：手动添加id：0；parent_id：-1作为全球（根节点）
            TbArea root = new TbArea();
            root.setAreaId(0L);
            root.setAreaName("全球");
            root.setParentArea(-1L);
            areas.add(root);
        }
        
        //TreeNodeConfig config = new TreeNodeConfig();
        // 最大递归深度 config.setDeep(5); 不配置默认无限递归

        return TreeUtil.build(areas, -1L, (node, tree) -> {
            // tree.setId(node.getAreaId().toString());
            tree.setId(node.getAreaId());
            tree.setName(node.getAreaName());
            //tree.setParentId(node.getParentArea().toString());
            // tree.setParentId(node.getParentArea() == null ? "-1" : node.getParentArea().toString());
            tree.setParentId(node.getParentArea() == null ? -1L : node.getParentArea());

            // 或者前端使用normalizer自定义属性名，默认使用label
            tree.put("node", node);
            tree.put("label", node.getAreaName());
            tree.put("labelRU", node.getAreaNameRU());
            tree.put("labelES", node.getAreaNameES());
            tree.put("labelUS", node.getAreaNameUS());
            tree.put("localLabel", localAreaNameFun().apply(node));
        });
        
    }

    /**
     * 根据登录用户获取区域树
     * @return 结果
     */
    @Override
    public List<Tree<Long>> getAreaTreeByUser() {
        List<Long> areaIdList = SecurityUtils.getLoginUser().getAreaIdList();
        List<TbArea> areas = new ArrayList<>();
        if (areaIdList.contains(0L)) {
            areas = tbAreaMapper.getAllAreaList();
            areas.remove(0);
        } else {
            areas = tbAreaMapper.selectChildAreaByAreaIds(areaIdList);
            for (Long areaId : areaIdList) {
                areas.stream().filter(area -> area.getAreaId().equals(areaId)).findFirst().ifPresent(area -> area.setParentArea(0L));
            }
        }
        return TreeUtil.build(areas, 0L, (node, tree) -> {
            tree.setId(node.getAreaId());
            tree.setName(node.getAreaName());
            tree.setParentId(node.getParentArea() == null ? 0L : node.getParentArea());
            // 或者前端使用normalizer自定义属性名，默认使用label
            tree.put("node", node);
            tree.put("label", node.getAreaName());
            tree.put("labelRU", node.getAreaNameRU());
            tree.put("labelES", node.getAreaNameES());
            tree.put("labelUS", node.getAreaNameUS());
            tree.put("localLabel", localAreaNameFun().apply(node));
        });
    }

    @Override
    public List<TbArea> getAreaByUser() {
        List<Long> areaIdList = SecurityUtils.getLoginUser().getAreaIdList();
        List<TbArea> areas = new ArrayList<>();
        if (areaIdList.contains(0L)) {
            areas = tbAreaMapper.getAllAreaList();
            areas.remove(0);
        } else {
            areas = tbAreaMapper.selectChildAreaByAreaIds(areaIdList);
            for (Long areaId : areaIdList) {
                areas.stream().filter(area -> area.getAreaId().equals(areaId)).findFirst()
                    .ifPresent(area -> area.setParentArea(0L));
            }
        }
        return areas;
    }

    @Override
    public List<TbArea> getAreaListByCountryId(Long countryId) {
        return tbAreaMapper.getAreaListByCountryId(countryId);
    }

    @Override
    public List<TbArea> selectAreaListByIds(List<Long> areaIds) {
        return tbAreaMapper.selectAreaListByIds(areaIds);
    }

    /**
     * 查询指定区域的所有子区域
     * TODO 这里缓存的 key 会不会有点多，可以优化
     * 
     * @param areaIds 区域ID
     * @param justSubs 是否只查询子区域（不包括孙子即后代）
     * @param includeSelf 是否包含自己
     */
    @Override
    // @Cacheable(value = AREA_KEY, key = "#areaIds + '_' + #justSubs + '_' + #includeSelf", unless = "#result == null", cacheManager = "cacheManager")
    public List<TbArea> selectChildAreaList(List<Long> areaIds, boolean justSubs, boolean includeSelf) {

        AreaParam areaP = new AreaParam();
        areaP.setIds(areaIds);

        List<TbArea> tbAreas = tbAreaMapper.selectTbAreaList(areaP);
        if (CollectionUtils.isEmpty(tbAreas)) {
            throw new ServiceException(MessageUtils.message("area.name.invalid"));
        }
        List<TbArea> resultAreas;
        if (justSubs) {
            // 这里不用考虑上级区域是 null 的问题
            AreaParam areaParam = new AreaParam();
            areaParam.setParentArea(areaIds);
            resultAreas = tbAreaMapper.selectTbAreaList(areaParam);
            // 结果默认不包含自己
            if (includeSelf) {
                resultAreas.addAll(tbAreas);
            }
        } else {
            // // 反转字符串
            // String permission = new StringBuilder(tbArea.getPermissionChar()).reverse().toString();
            // //permission += justSubs ? "_," : "%";
            //
            // resultAreas = tbAreaMapper.selectChildAreaList(permission);
            resultAreas = tbAreaMapper.selectChildAreaByAreaIds(areaIds);
            // 结果默认包含自己
            if (!includeSelf) {
                // 根据id删除
                resultAreas.removeIf(area -> areaIds.contains(area.getAreaId()));
            }
        }
       
        return resultAreas;
    }

    @Override
    public List<Long> selectChildAreaIdsByAreaIds(List<Long> areaIds) {
        return tbAreaMapper.selectChildAreaIdsByAreaIds(areaIds);
    }

    @Override
    public List<Long> selectDeepOneAreaList(List<Long> areaIds) {
        return tbAreaMapper.selectDeepOneAreaList(areaIds);
    }

    @Override
    @Cacheable(value = AREA_KEY, key = "'allAreaMap'", cacheManager = "concurrentMapCacheManager")
    public Map<Long, TbArea> allAreaMap() {
        List<TbArea> areas = SpringUtils.getAopProxy(this).getAllAreaList();
        return CollectionUtils.isEmpty(areas) ? Collections.emptyMap() : areas.stream().collect(Collectors.toMap(TbArea::getAreaId, area -> area));
    }
}
