package com.chenyang.nse.bussiness.kms.service.impl;

import com.chenyang.nse.bussiness.dao.core.key.TCoreKeyTypeManagementDao;
import com.chenyang.nse.bussiness.dao.table.core.scheduler.TCoreSchedulerKmLogDao;
import com.chenyang.nse.bussiness.dao.table.core.scheduler.TCoreSchedulerKmRulesDao;
import com.chenyang.nse.bussiness.entity.orm.table.core.key.TCoreKeyTypeManagement;
import com.chenyang.nse.bussiness.entity.orm.table.core.scheduler.TCoreSchedulerKmLog;
import com.chenyang.nse.bussiness.entity.orm.table.core.scheduler.TCoreSchedulerKmRules;
import com.chenyang.nse.bussiness.kms.model.Kms;
import com.chenyang.nse.bussiness.kms.model.KmsSecretKey;
import com.chenyang.nse.bussiness.kms.model.KmsSecretKeys;
import com.chenyang.nse.bussiness.kms.service.KmsService;
import com.chenyang.nse.bussiness.local.service.TestService;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

@Service("KmsTestServiceImpl")
public class KmsTestServiceImpl implements TestService {
   private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
   @Autowired
   private TCoreSchedulerKmRulesDao tCoreSchedulerKmRulesDao;
   @Autowired
   private TCoreSchedulerKmLogDao tCoreSchedulerKmLogDao;
   private static final Logger LOGGER = LoggerFactory.getLogger(KmsTestServiceImpl.class);
   @Autowired
   private KmsService kmsService;
   @Autowired
   protected JdbcTemplate jdbcTemplate;
   @Autowired
   private TCoreKeyTypeManagementDao tCoreKeyTypeManagementDao;
   @Value("${encryption.secret-key-mode:Local}")
   private String secretKeyMode;

   public void test() {
      try {
         TestResult result = this.testKms();
         this.saveTestResult(result);
      } catch (Exception e) {
         LOGGER.error(e.getMessage(), e);
      }

   }

