package org.dromara.settlement.dubbo;


import org.apache.dubbo.config.annotation.DubboService;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.settlement.api.RemoteConfigService;
import org.dromara.settlement.api.constant.SystemConfig;
import org.dromara.settlement.api.domain.*;
import org.dromara.settlement.common.PropertyUtils;
import org.dromara.settlement.common.QiniuUtils;
import org.dromara.settlement.domain.SelectData;
import org.dromara.settlement.domain.SysUnitConfig;
import org.dromara.settlement.mapper.SysUnitConfigMapper;
import org.redisson.api.RLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@DubboService
public class RemoteConfigServiceImpl implements RemoteConfigService {
	private static final Logger log = LoggerFactory.getLogger(RemoteConfigServiceImpl.class);
    /**
     * 空值
     */
    public final String EMPTY = "-empty-";

	@Autowired
	private SysUnitConfigMapper unitConfigDao;//单位配置

	@Override
	public Boolean valiServiceAccess(long unitId, String key) {
		// TODO 自动生成的方法存根
		try {
			Map<String, String> items = getItemsMap(unitId, key);
			if(items.containsKey(key) && StringUtils.isNotBlank(items.get(key)))
				return true;
		} catch (Exception e) {
			// TODO 自动生成的 catch 块
			String msg = "验证服务是否能访问出错：（"+ unitId + "," + key +"）";
			log.error(msg,e);
		}
		return false;
	}

	@Override
	public String getItem(long unitId, String key) {
		// TODO 自动生成的方法存根
		try {
			Map<String, String> items = getItemsMap(unitId, key);
			return items.get(key);
		} catch (Exception e) {
            e.printStackTrace();
			// TODO 自动生成的 catch 块
			String msg = "获取配置项出错：（"+ unitId + "," + key +"）";
			log.error(msg,e);
		}
		return null;
	}

	@Override
	public Map<String, String> getItems(long unitId, String... keys) {
		// TODO 自动生成的方法存根
		try {
			return getItemsMap(unitId, keys);
		} catch (Exception e) {
			// TODO 自动生成的 catch 块
			String msg = "获取配置项出错：（"+ unitId + "," + keys +"）";
			log.error(msg,e);
		}
		return null;
	}

	private String getUnitConfigKey(long unitId){
		return "config:"+unitId;
	}

	private String getItemValue(String redisKey,String key,Object itemObj){
		String itemValue = null;
		if (itemObj == null) {
			itemValue = EMPTY;
            RedisUtils.setCacheMapValue(redisKey, key, itemValue);
		}else {
			itemValue = itemObj.toString();
		}
		if(itemValue.equals(EMPTY)){
			itemValue = null;
		}
		return itemValue;
	}

