package com.jiayue.ipfcst.console.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.jiayue.ipfcst.common.core.exception.BusinessException;
import com.jiayue.ipfcst.common.data.constant.enums.AlarmTypeEnum;
import com.jiayue.ipfcst.common.data.entity.SysParameter;
import com.jiayue.ipfcst.common.data.repository.SysParameterRepository;
import com.jiayue.ipfcst.common.data.service.BaseService;
import lombok.extern.slf4j.Slf4j;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import net.sf.ehcache.search.Attribute;
import net.sf.ehcache.search.Query;
import net.sf.ehcache.search.Result;
import net.sf.ehcache.search.Results;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 系统参数业务层
 *
 * @author zzy
 * @version 1.0
 * @since 2019/8/6 16:35
 */
@Service
@Slf4j
public class SysParameterService extends BaseService {

    private final SysParameterRepository sysParameterRepository;

    private final EhCacheCacheManager ehCacheCacheManager;

    @Autowired
    public SysParameterService(SysParameterRepository sysParameterRepository, EhCacheCacheManager ehCacheCacheManager) {
        this.sysParameterRepository = sysParameterRepository;
        this.ehCacheCacheManager = ehCacheCacheManager;
    }

    /**
     * 新增系统参数
     *
     * @param sysParameter 系统参数实体
     * @throws BusinessException 业务异常
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    public void add(SysParameter sysParameter) throws BusinessException {

        boolean b = this.sysParameterRepository.existsBySysKey(sysParameter.getSysKey());
        if (b) {// 参数已存在
            throw new BusinessException("系统参数已存在!");
        } else {
            clearParameterCache();
            this.sysParameterRepository.save(sysParameter);
        }
    }

    /**
     * 修改系统参数
     *
     * @param sysParameter 系统参数实体
     * @throws BusinessException 业务异常
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    public void update(SysParameter sysParameter) throws BusinessException {
        if (StrUtil.isEmpty(sysParameter.getSysKey())) {
            throw new BusinessException("系统参数标识不能为空!");
        } else {
            clearParameterCache();
            this.sysParameterRepository.save(sysParameter);
        }
    }

    /**
     * 删除系统参数
     *
     * @param id 主键编号
     * @throws BusinessException 业务异常
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTS)
    public void delete(final Integer id) throws BusinessException {
        clearParameterCache();
        this.sysParameterRepository.deleteById(id);

    }


    /**
     * 查询参数
     *
     * @param sysParameter 查询条件
     * @param page         页码
     * @param size         每页记录数
     * @return 分页结果
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public Page<SysParameter> get(final SysParameter sysParameter, final Integer page, final Integer size) {
        ExampleMatcher matcher = ExampleMatcher.matching()
                .withMatcher("sysKey", ExampleMatcher.GenericPropertyMatchers.contains())
                .withMatcher("sysValue", ExampleMatcher.GenericPropertyMatchers.contains())
                .withMatcher("describe", ExampleMatcher.GenericPropertyMatchers.contains());
        Example<SysParameter> example = Example.of(sysParameter, matcher);
        Pageable pageable = PageRequest.of(page - 1, size);
        return this.sysParameterRepository.findAll(example, pageable);
    }

    /**
     * 查询参数值
     *
     * @param id 主键编号
     * @return 参数
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public String getParameter(final Integer id) {
        Optional<SysParameter> sysParameterOptional = this.sysParameterRepository.findById(id);
        return sysParameterOptional.map(SysParameter::getSysValue).orElse(null);
    }

    /**
     * 移除缓存中的参数信息
     */
    public void clearParameterCache() {
        List<SysParameter> sysParameterList = this.getAll();
        Cache cache = ehCacheCacheManager.getCacheManager().getCache("searchablecache");
        for (SysParameter sysParameter : sysParameterList) {
            cache.remove("par" + sysParameter.getId());
        }
    }

    /**
     * 查询所有参数信息
     *
     * @return 通道信息
     */
    public List<SysParameter> getAll() {
        Cache cache = ehCacheCacheManager.getCacheManager().getCache("searchablecache");
        Query query = cache.createQuery();
        //查询结果中包含Key和value
        query.includeKeys().includeValues();
        Attribute<String> keyName = cache.getSearchAttribute("key");
        query.addCriteria(keyName.ilike("*par*"));
        Results results = query.execute();
        List<Result> resultList = results.all();

        List<SysParameter> list = new ArrayList();
        if (resultList != null && !resultList.isEmpty()) {
            for (Result result : resultList) {
                SysParameter e = (SysParameter) result.getValue();
                list.add(e);
            }
            results.discard();
        } else {
            //查询数据库
            list = sysParameterRepository.findAll();
            for (SysParameter sysParameter : list) {
                //将结果存入缓存
                cache.put(new Element("par" + sysParameter.getId(), sysParameter));
            }
        }
        return list;
    }
/*
    *//**
     * 根据key获取值
     *
     * @return 通道信息
     *//*
    public String getParameterValue(String key, String defaultValue) {
        List<SysParameter> sysParameterList = this.getAll();
        List<SysParameter> filterList = sysParameterList.stream().filter(a -> a.getSysKey().equals(key)).collect(Collectors.toList());
        String retValue = "";
        if (CollUtil.isEmpty(filterList)) {
            retValue = defaultValue;
        } else {
            retValue = filterList.get(0).getSysValue();
        }
        return retValue;
    }*/

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void saveCloud(SysParameter bean) {
        Optional<SysParameter> optional = sysParameterRepository.findBySysKey(bean.getSysKey());
        if (optional.isPresent()) {
            bean.setId(optional.get().getId());
        }
        sysParameterRepository.save(bean);
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void saveCloud(List<SysParameter> beans) {
        if(beans != null && beans.size() > 0){
            sysParameterRepository.deleteAll();
            sysParameterRepository.saveAll(beans);
        }
    }

    /**
     * 根据描述查询告警信息
     *
     * @return 告警信息
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public Page<SysParameter> getForKeywords(SysParameter sysParameter, Integer page, Integer size, String keywords) {
        sysParameter.setDescribe(keywords);
        ExampleMatcher matcher = ExampleMatcher.matching().withMatcher("modelNumber", ExampleMatcher.GenericPropertyMatchers.contains())
                .withMatcher("describe", ExampleMatcher.GenericPropertyMatchers.contains());
        Example<SysParameter> example = Example.of(sysParameter, matcher);
        Pageable pageable = PageRequest.of(page - 1, size);
        return this.sysParameterRepository.findAll(example, pageable);
    }


  /**
   * 查询参数值
   *
   * @param sysKey 参数标识
   * @return 参数
   */
  @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
  public SysParameter getParameterBySysKey(final String sysKey) {
    SysParameter sysParameter = this.sysParameterRepository.findBySysKeyEquals(sysKey);
    return sysParameter;
  }


  /**
   * 获取文件上报数值类型参数
   *
   * @param key
   * @param defaultValue
   * @return
   */
  public int getTranSysParameter(String key, String defaultValue) {
    int returnValue = 0;
    try {
      String value = super.getSysParameter(key, defaultValue);
      returnValue = Integer.parseInt(value);
    } catch (RuntimeException e) {
      String errorInfo = "参数表" + key + "获取失败";
      log.error(errorInfo, e);
      String name = "参数表" + key + "获取失败";
      String describe = "参数表" + key + "获取失败";
      String solution = "使用默认值" + defaultValue;
      super.saveSysAlarm(AlarmTypeEnum.E1, name, describe, errorInfo, solution);
      returnValue = Integer.parseInt(defaultValue);
    }
    return returnValue;
  }

}
