/*
 * Copyright 2019-2029 FISOK(www.fisok.cn).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.goer.common.dialect.impl;

import com.goer.common.chiner.model.ColumnField;
import com.goer.common.chiner.model.TableEntity;
import com.goer.common.command.kit.ConnParseKit;
import com.goer.common.dialect.DBDialect;
import com.goer.common.utils.fisok.raw.kit.JdbcKit;
import com.goer.common.utils.fisok.raw.kit.StringKit;
import org.apache.commons.lang3.tuple.Pair;

import java.sql.*;

/**
 * @author : 杨松<yangsong158@qq.com>
 * @date : 2021/6/14
 * @desc : SQLServer数据库方言
 */
public class DBDialectSQLServer extends DBDialect {

    private String querySQL = "SELECT\n" +
            "\ttable_code =\n" +
            "CASE\n" +
            "\t\tWHEN a.colorder= 1 THEN\n" +
            "\t\td.name ELSE ''\n" +
            "\tEND,\n" +
            "\ttable_comment =\n" +
            "CASE\n" +
            "\tWHEN a.colorder= 1 THEN\n" +
//            "\tISNULL( f.value, '' ) ELSE ''\n" +
            "\tCONVERT(nvarchar(1000), f.value) ELSE ''\n" +
            "\tEND,\n" +
            "\tcolumn_index = a.colorder,\n" +
            "\tcolumn_name = a.name,\n" +
            "\tcolumn_is_identity =\n" +
            "CASE\n" +
            "\tWHEN COLUMNPROPERTY( a.id, a.name, 'IsIdentity' ) = 1 THEN\n" +
            "\t'Y' ELSE ''\n" +
            "\tEND,\n" +
            "\tcolumn_is_primary_key =\n" +
            "CASE\n" +
            "\tWHEN EXISTS (\n" +
            "\tSELECT\n" +
            "\t\t1\n" +
            "\tFROM\n" +
            "\t\tsysobjects\n" +
            "\tWHERE\n" +
            "\t\txtype = 'PK'\n" +
            "\t\tAND name IN ( SELECT name FROM sysindexes WHERE indid IN ( SELECT indid FROM sysindexkeys WHERE id = a.id AND colid = a.colid ) )\n" +
            "\t\t) THEN\n" +
            "\t\t'Y' ELSE ''\n" +
            "\tEND,\n" +
            "\tcolumn_data_type = b.name,\n" +
            "\tcolumn_data_bytes = a.length,\n" +
            "\tcolumn_data_length = COLUMNPROPERTY( a.id, a.name, 'PRECISION' ),\n" +
            "\tcolumn_data_scale = ISNULL( COLUMNPROPERTY( a.id, a.name, 'Scale' ), 0 ),\n" +
            "\tcolumn_data_is_required =\n" +
            "CASE\n" +
            "\t\tWHEN a.isnullable= 1 THEN\n" +
            "\t\t'Y' ELSE ''\n" +
            "\tEND,\n" +
            "\tcolumn_default_value = ISNULL( e.text, '' ),\n" +
//            "\tcolumn_comment = ISNULL( g.[value], '' )\n" +
            "\tcolumn_comment = CONVERT(nvarchar(1000), ISNULL( g.[value], '' ))\n" +
            "FROM\n" +
            "\tsyscolumns a\n" +
            "\tLEFT JOIN systypes b ON a.xusertype= b.xusertype\n" +
            "\tINNER JOIN sysobjects d ON a.id= d.id\n" +
            "\tAND d.xtype= 'U'\n" +
            "\tAND d.name<> 'dtproperties'\n" +
            "\tLEFT JOIN syscomments e ON a.cdefault= e.id\n" +
            "\tLEFT JOIN sys.extended_properties g ON a.id= g.major_id\n" +
            "\tAND a.colid= g.minor_id\n" +
            "\tLEFT JOIN sys.extended_properties f ON d.id= f.major_id\n" +
            "\tAND f.minor_id= 0\n" +
            "where   d.name=?\n" +
            "ORDER BY\n" +
            "\ta.id,\n" +
            "\ta.colorder;";

    @Override
    public String getTableNamePattern(Connection conn) throws SQLException {
        return "%";
    }

    /**
     * 将resultset,主键的resultset装到一个二元组中，并返回
     * @param conn
     * @param tableName
     * @return
     * @throws SQLException
     */
    @Override
    public Pair getColumnAndPrimaryKeyResultSetPair(Connection conn, String tableName) throws SQLException {
        DatabaseMetaData connMetaData = conn.getMetaData();
        String schema = getSchemaPattern(conn);

//        ResultSet rs = connMetaData.getColumns(conn.getCatalog(), schema,tableName, "%");
//        ResultSet pkRs = connMetaData.getPrimaryKeys(conn.getCatalog(),schema,tableName);
        ResultSet rs = connMetaData.getColumns(null,null,tableName,null);
        ResultSet pkRs = connMetaData.getPrimaryKeys(null,null,tableName);

        Pair<ResultSet,ResultSet> pair = Pair.of(rs,pkRs);

        return pair;
    }


    @Override
    public void fillTableEntityNoColumn(TableEntity tableEntity, Connection conn, ResultSet rs) throws SQLException {
        super.fillTableEntityNoColumn(tableEntity,conn,rs);
        ResultSet nrs = getResultSet(conn,tableEntity.getDefKey());
        if(nrs.next()){
            String remarks = nrs.getString("table_comment");
            String defName = remarks;
            String comment = "";

            //如果remark中有分号等分割符，则默认之后的就是注释说明文字
            if(StringKit.isNotBlank(remarks)){
                Pair<String, String> pair = ConnParseKit.parseNameAndComment(remarks);
                defName = pair.getLeft();
                comment = pair.getRight();
            }
            tableEntity.setDefName(defName);
            tableEntity.setComment(comment);
        }
        JdbcKit.close(nrs);
    }

    @Override
    public void fillTableEntity(TableEntity tableEntity, Connection conn) throws SQLException {
        super.fillTableEntity(tableEntity, conn);

        ResultSet nrs = getResultSet(conn,tableEntity.getDefKey());
        while(nrs.next()){
            String columnName = nrs.getString("column_name");
            String columnIsPrimaryKey = nrs.getString("column_is_primary_key");
            String columnDataType = nrs.getString("column_data_type");
            String columnDataLength = nrs.getString("column_data_length");
            String columnDataScale = nrs.getString("column_data_scale");
            String columnDataIsRequired = nrs.getString("column_data_is_required");
            String columnDefaultValue = nrs.getString("column_default_value");
            String columnComment = nrs.getString("column_comment");
            ColumnField field = tableEntity.lookupField(columnName);
            if(field != null){
                String defName = columnComment;
                String comment = "";

                //如果remark中有分号等分割符，则默认之后的就是注释说明文字
                if(StringKit.isNotBlank(columnComment)){
                    Pair<String, String> pair = ConnParseKit.parseNameAndComment(columnComment);
                    defName = pair.getLeft();
                    comment = pair.getRight();
                }
                field.setDefName(defName);
                field.setComment(comment);
                field.setDefaultValue(columnDefaultValue);
            }

        }

        JdbcKit.close(nrs);
    }





    private ResultSet getResultSet(Connection conn,String tableName) throws SQLException {
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        pstmt = conn.prepareStatement(querySQL);
        pstmt.setString(1,tableName);
        rs = pstmt.executeQuery();
        return rs;
    }
}
