package com.tax.user.service.impl;


import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.tax.user.mapper.SysClientUserMapper;
import com.tax.user.model.*;
import com.tax.user.service.api.*;
import com.tax.user.service.rules.manager.RulesManager;
import com.tax.user.utils.RuleUtils;
import com.yxcheng.token.common.cache.RedisService;
import com.yxcheng.token.common.model.JsonResult;
import com.yxcheng.token.common.model.RuleModel;
import com.yxcheng.token.constants.RedisContants;
import com.yxcheng.token.utils.ObjectUtil;
import com.yxcheng.token.utils.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

@Transactional
@Component
public class SysClientUserServiceImpl implements SysClientUserService {

    private static final Logger logger = LoggerFactory.getLogger(SysClientUserServiceImpl.class);

    @Autowired
    private SysClientUserMapper sysClientUserMapper;

    @Autowired
    private SysRuleService sysRuleService;

    @Autowired
    private SysRuleIpService sysRuleIpService;

    @Autowired
    private SysServerFunctionService sysServerFunctionService;

    @Autowired
    private SysUserTaxnoService sysUserTaxnoService;

    @Autowired
    private RedisService redisService;

    @Override
    public boolean checkUserFunction(RuleModel ruleModel) {
        //检查参数是否为空
        if(!ObjectUtil.checkData(ruleModel.getUserName(),ruleModel.getFunctionCode())){
            return false;
        }
        //检测是否有此接口权限
        return RuleUtils.checkFunction(ruleModel.getUserName(),ruleModel.getFunctionCode());
    }

    @Override
    public boolean checkUserRule(RuleModel ruleModel, JsonResult<String> result) {
        List<SysRule> rules = RuleUtils.getRuleList(ruleModel.getUserName());
        return RulesManager.checkRule(rules,ruleModel,result);
    }

    @Override
    public Map<String, Integer> flushClientUserList(String userName) {
        Map<String, Integer> resultMap = Maps.newHashMap();
        //用户信息部分
        int userInfoFlag = flushUserInfo(userName);
        resultMap.put("userInfoFlag", userInfoFlag);
        if(StringUtil.isNotEmpty(userName)) {
            //功能部分
            int functionInfoFlag = flushFunctionInfo(userName);
            resultMap.put("functionInfoFlag", functionInfoFlag);
            //规则部分
            int ruleInfoFlag = flushRuleInfo(userName);
            resultMap.put("ruleInfoFlag", ruleInfoFlag);
            //规则IP加载
            int ruleIpInfoFlag = flushRuleIpInfo(userName);
            resultMap.put("ruleIpInfoFlag", ruleIpInfoFlag);
            //规则用户税号权限加载
            int userTaxnoInfoFlag = flushUserTaxnoInfo(userName);
            resultMap.put("userTaxnoInfoFlag", userTaxnoInfoFlag);
        }
        return resultMap;
    }

    public int flushUserInfo(String userName) {
        int flag = 0;
        try{
            List<SysClientUser> userList = sysClientUserMapper.queryClientUserList(userName);
            //清除旧的用户信息
            redisService.delByReg(RedisContants.CHECK_USER + StringUtil.transEmpty(userName));
            redisService.delByReg(RedisContants.CHECK_FULLINFO + StringUtil.transEmpty(userName));
            //加载新的用户信息
            for(SysClientUser clientUser:userList) {
                redisService.set(RedisContants.CHECK_USER + clientUser.getUserName(), clientUser.getPassword());
                redisService.set(RedisContants.CHECK_FULLINFO + clientUser.getUserName(), JSON.toJSONString(clientUser), "utf-8");
            }
            flag = 1;
            logger.info("1.flush userInfo is over." + userList.size());
        } catch (Exception e) {
            logger.error("1.flush userInfo is error." + e.getMessage());
        }
        return flag;
    }

