// https://issues.jboss.org/browse/TEIID-2771
// https://issues.jboss.org/browse/TEIID-2181
package org.teiid.jdbc;

import static org.junit.jupiter.api.Assertions.*;

import java.io.ByteArrayInputStream;
import java.sql.SQLException;
import java.util.Arrays;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.teiid.adminapi.impl.VDBImportMetadata;
import org.teiid.core.util.UnitTestUtil;
import org.teiid.jdbc.FakeServer.DeployVDBParameter;


@SuppressWarnings("nls")
public class TestVDBMerge extends AbstractMMQueryTestCase {
	
	private static final String VDB1 = "PartsSupplier"; //$NON-NLS-1$
	private static final String VDB2 = "QT_Ora9DS"; //$NON-NLS-1$

	private FakeServer server;
    
    @BeforeEach public void setup() throws Exception {
    	server = new FakeServer(true);
    	server.setThrowMetadataErrors(false); //test vdb has errors
    }
    
    @AfterEach public void teardown() throws Exception {
    	server.stop();
    }
    
	@Test
    public void testMerge() throws Throwable {
		
		server.deployVDB(VDB1, UnitTestUtil.getTestDataPath() + "/PartsSupplier.vdb");
		this.internalConnection = server.createConnection("jdbc:datavirtuality:" + VDB1);

		execute("select * from tables where schemaname ='PartsSupplier'"); //$NON-NLS-1$
		TestMMDatabaseMetaData.compareResultSet("TestVDBMerge/merge.test", this.internalResultSet);

		execute("select * from tables where schemaname='BQT1'"); //$NON-NLS-1$
		TestMMDatabaseMetaData.compareResultSet("TestVDBMerge/merge.before", this.internalResultSet);

		this.internalConnection.close();

       server.deployVDB(VDB2, UnitTestUtil.getTestDataPath()+"/QT_Ora9DS_1.vdb");

       DeployVDBParameter param = new DeployVDBParameter(null, null);
       VDBImportMetadata vdbImport = new VDBImportMetadata();
       vdbImport.setName(VDB2);
       param.vdbImports = Arrays.asList(vdbImport);
       server.removeVDB(VDB1);
       server.deployVDB(VDB1, UnitTestUtil.getTestDataPath()+"/PartsSupplier.vdb", param);
       
       this.internalConnection = server.createConnection("jdbc:datavirtuality:"+VDB1);

		execute("select * from tables where schemaname='BQT1' order by name"); //$NON-NLS-1$
		TestMMDatabaseMetaData.compareResultSet("TestVDBMerge/merge.after", this.internalResultSet);
	}

	@Test
	public void testMergeWithEmptyVDB() throws Exception {
		server.deployVDB("empty", UnitTestUtil.getTestDataPath() + "/empty.vdb");
    	this.internalConnection = server.createConnection("jdbc:datavirtuality:empty");
    
		String[] expectedBefore = {
     		   "VDBName[string]    SchemaName[string]    Name[string]    Type[string]    NameInSource[string]    IsPhysical[boolean]    SupportsUpdates[boolean]    UID[string]    Cardinality[long]    Description[string]    OriginalDescription[string]    IsSystem[boolean]    IsMaterialized[boolean]    OID[integer]",
        };

		execute("select * from tables where schemaname ='BQT1'"); //$NON-NLS-1$
		TestMMDatabaseMetaData.compareResultSet("TestVDBMerge/mergeEmpty.before", this.internalResultSet);
		this.internalConnection.close();

        server.deployVDB(VDB2, UnitTestUtil.getTestDataPath()+"/QT_Ora9DS_1.vdb");
        
        DeployVDBParameter param = new DeployVDBParameter(null, null);
        VDBImportMetadata vdbImport = new VDBImportMetadata();
        vdbImport.setName(VDB2);
        param.vdbImports = Arrays.asList(vdbImport);
        server.undeployVDB("empty");
        server.deployVDB("empty", UnitTestUtil.getTestDataPath() + "/empty.vdb", param);

		this.internalConnection = server.createConnection("jdbc:datavirtuality:empty");
		execute("select * from tables where schemaname='BQT1'"); //$NON-NLS-1$
		TestMMDatabaseMetaData.compareResultSet("TestVDBMerge/mergeEmpty.after", this.internalResultSet);
	}

	@Test public void testMergeWithPolicies() throws Exception {
		server.deployVDB(new ByteArrayInputStream(new String("<vdb name=\"role-1\" version=\"1\">"
				+ "<model name=\"myschema\" type=\"virtual\">"
				+ "<metadata type = \"DDL\"><![CDATA[CREATE VIEW vw as select 'a' as col;]]></metadata></model>"
				+ "<data-role name=\"y\" any-authenticated=\"true\"/></vdb>").getBytes()));
		this.internalConnection = server.createConnection("jdbc:datavirtuality:role-1");

		try {
			execute("select * from vw"); //$NON-NLS-1$
			fail("should not be authorized");
		} catch (SQLException e) {

		}

		server.deployVDB(new ByteArrayInputStream(new String("<vdb name=\"role-2\" version=\"1\">"
				+ "<import-vdb name=\"role-1\" version=\"1\"/>"
				+ "</vdb>").getBytes()));
		this.internalConnection = server.createConnection("jdbc:datavirtuality:role-2");

		try {
			execute("select * from vw"); //$NON-NLS-1$
			fail("should not be authorized");
		} catch (SQLException e) {

		}

		server.deployVDB(new ByteArrayInputStream(new String("<vdb name=\"role-3\" version=\"1\">"
				+ "<import-vdb name=\"role-1\" version=\"1\" import-data-policies=\"false\"/>"
				+ "</vdb>").getBytes()));
		this.internalConnection = server.createConnection("jdbc:datavirtuality:role-3");

		execute("select * from vw"); //$NON-NLS-1$
	}
}
