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

import cn.hutool.core.util.ObjectUtil;
import com.chenyang.nse.bussiness.config.PropertiesLoaderUtils;
import com.chenyang.nse.bussiness.dao.core.key.TCoreKeyTypeManagementDao;
import com.chenyang.nse.bussiness.dao.table.core.TCoreDatasystemDao;
import com.chenyang.nse.bussiness.dao.table.core.dataproject.TCoreSecretkeyDao;
import com.chenyang.nse.bussiness.dao.table.core.encryption.TCoreEncryptionDao;
import com.chenyang.nse.bussiness.dao.table.core.encryption.TCoreEncryptionTypeFieldDao;
import com.chenyang.nse.bussiness.entity.orm.table.core.TCoreDatasystem;
import com.chenyang.nse.bussiness.entity.orm.table.core.dataproject.TCoreSecretkey;
import com.chenyang.nse.bussiness.entity.orm.table.core.encryption.TCoreEncryption;
import com.chenyang.nse.bussiness.entity.orm.table.core.encryption.TCoreEncryptionTypeField;
import com.chenyang.nse.bussiness.entity.vo.AutoDetectVO;
import com.chenyang.nse.bussiness.entity.vo.AutoFieldVO;
import com.chenyang.nse.bussiness.entity.vo.ComboboxVO;
import com.chenyang.nse.bussiness.entity.vo.key.TCoreKeyTypeManagementVO;
import com.chenyang.nse.bussiness.service.core.encryption.TCoreEncryptionService;
import com.chenyang.nse.bussiness.service.core.impl.encryption.TCoreEncryptionServiceImpl;
import com.chenyang.nse.bussiness.service.key.KeyManagerService;
import com.chenyang.nse.bussiness.tools.dataprocess.ApplicationContextProvider;
import com.chenyang.nse.bussiness.tools.encryption.EncProvider;
import com.chenyang.nse.bussiness.tools.encryption.SM4Util;
import com.chenyang.nse.bussiness.tools.io.FileTool;
import com.chenyang.nse.bussiness.tools.jdbc.JdbcTool;
import com.chenyang.nse.bussiness.tools.token.TokenUtil;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.servlet.http.HttpServletRequest;
import kl.hsm.client.sdk.HsmSdk;
import org.apache.commons.lang3.StringUtils;
import org.apache.thrift.TException;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.stereotype.Service;

@Service
public class TCoreEncryptionServiceSdkImpl implements TCoreEncryptionService {
   @Autowired
   TCoreEncryptionDao tCoreEncryptionDao;
   @Autowired
   HttpServletRequest request;
   @Autowired
   TCoreSecretkeyDao tCoreSecretkeyDao;
   @Autowired
   private TCoreDatasystemDao tCoreDatasystemDao;
   @Autowired
   TCoreEncryptionTypeFieldDao tCoreEncryptionTypeFieldDao;
   @Autowired
   KeyManagerService keyManagerService;
   @Autowired
   TCoreKeyTypeManagementDao tCoreKeyTypeManagementDao;
   private static Charset charset = Charset.forName("GBK");
   private static CharsetDecoder decoder;
   protected Logger logger = LoggerFactory.getLogger(this.getClass());

   public void save(TCoreEncryption encryption) {
      String username = TokenUtil.getUserId(this.request.getHeader("token"));
      if (encryption.getId() != null && !encryption.getId().equals("")) {
         encryption.setUpdatetime(new Date());
         encryption.setUpdateuser(username);
         this.tCoreEncryptionDao.update(encryption);
      } else {
         encryption.setCreatetime(new Date());
         encryption.setCreateuser(username);
         this.tCoreEncryptionDao.save(encryption);
      }

   }

   public List<ComboboxVO> initEncryptionTypeList() {
      return this.tCoreEncryptionDao.initEncryptionTypeList();
   }

