package com.jy.system.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jy.framework.redis.RedisCache;
import com.jy.framework.redis.RedisKey;
import com.jy.framework.utils.AssertUtil;
import com.jy.framework.utils.LockUtil;
import com.jy.system.dao.SysDictDataDao;
import com.jy.system.dao.SysDictTypeDao;
import com.jy.system.model.dto.SysDictDataDto;
import com.jy.system.model.dto.SysDictDataSelectDto;
import com.jy.system.model.entity.SysDictType;
import com.jy.system.model.vo.SysDictDataCacheVo;
import com.jy.system.model.vo.SysDictDataVo;
import com.jy.system.service.SysDictDataService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 字典数据 服务实现类
 * </p>
 *
 * @author
 * @since 2024-06-20
 */
@Service
public class SysDictDataServiceImpl implements SysDictDataService {

    @Resource
    private SysDictDataDao sysDictDataDao;

    @Resource
    private SysDictTypeDao sysDictTypeDao;

    @Override
    public Page<SysDictDataVo> getPage(SysDictDataSelectDto dto) {
        return sysDictDataDao.getPage(dto);
    }

    @Override
    public SysDictDataVo getDetail(Long id) {
        SysDictDataVo vo = sysDictDataDao.getDetail(id);
        AssertUtil.notNull(vo, "未知数据");
        return vo;
    }

    @Override
    public void add(SysDictDataDto dto) {
        // 验证数据字典是否存在
        SysDictType sysDictType = sysDictTypeDao.getById(dto.getDictTypeId());
        AssertUtil.notNull(sysDictType, "未知字典");

        // 验证字典标签是否存在
        boolean labelExists = sysDictDataDao.labelExists(dto.getDictTypeId(), dto.getLabel());
        AssertUtil.eqFalse(labelExists, "字典标签已存在");

        // 验证字典值是否存在
        boolean valueExists = sysDictDataDao.valueExists(dto.getDictTypeId(), dto.getValue());
        AssertUtil.eqFalse(valueExists, "字典值已存在");

        // 删除字典缓存
        RedisCache.delete(RedisKey.getDict(sysDictType.getCode()));

        // 保存字典数据
        sysDictDataDao.save(dto);
    }

    @Override
    public void edit(SysDictDataDto dto) {
        // 验证数据字典类型是否存在
        SysDictType sysDictType = sysDictTypeDao.getById(dto.getDictTypeId());
        AssertUtil.notNull(sysDictType, "未知字典");

        // 验证字典标签是否存在
        boolean labelExists = sysDictDataDao.labelExists(dto.getDictTypeId(), dto.getLabel(), dto.getId());
        AssertUtil.eqFalse(labelExists, "字典标签已存在");

        // 验证字典值是否存在
        boolean valueExists = sysDictDataDao.valueExists(dto.getDictTypeId(), dto.getValue(), dto.getId());
        AssertUtil.eqFalse(valueExists, "字典值已存在");

        // 删除字典缓存
        RedisCache.delete(RedisKey.getDict(sysDictType.getCode()));

        // 更新字典数据
        sysDictDataDao.updateById(dto);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<Long> idList) {
        // 根据字典数据id列表获取字典列表
        Set<Long> dictTypeIdSet = sysDictDataDao.getDictTypeIdSetByIdList(idList);
        List<SysDictType> sysDictTypeList = sysDictTypeDao.listByIds(dictTypeIdSet);

        // 删除字典缓存
        sysDictTypeList.forEach(item -> RedisCache.delete(RedisKey.getConfig(item.getCode())));

        // 删除字典数据信息
        sysDictDataDao.removeByIds(idList);
    }

    @Override
    public List<SysDictDataCacheVo> getListByCode(String code) {
        return LockUtil.cacheLock(RedisKey.getDict(code), () -> sysDictDataDao.getDictDataCacheVoListByCode(code));
    }

    @Override
    public Map<Integer, String> getMapByCode(String code) {
        return getListByCode(code).stream().collect(Collectors.toMap(SysDictDataCacheVo::getValue, SysDictDataCacheVo::getLabel));
    }

}
