package com.chenyang.nse.bussiness.service.core.udf;

import com.chenyang.nse.bussiness.config.PropertiesLoaderUtils;
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.vo.maskingtask.ColumnInfoVO;
import com.chenyang.nse.bussiness.service.core.TdataProjectService;
import com.chenyang.nse.bussiness.service.core.encryption.EncryptionConfigService;
import com.chenyang.nse.bussiness.tools.jdbc.JdbcTool;
import com.chenyang.nse.bussiness.tools.net.IpAddressTool;
import com.chenyang.nse.bussiness.tools.strategy.StrategyData;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.net.SocketException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class SqlServerUdfService extends UdfService {
   public SqlServerUdfService(TdataProjectService tdataProjectService, EncryptionConfigService encryptionConfigService, TCoreEncryptionTypeFieldDao tCoreEncryptionTypeFieldDao, StrategyData strategyData) {
      super(tdataProjectService, encryptionConfigService, tCoreEncryptionTypeFieldDao, strategyData);
   }

   public String alterTableName(TCoreDatasystem tCoreDatasystem, String schemaName, String tableName, String udfTableName) {
      try {
         this.connection = JdbcTool.getConnection(tCoreDatasystem);
         Statement statement = this.connection.createStatement();
         String alterNameSql = "EXEC sp_rename '" + tableName + "','" + udfTableName + "'";
         statement.executeUpdate(alterNameSql);
         String funIsExist = "select * from sysobjects where  name='EncT'";
         ResultSet res = statement.executeQuery(funIsExist);
         if (res.next()) {
            return "";
         } else {
            new Properties();
            String dbServerName = tCoreDatasystem.getDbservername();
            String setTrust = "ALTER DATABASE " + dbServerName + " SET TRUSTWORTHY ON";
            String spConfigure1 = "sp_configure 'show advanced options',1;RECONFIGURE;";
            String spConfigure2 = "sp_configure 'clr enabled', 1";
            String spConfigure3 = "Sp_changedbowner 'sa'";
            Properties props = PropertiesLoaderUtils.loadAllProperties("config.properties");
            String filepath = props.getProperty("sqlserverudfpath");
            String createAssembly = "create assembly EncDec from  '" + filepath + "' with permission_set=UNSAFE;";
            String createFunctionEncT = "create function EncT(@key nvarchar(4000),@value nvarchar(4000)) returns nvarchar(4000) as external name EncDec.T.Enc";
            String createFunctionDecT = "create function DecT(@key nvarchar(4000),@value nvarchar(4000)) returns nvarchar(4000) as external name EncDec.T.Dec;";
            statement.execute(setTrust);
            statement.execute(spConfigure1);
            statement.execute(spConfigure2);
            statement.execute(spConfigure3);
            statement.execute(createAssembly);
            statement.execute(createFunctionEncT);
            statement.execute(createFunctionDecT);
            return "ok";
         }
      } catch (SQLException e) {
         return e.getMessage();
      } catch (IOException e) {
         throw new RuntimeException(e);
      }
   }

   public boolean isFinished(String datasystemId, String schme, String tableName) {
      TCoreDatasystem tCoreDatasystem = this.tdataProjectService.selectOneProDataSource(datasystemId);
      String viewName = this.getSourceTable(tableName);
      this.connection = JdbcTool.getConnection(tCoreDatasystem);

      try {
         this.connection = JdbcTool.getConnection(tCoreDatasystem);
         Statement statement = this.connection.createStatement();
         String alterNameSql = "SELECT 1 FROM " + schme + ".[" + viewName + "]";
         ResultSet res = statement.executeQuery(alterNameSql);
         return res.next();
      } catch (SQLException var9) {
         return false;
      }
   }

   public String getCreateViewSql(String schemaName, String tableName, List<ColumnInfoVO> originList, Map<String, String> encryptionMap) {
      String viewName = this.getSourceTable(tableName);
      String sql = "CREATE or alter VIEW " + schemaName + ".[" + viewName + "] AS SELECT ";

      for(int i = 0; i < originList.size(); ++i) {
         ColumnInfoVO column = (ColumnInfoVO)originList.get(i);
         String columnName = column.getColumnname();
         if (!columnName.contains("_copy")) {
            String rule = (String)encryptionMap.get(column.getColumnname());
            if (rule != null) {
               columnName = schemaName + ".DecT('" + rule + "'," + columnName + ") AS " + columnName;
            }

            sql = sql + "" + columnName;
            if (i != originList.size() - 1) {
               sql = sql + ",";
            }
         }
      }

      sql = sql + " FROM \"" + tableName + "\"";
      return sql;
   }

   public String getCreateTriggerSql(String schemaName, String tableName, List<ColumnInfoVO> originList, Map<String, String> encryptionMap) {
      String viewName = this.getSourceTable(tableName);
      String schameView = schemaName + ".[" + viewName + "]";
      String schameTable = schemaName + ".[" + tableName + "]";
      String insertTriggerName = schemaName + "." + viewName + "_insert_encData";
      String declare = "";
      String set = "";
      String insert = " ( ";
      String values = " values( ";
      String isNull = "";
      String where = "";

      for(int i = 0; i < originList.size(); ++i) {
         ColumnInfoVO column = (ColumnInfoVO)originList.get(i);
         String columnName = column.getColumnname();
         if (!column.getPrimarykey().equals("1")) {
            if (column.getTypename().equals("varchar")) {
               declare = declare + "declare @" + columnName + " nvarchar(4000)";
            } else {
               declare = declare + "declare @" + columnName + " " + column.getTypename().replace(" identity", "");
               if (column.getTypename().equals("nvarchar")) {
                  declare = declare + " (" + column.getColumnsize() + ") ";
               }

               if (column.getColumndef() != null) {
                  isNull = isNull + "if(@" + columnName + " is Null )";
                  isNull = isNull + "set @" + columnName + " = " + column.getColumndef() + ";";
               }
            }

            declare = declare + "; ";
            set = set + "set @" + columnName + "= (select [" + columnName + "] from inserted); ";
            String rule = (String)encryptionMap.get(column.getColumnname());
            insert = insert + "[" + columnName + "]";
            String valueName = "@" + columnName;
            if (rule != null) {
               valueName = schemaName + ".EncT('" + rule + "'," + valueName + ")";
            }

            values = values + valueName;
            if (i != originList.size() - 1) {
               values = values + ",";
               insert = insert + ",";
            }
         }
      }

      insert = insert + " )";
      values = values + ")";
      String sql = "CREATE OR alter TRIGGER " + insertTriggerName + " ON " + schameView + " instead of INSERT as ";
      sql = sql + " BEGIN ";
      sql = sql + declare;
      sql = sql + set;
      sql = sql + isNull;
      sql = sql + " insert into " + schameTable + insert + values + ";";
      sql = sql + "select @@IDENTITY";
      sql = sql + " end";
      return sql;
   }

   public String getUpdateTriggerSql(String schemaName, String tableName, List<ColumnInfoVO> originList, Map<String, String> encryptionMap) {
      String viewName = this.getSourceTable(tableName);
      String schameView = schemaName + ".[" + viewName + "]";
      String schameTable = schemaName + ".[" + tableName + "]";
      String updateTriggerName = schemaName + "." + viewName + "_update_encData";
      String declare = "";
      String set = "";
      String update = "";
      String where = "";

      for(int i = 0; i < originList.size(); ++i) {
         ColumnInfoVO column = (ColumnInfoVO)originList.get(i);
         String columnName = column.getColumnname();
         if (column.getTypename().equals("varchar")) {
            declare = declare + "declare @" + columnName + " nvarchar(4000)";
         } else {
            declare = declare + "declare @" + columnName + " " + column.getTypename().replace(" identity", "");
         }

         if (column.getTypename().equals("nvarchar")) {
            declare = declare + " (" + column.getColumnsize() + ") ";
         }

         declare = declare + "; ";
         set = set + "set @" + columnName + "= (select [" + columnName + "] from inserted); ";
         String rule = (String)encryptionMap.get(column.getColumnname());
         if (column.getPrimarykey().equals("1")) {
            where = " where " + columnName + " = @" + columnName;
         } else {
            update = update + columnName + " = ";
            String valueName = "@" + columnName;
            if (rule != null) {
               valueName = schemaName + ".EncT('" + rule + "'," + valueName + ")";
            }

            update = update + valueName;
            if (i != originList.size() - 1) {
               update = update + ",";
            }
         }
      }

      String sql = "CREATE OR alter TRIGGER " + updateTriggerName + " ON " + schameView + " instead of UPDATE as ";
      sql = sql + " BEGIN ";
      sql = sql + declare;
      sql = sql + set;
      sql = sql + " update " + schameTable + " set " + update + where + ";";
      sql = sql + " end";
      return sql;
   }

   public String getType() {
      return "sqlserver";
   }

   public static String createBat(String path, String gatewayPort) {
      String ip = "";
      String schema = "http";
      String project = "project";

      try {
         ip = IpAddressTool.getLinuxLocalIp().get(0).toString();
      } catch (SocketException e) {
         throw new RuntimeException(e);
      }

      StringBuilder configContent = new StringBuilder();
      configContent.append("reg add  HKEY_CURRENT_CONFIG\\Software\\ENC /f");
      configContent.append("\r\n");
      configContent.append("reg add  HKEY_CURRENT_CONFIG\\Software\\ENC /V ip /t REG_SZ /d " + ip + " /f ");
      configContent.append("\r\n");
      configContent.append("reg add  HKEY_CURRENT_CONFIG\\Software\\ENC /V port /t REG_SZ /d " + gatewayPort + " /f ");
      configContent.append("\r\n");
      configContent.append("reg add  HKEY_CURRENT_CONFIG\\Software\\ENC /V schema /t REG_SZ /d " + schema + " /f ");
      configContent.append("\r\n");
      configContent.append("reg add  HKEY_CURRENT_CONFIG\\Software\\ENC /V project /t REG_SZ /d " + project + " /f ");
      configContent.append("\r\n");
      String filepath = path + "sqlserver.bat";
      FileWriter fileWriter = null;

      try {
         fileWriter = new FileWriter(filepath, false);
         BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
         bufferedWriter.write(configContent.toString());
         bufferedWriter.close();
         fileWriter.close();
         return "";
      } catch (IOException e) {
         throw new RuntimeException(e);
      }
   }

   public static void main(String[] args) {
      Properties props = new Properties();

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

      String filepath = props.getProperty("udfproxypath");
      createBat(filepath, "8181");
   }
}