   public List<TCoreEncryptionTypeField> deleteEncryption(String encryptionId) {
      List<TCoreSecretkey> tCoreSecretkeys = this.tCoreSecretkeyDao.queryAll(new Criterion[]{Restrictions.eq("encryption_id", encryptionId)});
      List<TCoreEncryptionTypeField> curFlagFieldList = new ArrayList();

      for(TCoreSecretkey tCoreSecretkey : tCoreSecretkeys) {
         if (!ObjectUtil.isEmpty(this.delSecretKey(tCoreSecretkey.getId()))) {
            for(TCoreEncryptionTypeField tCoreEncryptionTypeField : this.delSecretKey(tCoreSecretkey.getId())) {
               curFlagFieldList.add(tCoreEncryptionTypeField);
            }
         }
      }

      if (curFlagFieldList.size() > 0) {
         return curFlagFieldList;
      } else {
         if (!ObjectUtil.isEmpty(this.tCoreEncryptionDao.get(encryptionId))) {
            this.tCoreEncryptionDao.removeById(encryptionId);
         }

         return null;
      }
   }

   private Properties getP() {
      Properties props = new Properties();

      try {
         props = PropertiesLoaderUtils.loadAllProperties("config.properties");
      } catch (IOException e) {
         e.printStackTrace();
      }

      return props;
   }

   public Map<String, String> getParams() {
      TCoreKeyTypeManagementVO tCoreKeyTypeManagementVO = this.keyManagerService.queryTCoreKeyTypeManageUsed();
      return this.keyManagerService.showKeyParams(tCoreKeyTypeManagementVO.getId());
   }

   public String getRandomValue(String type) {
      HsmSdk sdk = new HsmSdk();
      Long sessionId = 0L;

      String var16;
      try {
         Map<String, String> params = this.getParams();
         String path = (String)params.get("hsmfiledir");
         if (!path.endsWith(File.separator)) {
            path = path + File.separator;
         }

         path = path + "HsmConfig.properties";
         String SDKKeyId = (String)params.get("sdkkeyid");
         String password = (String)params.get("sdkpassword");
         Map<String, String> paramMap = getParamsFromFile(path);
         sdk.init((String)paramMap.get("ip"), Integer.parseInt((String)paramMap.get("port")), Boolean.parseBoolean((String)paramMap.get("ssl")), (String)paramMap.get("keyStore"), (String)paramMap.get("trustStore"), Integer.parseInt((String)paramMap.get("poolMax")));
         sessionId = sdk.openSession();
         String n16 = EncProvider.generateKey("SM4");
         ByteBuffer random = ByteBuffer.wrap(n16.getBytes());
         ByteBuffer dataKeyBuf = sdk.asymEncIn(Integer.parseInt(SDKKeyId), random);
         String dataKey = Base64.getEncoder().encodeToString(dataKeyBuf.array());
         sdk.getPrivateKeyAccessRight(sessionId, Integer.parseInt(SDKKeyId), ByteBuffer.wrap(password.getBytes()));
         ByteBuffer asymEncData = ByteBuffer.wrap(Base64.getDecoder().decode(dataKey));
         ByteBuffer asymDecDataByt = sdk.asymDecIn(sessionId, Integer.parseInt(SDKKeyId), asymEncData);
         dataKey = new String(asymDecDataByt.array());
         TCoreEncryptionServiceImpl tCoreEncryptionServiceImpl = (TCoreEncryptionServiceImpl)ApplicationContextProvider.getBean(TCoreEncryptionServiceImpl.class);
         dataKey = tCoreEncryptionServiceImpl.getEncDataKey(dataKey);
         this.logger.info("dataKey={}", dataKey);
         var16 = dataKey;
      } catch (Exception e) {
         this.logger.error(e.getMessage(), e);
         throw new RuntimeException(e.getMessage(), e);
      } finally {
         try {
            if (sessionId > 0L) {
               sdk.closeSession(sessionId);
            }
         } catch (TException e) {
            e.printStackTrace();
         }

      }

      return var16;
   }

