package com.chenyang.nse.bussiness.service.core.dataproject.impl;

import com.chenyang.nse.bussiness.dao.core.dataproject.TableClounmInfoDao;
import com.chenyang.nse.bussiness.dao.core.dataproject.TableJoinsInfoDao;
import com.chenyang.nse.bussiness.entity.db.ColumnInfo;
import com.chenyang.nse.bussiness.entity.db.ForeignKeyInfo;
import com.chenyang.nse.bussiness.entity.db.PrimaryKeyInfo;
import com.chenyang.nse.bussiness.entity.orm.table.core.dataproject.TableClounmInfo;
import com.chenyang.nse.bussiness.entity.orm.table.core.dataproject.TableJoinsInfo;
import com.chenyang.nse.bussiness.service.core.dataproject.TableJoinsInfoService;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class TableJoinsInfoServiceImpl implements TableJoinsInfoService {
   @Autowired
   private TableJoinsInfoDao tableJoinsInfoDao;
   @Autowired
   private TableClounmInfoDao tableClounmInfoDao;

   public void save(TableJoinsInfo tableJoinsInfo) {
      this.tableJoinsInfoDao.save(tableJoinsInfo);
   }

   public List<TableJoinsInfo> queryAllbyTaskid(String taskid) {
      return this.tableJoinsInfoDao.queryAll(new Criterion[]{Restrictions.eq("taskid", taskid)});
   }

   public void removeByTaskid(String taskid) {
      this.tableJoinsInfoDao.remove(new Criterion[]{Restrictions.eq("taskid", taskid)});
   }

   public void removeTbcolumByTJid(String id) {
      this.tableClounmInfoDao.remove(new Criterion[]{Restrictions.eq("tableJoinsId", id)});
   }

   public void saveJoinsInfo(Connection connection, String schema, String tablename, List<ColumnInfo> columnInfoList, String taskid, List<String> tablenamelist) {
      List<PrimaryKeyInfo> pkList = getPkList(connection, schema, tablename);
      TableJoinsInfo tableJoinsInfo = new TableJoinsInfo();
      tableJoinsInfo.setId(UUID.randomUUID().toString());
      tableJoinsInfo.setOnwer(schema);
      tableJoinsInfo.setTableName(tablename);
      tableJoinsInfo.setTaskid(taskid);
      int datacount = 0;
      if (pkList.size() == 0) {
         datacount = this.getDataCount(connection, schema, tablename);
      }

      for(ColumnInfo columnInfo : columnInfoList) {
         TableClounmInfo tableClounmInfo = new TableClounmInfo();
         tableClounmInfo.setClounmName(columnInfo.getColumnname());
         tableClounmInfo.setClounmType(columnInfo.getTypename());
         tableClounmInfo.setClounmLength(columnInfo.getColumnsize());
         if (pkList.size() > 0) {
            for(PrimaryKeyInfo primaryKeyInfo : pkList) {
               if (columnInfo.getColumnname().equals(primaryKeyInfo.getColumnname())) {
                  tableClounmInfo.setIsPK("YES");
               } else {
                  tableClounmInfo.setIsPK("NO");
               }
            }
         } else {
            int colDataCount = this.getColDataCount(connection, schema, tablename, columnInfo.getColumnname());
            if (colDataCount == datacount && datacount != 0) {
               tableClounmInfo.setIsPK("YES");
            } else {
               tableClounmInfo.setIsPK("NO");
            }
         }

         tableClounmInfo.setIsFK("NO");
         tableClounmInfo.setFkTableName("");
         tableClounmInfo.setFkClounmName("");
         tableClounmInfo.setTableJoinsId(tableJoinsInfo.getId());
         this.tableClounmInfoDao.save(tableClounmInfo);
      }

      this.tableJoinsInfoDao.save(tableJoinsInfo);
   }

   public static List<PrimaryKeyInfo> getPkList(Connection connection, String schema, String tablename) {
      List<PrimaryKeyInfo> list = new ArrayList();
      PreparedStatement pstmt = null;
      ResultSet rs = null;
      String sql = "select a.constraint_name pk_con,a.table_name pk_table,b.column_name pk_col,a.owner pk_owner from dba_constraints a,dba_cons_columns b where (a.constraint_type='P' or a.constraint_type='U') and a.constraint_name=b.constraint_name and a.owner=b.owner and a.table_name = ? and a.owner = ?";

      try {
         pstmt = connection.prepareStatement(sql);
         pstmt.setString(1, tablename);
         pstmt.setString(2, schema);
         rs = pstmt.executeQuery();

         while(rs.next()) {
            PrimaryKeyInfo primaryKeyInfo = new PrimaryKeyInfo();
            primaryKeyInfo.setTablename(tablename);
            primaryKeyInfo.setColumnname(rs.getString("pk_col"));
            primaryKeyInfo.setKeyseq(rs.getString("pk_con"));
            list.add(primaryKeyInfo);
         }
      } catch (SQLException e1) {
         e1.printStackTrace();
      } finally {
         try {
            if (rs != null) {
               rs.close();
            }

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

      }

      return list;
   }

   public List<ForeignKeyInfo> getFkList(Connection connection, String schema, String tablename) {
      List<ForeignKeyInfo> list = new ArrayList();
      PreparedStatement pstmt = null;
      ResultSet rs = null;
      String sql = "select fk_table fkTableName,fk_col fkCloumName,pk_table pkTableName,pk_col pkClounmName from (select c.constraint_name fk_con,c.table_name fk_table,c.delete_rule del_rule,d.column_name fk_col,c.R_OWNER r_pk_owner,c.R_CONSTRAINT_NAME r_pk_con,c.owner fk_owner from dba_constraints c,dba_cons_columns d where c.constraint_type='R' and c.constraint_name=d.constraint_name and c.owner=d.owner) fk left join  (select a.constraint_name pk_con,a.table_name pk_table,b.column_name pk_col,a.owner pk_owner from dba_constraints a,dba_cons_columns b where (a.constraint_type='P' or a.constraint_type='U') and a.constraint_name=b.constraint_name and a.owner=b.owner) pk  on pk.pk_con=fk.r_pk_con where pk.pk_owner=fk.r_pk_owner and fk_table = ? and fk_owner = ?";

      try {
         pstmt = connection.prepareStatement(sql);
         pstmt.setString(1, tablename);
         pstmt.setString(2, schema);
         rs = pstmt.executeQuery();

         while(rs.next()) {
            ForeignKeyInfo foreignKeyInfo = new ForeignKeyInfo();
            foreignKeyInfo.setFktable(tablename);
            foreignKeyInfo.setFkcolumn(rs.getString("fkCloumName"));
            foreignKeyInfo.setPktable(rs.getString("pkTableName"));
            foreignKeyInfo.setPkcolumn(rs.getString("pkClounmName"));
            list.add(foreignKeyInfo);
         }
      } catch (SQLException e1) {
         e1.printStackTrace();
      } finally {
         try {
            if (rs != null) {
               rs.close();
            }

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

      }

      return list;
   }

   public static List<ColumnInfo> getTableForCol(Connection connection, String schema) {
      List<ColumnInfo> list = new ArrayList();
      PreparedStatement pstmt = null;
      ResultSet rs = null;
      String sql = "select table_name, a.COLUMN_NAME colname from dba_tab_columns a order by table_name";

      try {
         pstmt = connection.prepareStatement(sql);
         rs = pstmt.executeQuery();

         while(rs.next()) {
            ColumnInfo columnInfo = new ColumnInfo();
            columnInfo.setTablename(rs.getString("table_name"));
            columnInfo.setColumnname(rs.getString("colname"));
            list.add(columnInfo);
         }
      } catch (SQLException e1) {
         e1.printStackTrace();
      } finally {
         try {
            if (rs != null) {
               rs.close();
            }

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

      }

      return list;
   }

   public int getDataCount(Connection connection, String schema, String tablename) {
      PreparedStatement pstmt = null;
      ResultSet rs = null;
      int count = 0;
      String sql = "select count(1) from " + schema + "." + tablename;

      try {
         pstmt = connection.prepareStatement(sql);

         for(rs = pstmt.executeQuery(); rs.next(); count = rs.getInt(1)) {
         }
      } catch (SQLException e1) {
         e1.printStackTrace();
      } finally {
         try {
            if (rs != null) {
               rs.close();
            }

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

      }

      return count;
   }

   public int getColDataCount(Connection connection, String schema, String tablename, String columnname) {
      PreparedStatement pstmt = null;
      ResultSet rs = null;
      int count = 0;
      String sql = "select count(1) from (select distinct \"" + columnname + "\" from " + schema + "." + tablename + ")";

      try {
         pstmt = connection.prepareStatement(sql);

         for(rs = pstmt.executeQuery(); rs.next(); count = rs.getInt(1)) {
         }
      } catch (SQLException e1) {
         e1.printStackTrace();
      } finally {
         try {
            if (rs != null) {
               rs.close();
            }

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

      }

      return count;
   }

   public List<TableClounmInfo> queryColAllbyId(String id) {
      return this.tableClounmInfoDao.queryAll(new Criterion[]{Restrictions.eq("tableJoinsId", id)});
   }

   public List<TableJoinsInfo> queryAllbyTaskidAndtbName(String taskid, String tablename) {
      return this.tableJoinsInfoDao.queryAll(new Criterion[]{Restrictions.eq("taskid", taskid), Restrictions.eq("tableName", tablename)});
   }

   public void updateColInfo(TableClounmInfo tableClounmInfo) {
      this.tableClounmInfoDao.saveOrUpdate(tableClounmInfo);
   }

   public List<ColumnInfo> queryTbForCol(Connection connection, String schema) {
      return getTableForCol(connection, schema);
   }

   public void findColFK(String taskid, String tableName, List<ColumnInfo> columlist, List<ForeignKeyInfo> fkList) {
      List<TableJoinsInfo> tableJoinsInfolist1 = this.queryAllbyTaskidAndtbName(taskid, tableName);
      TableJoinsInfo tableJoinsInfo = null;
      if (tableJoinsInfolist1.size() == 0) {
         System.out.println(tableName);
      } else {
         tableJoinsInfo = (TableJoinsInfo)tableJoinsInfolist1.get(0);
         List<TableClounmInfo> queryCol = this.queryColAllbyId(tableJoinsInfo.getId());

         for(TableClounmInfo tableClounmInfo1 : queryCol) {
            if ("YES".equals(tableClounmInfo1.getIsPK())) {
               for(ColumnInfo columnInfo : columlist) {
                  if (columnInfo.getColumnname().equals(tableClounmInfo1.getClounmName())) {
                     List<TableJoinsInfo> tableJoinsInfolist = this.queryAllbyTaskidAndtbName(taskid, columnInfo.getTablename());
                     TableJoinsInfo tableJoinsInfo1 = null;
                     if (tableJoinsInfolist.size() == 0) {
                        System.out.println(columnInfo.getTablename());
                     } else {
                        tableJoinsInfo1 = (TableJoinsInfo)tableJoinsInfolist.get(0);
                        if (!tableJoinsInfo.getId().equals(tableJoinsInfo1.getId())) {
                           TableClounmInfo tableClounmInfo = (TableClounmInfo)this.tableClounmInfoDao.queryAll(new Criterion[]{Restrictions.eq("tableJoinsId", tableJoinsInfo1.getId()), Restrictions.eq("clounmName", columnInfo.getColumnname())}).get(0);
                           if ("NO".equals(tableClounmInfo.getIsPK())) {
                              tableClounmInfo.setIsFK("YES");
                              tableClounmInfo.setFkTableName(tableName);
                              tableClounmInfo.setFkClounmName(tableClounmInfo1.getClounmName());
                              this.updateColInfo(tableClounmInfo);
                           }
                        }
                     }
                  }
               }
            }
         }

         for(TableClounmInfo tableClounmInfo2 : queryCol) {
            if (fkList.size() > 0) {
               for(ForeignKeyInfo foreignKeyInfo : fkList) {
                  if (tableClounmInfo2.getClounmName().equals(foreignKeyInfo.getFkcolumn())) {
                     tableClounmInfo2.setIsPK("NO");
                     tableClounmInfo2.setIsFK("YES");
                     tableClounmInfo2.setFkTableName(foreignKeyInfo.getPktable());
                     tableClounmInfo2.setFkClounmName(foreignKeyInfo.getPkcolumn());
                  }
               }
            }

            this.updateColInfo(tableClounmInfo2);
         }
      }

   }
}