	private Map<String, String> getItemsMap(long unitId, String... keys) throws InterruptedException {
		// TODO 自动生成的方法存根
		Map<String, String> configMap = new HashMap<String, String>();
		if(keys.length > 0){
			String redisKey = getUnitConfigKey(unitId);
			boolean read = false;//需要读取数据库
			if(keys.length == 1){
				if(RedisUtils.hasKey(redisKey)){
					Object itemObj = RedisUtils.getCacheMapValue(redisKey, keys[0]);
					String itemValue = getItemValue(redisKey, keys[0], itemObj);
					configMap.put(keys[0], itemValue);
					return configMap;
				}else{
					read = true;
				}
			}else {
				Map<String, Object> map = RedisUtils.getCacheMap(redisKey);
				if (map != null && map.size() > 0) {
					for (String key : keys) {
						Object itemObj = map.get(key);
						String itemValue = getItemValue(redisKey, key, itemObj);
						configMap.put(key, itemValue);
					}
				} else {
					read = true;
				}
			}
			if (read) {
				int lockTime = 10 * 1000;//毫秒
                RLock lock = RedisUtils.getClient().getLock(redisKey);
				boolean lockResult = lock.tryLock(lockTime,TimeUnit.MILLISECONDS);
				if(lockResult){
					try {
						Map<String,Object> unitConfig = new HashMap<String, Object>();
						int common = 0;//公共配置
						List<SysUnitConfig> configList = unitConfigDao.selectByUnit(unitId+","+common, null);
						//默认的配置
						for (SysUnitConfig con : configList) {
							if(con.getConfUnit() == common){
								unitConfig.put(con.getConfItem(), con.getConfValue() == null ?"":con.getConfValue());
								if(con.getIsEnable() != null && con.getIsEnable() == 1 && StringUtils.isNotEmpty(con.getClassAlias()))//key:配置分类别名 value:配置组
									unitConfig.put(con.getClassAlias(), con.getConfGroup());
							}
						}
						//单位配置
						for (SysUnitConfig con : configList) {
							if(con.getConfUnit() == unitId){
								unitConfig.put(con.getConfItem(), con.getConfValue() == null ?"":con.getConfValue());
								if(con.getIsEnable() != null && con.getIsEnable() == 1 && StringUtils.isNotEmpty(con.getClassAlias()))//key:配置分类别名 value:配置组
									unitConfig.put(con.getClassAlias(), con.getConfGroup());
							}
						}
						//防止穿透
						for (String key : keys) {
							configMap.put(key, unitConfig.containsKey(key) ? unitConfig.get(key)+"" : null);
							if (!unitConfig.containsKey(key)) {
								unitConfig.put(key, EMPTY);
							}
						}

						RedisUtils.setCacheMap(redisKey, unitConfig);
                        RedisUtils.expire(redisKey, 60 * 60 * 24 * 6);//6天
					} catch (Exception e) {
						// TODO 自动生成的 catch 块
						log.error("读取数据库配置出错：（"+unitId+"）",e);
					}finally{
                        if(lock.isLocked() && lock.isHeldByCurrentThread()){
                            lock.unlock();
                        }
					}
				}else {
					// 设置失败次数计数器, 当到达5次时, 返回失败
		            int failCount = 1;
		            int sleepTime = 100;//毫秒
		            int maxFailCount = lockTime / sleepTime;
		            while(failCount <= maxFailCount){
		                // 等待100ms重试
		                try {
		                    TimeUnit.MILLISECONDS.sleep(sleepTime);
		                } catch (InterruptedException e) {
		                    log.error("等待缓存读取出错：（"+unitId+","+keys+"）",e);
		                }
		                configMap = getItemsMap(unitId, keys);
		                if (configMap.size() > 0){
		                   // 执行逻辑操作
		                	break;
		                }else{
		                    failCount ++;
		                }
		            }
				}
			}
		}
		return configMap;
	}

	@Override
	public String getUploadNetPath(long unitId) {
		// TODO 自动生成的方法存根
		String key = "download_root_path";
		//String path = propertyUtils.getPropertiesString(key);
        String path = "";
        if (StringUtils.isBlank(path)) {
			path = getItem(unitId, key);
		}
		if (StringUtils.isBlank(path)) {
			log.warn("文件访问路径配置错误（"+unitId+","+key+"）：缺少配置");
			return "";
		}
		if (!path.substring(path.length()-1).equals("/")) {
			log.warn("文件访问路径配置错误（"+unitId+","+key+"）：应以/结尾");
			return "";
		}
		path = path + unitId + "/";
		return path;
	}

	@Override
	public SystemConfig.StoreType getStoreType(long unitId) {
		// TODO 自动生成的方法存根
		String storeType = getItem(unitId, "store.type");
		return SystemConfig.StoreType.valueOfs(storeType);
	}

	@Override
	public String getUploadPhyPath(long unitId) {
		// TODO 自动生成的方法存根
		String key = "upload_root_pathpage";
		//String path = propertyUtils.getPropertiesString(key);
        String path = "";
        if (StringUtils.isBlank(path)) {
			path = getItem(unitId, key);
		}
		if (StringUtils.isBlank(path)) {
			log.warn("文件访问路径配置错误（"+unitId+","+key+"）：缺少配置");
			return "";
		}
		if (!path.substring(path.length()-1).equals("/")) {
			log.warn("文件访问路径配置错误（"+unitId+","+key+"）：应以/结尾");
			return "";
		}
		path = path + unitId;
		return path;
	}