   public String testEncryption(String type, String param, String isLike, String secret_key, String keepfirst, String encdigit, String twoindex) {
      String cipher = "";

      try {
         try {
            TCoreEncryptionServiceImpl tCoreEncryptionServiceImpl = (TCoreEncryptionServiceImpl)ApplicationContextProvider.getBean(TCoreEncryptionServiceImpl.class);
            String dataKey = tCoreEncryptionServiceImpl.getDecDataKey(secret_key);
            cipher = EncProvider.encryptEcb(type, dataKey, param, isLike, (String)null, (String)null, (String)null);
         } catch (Exception e) {
            e.printStackTrace();
         }

         return cipher;
      } finally {
         ;
      }
   }

   public void saveSecretKey(TCoreSecretkey tCoreSecretKey) {
      String username = TokenUtil.getUserId(this.request.getHeader("token"));
      if (tCoreSecretKey.getId() != null && !tCoreSecretKey.getId().equals("")) {
         tCoreSecretKey.setUpdatetime(new Date());
         tCoreSecretKey.setUpdateuser(username);
         this.tCoreSecretkeyDao.update(tCoreSecretKey);
      } else {
         tCoreSecretKey.setCreatetime(new Date());
         tCoreSecretKey.setCreateuser(username);
         this.tCoreSecretkeyDao.save(tCoreSecretKey);
      }

   }

   public List<TCoreEncryptionTypeField> delSecretKey(String keyId) {
      List<TCoreEncryptionTypeField> tCoreEncryptionTypeFieldList = this.tCoreEncryptionTypeFieldDao.queryAll();
      List<TCoreEncryptionTypeField> curDelFieldList = new ArrayList();
      List<TCoreEncryptionTypeField> curFlagFieldList = new ArrayList();

      for(TCoreEncryptionTypeField tCoreEncryptionTypeField : tCoreEncryptionTypeFieldList) {
         if (keyId.equals(tCoreEncryptionTypeField.getEncryption_secretkey_id())) {
            curFlagFieldList.add(tCoreEncryptionTypeField);
         }
      }

      if (curFlagFieldList.size() > 0) {
         return curFlagFieldList;
      } else {
         if (curDelFieldList.size() > 0) {
            for(TCoreEncryptionTypeField curTCoreEncryptionTypeField : curDelFieldList) {
               this.tCoreEncryptionTypeFieldDao.removeById(curTCoreEncryptionTypeField.getId());
            }
         }

         if (!ObjectUtil.isEmpty(this.tCoreSecretkeyDao.get(keyId))) {
            this.tCoreSecretkeyDao.removeById(keyId);
         }

         return null;
      }
   }

   public List<TCoreEncryption> queryEncryptionList(String encryption_name) {
      List<TCoreEncryption> encryptionList = this.tCoreEncryptionDao.queryAll(new Criterion[]{Restrictions.like("encryption_name", encryption_name, MatchMode.ANYWHERE)});

      for(TCoreEncryption tCoreEncryption : encryptionList) {
         List<TCoreSecretkey> keyList = this.tCoreSecretkeyDao.queryAll(new Criterion[]{Restrictions.eq("encryption_id", tCoreEncryption.getId())});
         tCoreEncryption.setList(keyList);
      }

      return encryptionList;
   }

   public Map<String, String> queryEncryptionInfo(String secretKeyId) {
      Map returnMap = new HashMap();
      String encryptionType = "";
      TCoreSecretkey tCoreSecretkey = (TCoreSecretkey)this.tCoreSecretkeyDao.queryUnique(new Criterion[]{Restrictions.eq("id", secretKeyId)});
      TCoreEncryption tCoreEncryption = (TCoreEncryption)this.tCoreEncryptionDao.queryUnique(new Criterion[]{Restrictions.eq("id", tCoreSecretkey.getEncryption_id())});
      if (tCoreEncryption != null) {
         encryptionType = tCoreEncryption.getEncryption_type();
      }

      returnMap.put("encryptionType", encryptionType);
      String dataKey = "";
      if (null != tCoreSecretkey.getSectet_key_value() && !"".equals(tCoreSecretkey.getSectet_key_value())) {
         try {
            TCoreEncryptionServiceImpl tCoreEncryptionServiceImpl = (TCoreEncryptionServiceImpl)ApplicationContextProvider.getBean(TCoreEncryptionServiceImpl.class);
            dataKey = tCoreEncryptionServiceImpl.getDecDataKey(tCoreSecretkey.getSectet_key_value());
         } catch (Exception e) {
            e.printStackTrace();
         } finally {
            ;
         }
      }

      returnMap.put("secretkey", dataKey);
      return returnMap;
   }