    public int flushFunctionInfo(String userName) {
        int flag = 0;
        try{
            redisService.delByReg(RedisContants.CHECK_FUNCTION + StringUtil.transEmpty(userName));
            List<SysServerFunction> functionList = sysServerFunctionService.queryFunctionList(userName);
            for(SysServerFunction function:functionList) {
                redisService.set(RedisContants.CHECK_FUNCTION + function.getUserName() + RedisContants.DELIMITER + function.getFunctionCode(), function.getFunctionName());
            }
            flag = 1;
            logger.info("2.flush functionInfo is over." + functionList.size());
        } catch (Exception e) {
            logger.error("2.flush functionInfo is error." + e.getMessage());
        }
        return flag;
    }

    public int flushRuleInfo(String userName) {
        int flag = 0;
        try{
            redisService.delByReg(RedisContants.CHECK_RULE + StringUtil.transEmpty(userName));
            List<SysRule> ruleList = sysRuleService.queryRuleList(userName);
            Map<String, List<SysRule>> ruleMap = Maps.newHashMap();
            List<SysRule> userRuleList = null;
            //按用户分组
            for(SysRule rule:ruleList) {
                if(null == ruleMap.get(rule.getUserName())) {
                    userRuleList = Lists.newArrayList();
                } else {
                    userRuleList = ruleMap.get(rule.getUserName());
                }
                userRuleList.add(rule);
                ruleMap.put(rule.getUserName(), userRuleList);
            }
            for(String ruleUser:ruleMap.keySet()) {
                redisService.set(RedisContants.CHECK_RULE + ruleUser, JSON.toJSONString(ruleMap.get(ruleUser)), "utf-8");
            }
            flag = 1;
            logger.info("3.flush ruleInfo is over." + ruleMap.size());
        } catch (Exception e) {
            logger.error("3.flush ruleInfo is error." + e.getMessage());
        }
        return flag;
    }

    public int flushRuleIpInfo(String userName) {
        int flag = 0;
        try{
            redisService.delByReg(RedisContants.CHECK_RULE_IP + StringUtil.transEmpty(userName));
            List<SysRuleIp> ruleList = sysRuleIpService.queryRuleIpList(userName);
            Map<String, List<String>> ruleMap = Maps.newHashMap();
            List<String> userRuleList = null;
            //按用户分组
            for(SysRuleIp rule:ruleList) {
                if(null == ruleMap.get(rule.getUserName())) {
                    userRuleList = Lists.newArrayList();
                } else {
                    userRuleList = ruleMap.get(rule.getUserName());
                }
                userRuleList.add(rule.getIpAddr());
                ruleMap.put(rule.getUserName(), userRuleList);
            }
            for(String ruleUser:ruleMap.keySet()) {
                redisService.set(RedisContants.CHECK_RULE_IP + ruleUser, JSON.toJSONString(ruleMap.get(ruleUser)), "utf-8");
            }
            flag = 1;
            logger.info("4.flush ruleIpInfo is over." + ruleMap.size());
        } catch (Exception e) {
            logger.error("4.flush ruleIpInfo is error." + e.getMessage());
        }
        return flag;
    }

    public int flushUserTaxnoInfo(String userName) {
        int flag = 0;
        try{
            redisService.delByReg(RedisContants.CHECK_USER_TAXNO + StringUtil.transEmpty(userName));
            List<SysUserTaxno> userTaxnoList = sysUserTaxnoService.queryUserTaxnoList(userName);
            for(SysUserTaxno userTaxno:userTaxnoList) {
                redisService.set(RedisContants.getCheckTaxnosByUser(userTaxno.getUserName(), userTaxno.getFunctionType(), userTaxno.getTaxno())
                        , JSON.toJSONString(userTaxno), "utf-8");
            }

            flag = 1;
            logger.info("5.flush userTaxnoInfo is over." + userTaxnoList.size());
        } catch (Exception e) {
            logger.error("5.flush userTaxnoInfo is error." + e.getMessage());
        }
        return flag;
    }

    public List<SysClientUser> queryUserList() {
        List<SysClientUser> userList = sysClientUserMapper.queryClientUserList(null);
        return userList;
    }
}