	@Override
	public String getQiNiuDomain(long unitId) {
		// TODO 自动生成的方法存根
		return getItem(unitId, "QiNiu_DOMAIN");
	}

	@Override
	public String getQiNiuUptoken(long unitId) {
		// TODO 自动生成的方法存根
		try {
			String bucketKey = "QiNiu_BUCKET";
			String accesskeyKey = "QiNiu_AccessKey";
			String secretkeyKey = "QiNiu_SecretKey";
			Map<String, String> configs = getItemsMap(unitId, bucketKey,accesskeyKey,secretkeyKey);
			return QiniuUtils.getUptoken(configs.get(accesskeyKey), configs.get(secretkeyKey), configs.get(bucketKey), null, null);
		} catch (Exception e) {
			String msg = "获取七牛上传凭证出错：（"+ unitId +"）";
			log.error(msg,e);
		}
		return "";
	}

	@Override
	public Result<List<UnitConfClass>> getConfClass(Long unit_id, String unitType) {
		Result<List<UnitConfClass>> result  = new Result<List<UnitConfClass>>();
		try {
		List<UnitConfClass> confClass = unitConfigDao.getConfClass(unit_id,unitType);
		result.setRtnData(confClass);
		}catch(Exception ex) {
			String msgStr = "查询企业大类异常";
			log.error(msgStr,ex);
			result.addError(msgStr);
		}
		return result;
	}

	@Override
	public Result<List<UnitConfGroup>> getConfGroupByUnit(Long unit_id, String class_alias) {
		Result<List<UnitConfGroup>> result  = new Result<List<UnitConfGroup>>();
		try {
		//查询默认的大类下的组分类
		List<UnitConfGroup> defGroups = unitConfigDao.getConfGroupByUnit(0L,class_alias);
		if(!CollectionUtils.isEmpty(defGroups)) {
			List<UnitConfGroup> schoolGroups = unitConfigDao.getConfGroupByUnit(unit_id,class_alias);
			if(!CollectionUtils.isEmpty(schoolGroups)) {//如果学校下面这个大类配置了,把默认选中的置为不选中
				for(UnitConfGroup def : defGroups) {
					def.setIs_enable(0);
					for(UnitConfGroup school:schoolGroups) {
						if(def.getConf_group().equals(school.getConf_group())) {
							def.setIs_enable(school.getIs_enable());
						}
					}
				}
			}else{
                int i = 0;
                for(UnitConfGroup def : defGroups) {
                    if(i == 0){
                        def.setIs_enable(1);
                    }else{
                        def.setIs_enable(0);
                    }
                    i++;
                }
            }
		}
		result.setRtnData(defGroups);
		}catch(Exception ex) {
			String msgStr = "查询企业大类异常";
			log.error(msgStr,ex);
			result.addError(msgStr);
		}
		return result;
	}

	@Override
	public Result<List<UnitConfDetail>> getConfDetailByUnit(Long unit_id, String conf_group) {
		Result<List<UnitConfDetail>> result  = new Result<List<UnitConfDetail>>();
		try {
			List<UnitConfDetail> unitDetails = unitConfigDao.getConfDetailByUnit(unit_id,conf_group);
			List<String> exists = new ArrayList<String>();
			for (UnitConfDetail d : unitDetails) {
				exists.add(d.getConf_item());
			}
			List<UnitConfDetail> defaultDetails =unitConfigDao.getConfDetailByUnit(0L,conf_group);
			for(UnitConfDetail de :defaultDetails) {
				de.setConf_value("");
				if (!exists.contains(de.getConf_item())) {
					unitDetails.add(de);
				}
			}
			result.setRtnData(unitDetails);
		}catch(Exception ex) {
			String msgStr = "查询企业大类异常";
			log.error(msgStr,ex);
			result.addError(msgStr);
		}
		return result;
	}