   public String queryEncryptionOpenKey(String secretKey) {
      if (StringUtils.isEmpty(secretKey)) {
         return "";
      } else {
         HsmSdk sdk = new HsmSdk();
         Long sessionId = 0L;

         try {
            Map<String, String> params = this.getParams();
            String path = (String)params.get("hsmfiledir");
            if (!path.endsWith(File.separator)) {
               path = path + File.separator;
            }

            path = path + "HsmConfig.properties";
            String SDKKeyId = (String)params.get("sdkkeyid");
            String password = (String)params.get("sdkpassword");
            sdk.init(path);
            sessionId = sdk.openSession();
            sdk.getPrivateKeyAccessRight(sessionId, Integer.parseInt(SDKKeyId), ByteBuffer.wrap(password.getBytes()));
            ByteBuffer asymEncData = ByteBuffer.wrap(Base64.getDecoder().decode(secretKey));
            ByteBuffer asymDecDataByt = sdk.asymDecIn(sessionId, Integer.parseInt(SDKKeyId), asymEncData);
            String var10 = new String(asymDecDataByt.array());
            return var10;
         } catch (Exception e) {
            e.printStackTrace();
         } finally {
            try {
               if (sessionId > 0L) {
                  sdk.closeSession(sessionId);
               }
            } catch (TException e) {
               e.printStackTrace();
            }

         }

         return "";
      }
   }

   public Map<String, String> queryEncryptionInfo(String keyName, String sKeyName) {
      Map<String, String> returnMap = new HashMap();
      String encryptionType = "";
      String secretKeyId = null;

      try {
         secretKeyId = this.tCoreSecretkeyDao.queryIdByKeyAndSKey(keyName, sKeyName);
      } catch (EmptyResultDataAccessException var8) {
         returnMap.put("msg", "加密类型和秘钥不匹配");
         return returnMap;
      }

      TCoreSecretkey tCoreSecretkey = (TCoreSecretkey)this.tCoreSecretkeyDao.queryUnique(new Criterion[]{Restrictions.eq("id", secretKeyId)});
      TCoreEncryption tCoreEncryption = (TCoreEncryption)this.tCoreEncryptionDao.queryUnique(new Criterion[]{Restrictions.eq("id", tCoreSecretkey.getEncryption_id())});
      if (tCoreEncryption != null) {
         encryptionType = tCoreEncryption.getEncryption_type();
      }

      returnMap.put("encryptionType", encryptionType);
      returnMap.put("secretkey", tCoreSecretkey.getSectet_key_value());
      returnMap.put("secretkeyId", secretKeyId);
      return returnMap;
   }