   public void initSecretKey() {
      TCoreKeyTypeManagement tCoreKeyTypeManagement = (TCoreKeyTypeManagement)this.tCoreKeyTypeManagementDao.queryUnique(new Criterion[]{Restrictions.eq("typeid", "5"), Restrictions.eq("isuse", "1")});
      if (!Objects.isNull(tCoreKeyTypeManagement)) {
         try {
            List<KmsSecretKey> secretKeyList = this.jdbcTemplate.query("SELECT k.id,k.encryption_id,e.encryption_type,k.secret_key_name,k.sectet_key_value FROM t_core_secretkey k ,t_core_encryption e WHERE k.encryption_id = e.id", (rs, rowNum) -> {
               String id = rs.getString("id");
               String encryption_id = rs.getString("encryption_id");
               String encryption_type = rs.getString("encryption_type");
               String secret_key_name = rs.getString("secret_key_name");
               String sectet_key_value = rs.getString("sectet_key_value");
               KmsSecretKey secretKey = new KmsSecretKey(id, encryption_id, encryption_type, secret_key_name, sectet_key_value);
               return secretKey;
            });
            List<KmsSecretKey> kmsSecretKeyList = new ArrayList();
            String challengeCode = this.kmsService.obtainChallengeCode();
            String accessToken = this.kmsService.obtainAccessToken(challengeCode);

            for(KmsSecretKey secretKey : secretKeyList) {
               String sectet_key_plain_text = this.kmsService.obtainSecretKey(Kms.MasterKey.getInstance().getKeyid(), accessToken, secretKey.getSectet_key_value());
               KmsSecretKey kmsSecretKey = new KmsSecretKey(secretKey.getTid(), secretKey.getEncryption_id(), secretKey.getEncryption_type(), secretKey.getSecret_key_name(), secretKey.getSectet_key_value(), sectet_key_plain_text);
               kmsSecretKeyList.add(kmsSecretKey);
            }

            KmsSecretKeys.init(kmsSecretKeyList);
         } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
         }

      }
   }

   private void saveTestResult(TestResult result) {
      TCoreSchedulerKmLog tCoreSchedulerKmLog = new TCoreSchedulerKmLog();
      tCoreSchedulerKmLog.setId(UUID.randomUUID().toString().replace("-", ""));
      tCoreSchedulerKmLog.setCreatetime(new Date());
      tCoreSchedulerKmLog.setTestTime(new Date());
      List<TCoreSchedulerKmRules> tCoreSchedulerKmRulesList = this.tCoreSchedulerKmRulesDao.queryAll();
      if (null != tCoreSchedulerKmRulesList && tCoreSchedulerKmRulesList.size() > 0) {
         tCoreSchedulerKmLog.setRulestype(((TCoreSchedulerKmRules)tCoreSchedulerKmRulesList.get(0)).getRulestype());
         if (((TCoreSchedulerKmRules)tCoreSchedulerKmRulesList.get(0)).getHowtime().equals("")) {
            tCoreSchedulerKmLog.setPollingRule("每天");
         } else {
            String[] arr1 = ((TCoreSchedulerKmRules)tCoreSchedulerKmRulesList.get(0)).getHowtime().split(",");
            StringBuilder logBuilder = new StringBuilder();

            for(int i = 0; i < arr1.length; ++i) {
               if ("1".equals(arr1[i])) {
                  logBuilder.append("周一");
               }

               if ("2".equals(arr1[i])) {
                  logBuilder.append("周二");
               }

               if ("3".equals(arr1[i])) {
                  logBuilder.append("周三");
               }

               if ("4".equals(arr1[i])) {
                  logBuilder.append("周四");
               }

               if ("5".equals(arr1[i])) {
                  logBuilder.append("周五");
               }

               if ("6".equals(arr1[i])) {
                  logBuilder.append("周六");
               }

               if ("7".equals(arr1[i])) {
                  logBuilder.append("周日");
               }
            }

            String pollingRule = "";
            if (null != logBuilder && !"".equals(logBuilder)) {
               pollingRule = logBuilder.toString();
               tCoreSchedulerKmLog.setPollingRule(pollingRule);
            }
         }
      } else {
         tCoreSchedulerKmLog.setPollingRule("每天");
         tCoreSchedulerKmLog.setRulestype("0");
      }

      if (result.success) {
         tCoreSchedulerKmLog.setTestResult("1");
      } else {
         tCoreSchedulerKmLog.setTestResult("0");
      }

      if (null != result.message && !"".equals(result.message.toString())) {
         tCoreSchedulerKmLog.setTestDetail(result.message.toString());
      }

      this.tCoreSchedulerKmLogDao.save(tCoreSchedulerKmLog);
   }

   private TestResult testKms() {
      TestResult result = new TestResult();
      Ticket ticket = this.testDataKey(result.message);
      if (ticket.token != null && ticket.dataKey != null) {
         result.success = this.testDecryptKey(ticket, result.message);
         return result;
      } else {
         return result;
      }
   }

   private Ticket testDataKey(StringBuffer sb) {
      Ticket ticket = new Ticket();
      sb.append(sdf.format(new Date()) + " INFO - 开始执行Kms获取密钥校验，\r\n");

      try {
         String challengeCode = this.kmsService.obtainChallengeCode();
         String token = this.kmsService.obtainAccessToken(challengeCode);
         ticket.token = token;
         String dataKey = this.kmsService.createDataKey(Kms.MasterKey.getInstance().getKeyid(), token);
         if (dataKey != null && dataKey.length() > 0) {
            sb.append(sdf.format(new Date()) + " INFO - 获取密钥成功，\r\n");
            ticket.dataKey = dataKey;
         } else {
            sb.append(sdf.format(new Date()) + " ERR - 获取密钥失败，密钥为空，\r\n");
         }

         sb.append(sdf.format(new Date()) + " INFO - 返回密钥值为:");
         sb.append(ticket.dataKey);
         sb.append("。\r\n");
         return ticket;
      } catch (Exception e) {
         sb.append(sdf.format(new Date()) + " ERR - 检测获取密钥失败，异常为：");
         this.printException(sb, e);
         sb.append("。\r\n");
         return ticket;
      }
   }

   private boolean testDecryptKey(Ticket ticket, StringBuffer sb) {
      sb.append(sdf.format(new Date()) + " INFO - 开始执行Kms解密密钥校验检测，被解密密钥为：");
      sb.append(ticket.dataKey);
      sb.append("。\r\n");

      try {
         String key = this.kmsService.obtainSecretKey(Kms.MasterKey.getInstance().getKeyid(), ticket.token, ticket.dataKey);
         if (key != null && key.length() != 0) {
            if (key.equals(ticket.dataKey)) {
               sb.append(sdf.format(new Date()) + " ERR - 解密失败，解密前密钥为:");
               sb.append(ticket.dataKey);
               sb.append("，解密后为密钥为：");
               sb.append(key);
               sb.append("。\r\n");
               return false;
            } else {
               sb.append(sdf.format(new Date()) + " INFO - 解密成功，解密后密钥为：");
               sb.append(key);
               sb.append("。\r\n");
               return true;
            }
         } else {
            sb.append(sdf.format(new Date()) + " ERR - 解密失败，解密后的密钥为空。\r\n");
            return false;
         }
      } catch (Exception e) {
         sb.append(sdf.format(new Date()) + " ERR - 检测解密密钥失败，异常为：");
         this.printException(sb, e);
         sb.append("。\r\n");
         return false;
      }
   }

   private void printException(StringBuffer sb, Exception exception) {
      sb.append(exception.toString());
   }

   static class Ticket {
      String token;
      String dataKey;
   }

   static class TestResult {
      boolean success = false;
      StringBuffer message = new StringBuffer();
   }
}