	@Override
	@Transactional
	public Result<Boolean> editConfDetail(List<UnitConfDetail> lendReco) {
		Result<Boolean> result = new Result<Boolean>();
		try {
			//缓存配置
			Map<String,Object> unitConfig = new HashMap<String, Object>();
			for(UnitConfDetail detail : lendReco) {
				detail.setIs_enable(1);
				detail.setConf_is_editor(1);
				detail.setConf_unit_type(1);
				if(detail.getConf_unit()==null||detail.getConf_unit().intValue()==0) {
					 result.addError("企业配置信息内容项不完整");
					 return  result;
				}
				unitConfig.put(detail.getConf_item(), detail.getConf_value());
				if(detail.getIs_enable() != null && detail.getIs_enable() == 1 && StringUtils.isNotEmpty(detail.getClass_alias()))//key:配置分类别名 value:配置组
					unitConfig.put(detail.getClass_alias(), detail.getConf_group());
			}
			//该企业下这个大类置为不可用
			unitConfigDao.updateIsEnableByUnit(lendReco.get(0).getConf_unit(),lendReco.get(0).getClass_alias());
			//删除企业下这个组的配置信息
			unitConfigDao.delConfIsEnableByUnit(lendReco.get(0).getConf_unit(),lendReco.get(0).getConf_group());
			//保存企业配置
			unitConfigDao.addConf(lendReco);
			//如果缓存已加载，则更新缓存
			String redisKey = getUnitConfigKey(lendReco.get(0).getConf_unit());
			if (RedisUtils.hasKey(redisKey) && unitConfig.size() > 0) {
                RedisUtils.setCacheMap(redisKey, unitConfig);//6天
                RedisUtils.expire(redisKey, 60 * 60 * 24 * 6);//6天
			}
			result.setRtnData(true);
		}catch(Exception ex) {
			String msgStr = "查询企业大类异常";
			log.error(msgStr,ex);
			result.addError(msgStr);
		}
		return result;
	}

	@Override
	public Result<QiNiuConfig> getQiniuConfg(Long unit_id) {
		Result<QiNiuConfig> result  = new Result<QiNiuConfig>();
		try {
			String bucketKey = "QiNiu_BUCKET";
			String accesskeyKey = "QiNiu_AccessKey";
			String secretkeyKey = "QiNiu_SecretKey";
			String secretregion = "QiNiu_Region";
			String secretdomain = "QiNiu_DOMAIN";
			Map<String, String> configs = getItemsMap(unit_id, bucketKey,accesskeyKey,secretkeyKey,secretregion,secretdomain);
		    String token = QiniuUtils.getUptoken(configs.get(accesskeyKey), configs.get(secretkeyKey), configs.get(bucketKey), null, null);
		    QiNiuConfig con = new QiNiuConfig();
		    con.setQiNiu_BUCKET(configs.get(bucketKey));
		    con.setQiNiu_AccessKey(configs.get(accesskeyKey));
		    con.setQiNiu_SecretKey(configs.get(secretkeyKey));
		    con.setQiNiu_Region(configs.get(secretregion));
		    con.setQiNiu_DOMAIN(configs.get(secretdomain));
		    con.setToken(token);
		    result.setRtnData(con);
		} catch (Exception e) {
			String msg = "获取七牛上传配置出错：（"+ unit_id +"）";
			log.error(msg,e);
			result.setRtnCode(ResultCodeEnum.ERROR);
		}
		return result;
	}

	@Override
	@Transactional
	public Result<Boolean> saveConfigById(Long unitId, String key,String value) {
		Result<Boolean> result = new Result<Boolean>();
		try {
			//删除原来老的配置
			unitConfigDao.delConfig(unitId,key);
			unitConfigDao.saveConfig(unitId,key,value);
			String redisKey = getUnitConfigKey(unitId);
			Map<String,Object> unitConfig = new HashMap<String, Object>();
			unitConfig.put(key, value);
            if (RedisUtils.hasKey(redisKey) && unitConfig.size() > 0) {
                RedisUtils.setCacheMap(redisKey, unitConfig);
                RedisUtils.expire(redisKey, 60 * 60 * 24 * 6);//6天
            }
			result.setRtnData(true);
		}catch (Exception e) {
			String msg = "配置信息失败";
			log.error(msg,e);
			result.setRtnCode(ResultCodeEnum.ERROR);
		}
		return result;
	}





}