   public AutoDetectVO autoDetect(AutoDetectVO autoDetectVO) throws SQLException {
      String dataSystemId = autoDetectVO.getDataSystemId();
      TCoreDatasystem datasystem = (TCoreDatasystem)this.tCoreDatasystemDao.get(dataSystemId);
      Connection conn = JdbcTool.getConnection(datasystem);
      Statement stmt = conn.createStatement();
      List<AutoFieldVO> columnsList = autoDetectVO.getColumnArr();
      String encString = "";
      Integer bestLength = 0;

      for(AutoFieldVO fieldVO : columnsList) {
         ResultSet rs = stmt.executeQuery("SELECT max(length(" + fieldVO.getColumnName() + ")) as maxLength FROM " + autoDetectVO.getTableName());

         while(rs.next()) {
            System.out.println(rs.getInt(1));
            Integer length = rs.getInt(1);
            StringBuffer encValue = new StringBuffer("");

            for(int i = 0; i < length; ++i) {
               encValue.append("啊");
            }

            try {
               encString = EncProvider.encryptEcb("SM4", SM4Util.generateKey(), encValue.toString(), fieldVO.getIsLike(), (String)null, (String)null, (String)null);
               bestLength = encString.length() + 10;
               bestLength = bestLength < fieldVO.getOriginalLength() ? fieldVO.getOriginalLength() : bestLength;
               fieldVO.setBestLength(bestLength);
            } catch (Exception e) {
               e.printStackTrace();
            }
         }
      }

      try {
         if (stmt != null) {
            stmt.close();
         }

         if (conn != null) {
            conn.close();
         }
      } catch (SQLException e) {
         e.printStackTrace();
      }

      return autoDetectVO;
   }

   public String getProcesslog(String path) {
      File logFile = new File(path);
      BufferedReader reader = null;
      StringBuffer stringBuffer = new StringBuffer();

      try {
         if (!logFile.exists()) {
            this.logger.warn("文件" + logFile + "不存在,重新创建一个");
            FileTool.fileDirsCreate(path);
            logFile.createNewFile();
         }

         reader = new BufferedReader(new FileReader(logFile));
         String lineStr = null;

         while((lineStr = reader.readLine()) != null) {
            stringBuffer.append(lineStr);
            stringBuffer.append("\n");
         }

         reader.close();
      } catch (Exception e) {
         this.logger.error(e.getMessage(), e);
         throw new RuntimeException(e);
      } finally {
         if (reader != null) {
            try {
               reader.close();
            } catch (IOException e) {
               this.logger.error(e.getMessage(), e);
               throw new RuntimeException(e);
            }
         }

      }

      return stringBuffer.toString();
   }

   public void updateFlag(String projectId, String dataSystemId, String schema, String tableName, String columnName, String flag) {
      TCoreEncryptionTypeField tCoreEncryptionTypeField = (TCoreEncryptionTypeField)this.tCoreEncryptionTypeFieldDao.queryUnique(new Criterion[]{Restrictions.eq("projectid", projectId), Restrictions.eq("datasystem_id", dataSystemId), Restrictions.eq("tschemas", schema), Restrictions.eq("names", tableName), Restrictions.eq("table_field_id", columnName)});
      tCoreEncryptionTypeField.setFlag(flag);
      this.tCoreEncryptionTypeFieldDao.update(tCoreEncryptionTypeField);
   }

   public static Map<String, String> getParamsFromFile(String filePath) throws IOException {
      HashMap<String, String> map = new HashMap(6);

      try {
         for(String line : Files.readAllLines(Paths.get(filePath))) {
            if (line.indexOf("hsm.ips=") >= 0) {
               map.put("ip", line.substring(line.indexOf("hsm.ips=") + 8).trim());
            } else if (line.indexOf("hsm.port=") >= 0) {
               map.put("port", line.substring(line.indexOf("hsm.port=") + 9).trim());
            } else if (line.indexOf("poolMax=") >= 0) {
               map.put("poolMax", line.substring(line.indexOf("poolMax=") + 8).trim());
            } else if (line.indexOf("ssl=") >= 0) {
               map.put("ssl", line.substring(line.indexOf("ssl=") + 4).trim());
            } else if (line.indexOf("keyStore=") >= 0) {
               map.put("keyStore", line.substring(line.indexOf("keyStore=") + 9).trim());
            } else if (line.indexOf("trustStore=") >= 0) {
               map.put("trustStore", line.substring(line.indexOf("trustStore=") + 11).trim());
            }
         }
      } catch (IOException e) {
         e.printStackTrace();
      }

      return map;
   }

   static {
      decoder = charset.newDecoder();
   }
}
