
// Global d.3 libraries
import com.dvelop.d3.server.core.D3Interface;
import com.dvelop.d3.server.Document;
import com.dvelop.d3.server.User;
import com.dvelop.d3.server.DocumentTypeAttribute;
import com.dvelop.d3.server.DocumentType;
import com.dvelop.d3.server.RepositoryField;
 
// Libraries to handle the diferent hook types
import com.dvelop.d3.server.Entrypoint;


// Foreign Libraries:
import com.dvelop.d3.server.exceptions.D3Exception
import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.google.gson.JsonParser
import groovy.json.StringEscapeUtils
import org.apache.http.HttpEntity
import org.apache.http.client.methods.CloseableHttpResponse
import org.apache.http.client.methods.HttpGet
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.StringEntity
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClientBuilder
import org.apache.http.util.EntityUtils
import groovy.json.JsonSlurper
import java.nio.charset.StandardCharsets;

public class D3Hooks
{
	@Entrypoint( entrypoint = "hook_insert_exit_20" )
	public int insertExit_20( D3Interface d3, Document doc, String fileDestination, int importOk, User user, DocumentType docType )
	{
		def repo_id = "2e0f1447-d775-51aa-8593-0e0a5d9662aa";
		def baseUri = "https://d3ecm.rau.rau-pforzheim.de";
		def authUsr = "Zyu0W+L0fb6HF0sxPRyPdETFQFBCTOBLb1KcZfli2Sfeepce3TAmYQ22Qq1upRpNAsZou2njb9rkV4c0MRzMdwhPMwEcQCgDWo/VDxsOLkk=&_z_A0V5ayCQR0EAw9MiR-iA1MQAZsBKD5iT_eZeqUR-mqT2T-xMwoBzOA2BvbwjxQEXwJoiuAEGbrxTzJRFYMTVwhHGjwW-p";
		
		//xlog( d3, 2, "repo_id " + repo_id );
		//xlog( d3, 2, "baseUri " + baseUri );
		//xlog( d3, 2, "authUsr " + authUsr );
		
		def empfaenger = [];
		
		def username = getUserIdpId( d3, "D3-User", repo_id, baseUri, authUsr );
		
		//xlog( d3, 2, "username " + username );
		
		
		empfaenger.push( username );
		
		def e = createTask( d3, user, docType, doc, "Neues Dokument", "Es wurde ein neues Dokument importiert: " + doc.id, empfaenger, baseUri, authUsr, repo_id );
		
		
		return 0;
	}

	@Entrypoint( entrypoint = "hook_validate_import_entry_10" )
	public int hook_validate_import_entry_10( D3Interface d3, User user, DocumentType docType, Document doc, String nextcall )
	{
		doc.setStatus( "Freigabe" );
		
		
		if ( isRepoIdInDocType( d3, docType.id, 51 ) ) // Kundenstammdaten
		{
			if ( doc.field[ 6 ] )
			{
				if ( doc.field[ 6 ].indexOf( "|" ) > 0 )
				{
					def werte = doc.field[ 6 ].tokenize( "|" );
					
					if ( werte[ 0 ].length() > 0 ) // Name
					{
						doc.field[ 5 ] = werte[ 0 ].trim();
					}
					
					if ( werte[ 1 ].length() > 0 ) // Strasse
					{
						doc.field[ 7 ] = werte[ 1 ].trim();
					}
					
					if ( werte[ 2 ].length() > 0 ) // PLZ
					{
						doc.field[ 8 ] = werte[ 2 ].trim();
					}
					
					if ( werte[ 3 ].length() > 0 ) // Ort
					{
						doc.field[ 9 ] = werte[ 3 ].trim();
					}
					
					if ( werte[ 4 ].length() > 0 ) // Land
					{
						doc.field[ 10 ] = werte[ 4 ].trim();
					}
					
					if ( werte[ 5 ].length() > 0 ) // Nummer
					{
						doc.field[ 6 ] = werte[ 5 ].trim();
					}
				}
			}
			
			if ( doc.field[ 5 ] )
			{
				if ( doc.field[ 5 ].indexOf( "|" ) > 0 )
				{
					def werte = doc.field[ 5 ].tokenize( "|" );
					
					if ( werte[ 0 ].length() > 0 ) // Name
					{
						doc.field[ 5 ] = werte[ 0 ].trim();
					}
					
					if ( werte[ 1 ].length() > 0 ) // Strasse
					{
						doc.field[ 7 ] = werte[ 1 ].trim();
					}
					
					if ( werte[ 2 ].length() > 0 ) // PLZ
					{
						doc.field[ 8 ] = werte[ 2 ].trim();
					}
					
					if ( werte[ 3 ].length() > 0 ) // Ort
					{
						doc.field[ 9 ] = werte[ 3 ].trim();
					}
					
					if ( werte[ 4 ].length() > 0 ) // Land
					{
						doc.field[ 10 ] = werte[ 4 ].trim();
					}
					
					if ( werte[ 5 ].length() > 0 ) // Nummer
					{
						doc.field[ 6 ] = werte[ 5 ].trim();
					}
				}
			}
			
		}
		
		///////////////////////////
		// eingefügt von CALB/d.velop AG / 2024.06.12 / Setzen des Mandanten bei SAP-Dokumenten (Mandant = 200)
		
		if ( ( isRepoIdInDocType( d3, docType.id, 48 ) ) && ( isRepoIdInDocType( d3, docType.id, 1 ) ) ) // Mandant / Buchungskreis ist in der Dokumentart enthalten
		{
			if ( doc.field[ 39 ] == "200" )
			{
				if ( doc.field[ 1 ] )
				{
					if ( doc.field[ 1 ].indexOf( "|" ) > 0 ) 
					{
						// wird weiter unten behandelt
					}
					else
					{
						def sqlQuery = "SELECT mandant_name FROM [D3ServiceT].[dbo].[dv_mandant] where mandant_nr = '" + doc.field[ 1 ] + "'";
						
						def sql = groovy.sql.Sql.newInstance( "jdbc:sqlserver://d3sql;databaseName=D3ServiceT", 'd3DBAdminT', 'Dvelop1!', 'com.microsoft.sqlserver.jdbc.SQLServerDriver' );
						
						def resultRows = sql.rows( sqlQuery );
						
						doc.field[ 39 ] = resultRows[ 0 ].mandant_name;
					}
				}
				
			}
		}
		
		// Einfügung Ende / Setzen des Mandanten bei SAP-Dokumenten (Mandant = 200)
		///////////////////////////
		
		if ( isRepoIdInDocType( d3, docType.id, 31 ) ) // Materialstammdaten, ID 31 => Materialnummer
		{
			for ( int i = 1; i <= Integer.valueOf( d3.config.value( "CUR_60ER_FIELD_NR" ) ); i++ )
			{
				if ( doc.field[ 61 ][ i ] )
				{
					if ( doc.field[ 61 ][ i ].indexOf( "|" ) > 0 )
					{
						def wert	= doc.field[ 61 ][ i ].tokenize( "|" );
						def ziel	= "";
						
						if ( wert[ 0 ].length() > 0 )
						{
							doc.field[ 61 ][ i ]	= wert[ 0 ].trim(); // Materialnummer
						}
						
						if ( wert[ 1 ] )
						{
							if ( wert[ 1 ].length() > 0 )
							{
								ziel	= wert[ 1 ].trim(); // Materianbezeichnung
							}
						}
						
						doc.field[ 65 ][ i ]	= ziel;
						ziel					= "";
						
						
						if ( wert[ 2 ] )
						{
							if ( wert[ 2 ].length() > 0 )
							{
								ziel	= wert[ 2 ].trim(); // Produkthierarchie
							}
						}
						
						doc.field[ 66 ][ i ]	= ziel;
						ziel					= "";
						
						if ( wert[ 3 ] )
						{
							if ( wert[ 3 ].length() > 0 )
							{
								ziel	= wert[ 3 ].trim(); // Kundenartikelnummer
							}
						}
						
						doc.field[ 67 ][ i ]	= ziel;
					}
				}
			}
		}
		
		if ( isRepoIdInDocType( d3, docType.id, 1 ) ) // Mandantenstammdaten (Buchungskreis, Firma)
		{
			// Wir schauen, was angegeben ist. Der Buchungskreis wird zuerst ausgewertet und schlägt den Mandantnamen (Feld Firma) (der nur ausgewertet wird, falls
			// kein Buchungskreis angegeben wurde).
			
			if ( doc.field[ 1 ] )
			{
				if ( doc.field[ 1 ].indexOf( "|" ) > 0 )
				{
					def werte = doc.field[ 1 ].tokenize( "|" );
					
					if ( werte[ 0 ].length() > 0 ) // Nummer
					{
						doc.field[ 1 ] = werte[ 0 ].trim();
					}
					
					if ( werte[ 1 ] )
					{
						if ( werte[ 1 ].length() > 0 ) // Name
						{
							doc.field[ 39 ] = werte[ 1 ].trim();
						}
					}
				}
				else
				{
					if ( ! doc.field[ 39 ] )
					{
						// Buchungskreis gefüllt, Firma aber nicht, d.h. offenbar ein Beleg aus SAP (=> da wird nur der Buchungskreis angegeben)
						// Firma wird aus Stammdaten gefüllt
						
						def sql = groovy.sql.Sql.newInstance( "jdbc:sqlserver://d3sql;databaseName=D3ServiceT", 'd3DBAdminT', 'Dvelop1!', 'com.microsoft.sqlserver.jdbc.SQLServerDriver' );
						
						def row = sql.firstRow( "SELECT mandant_name FROM [D3ServiceT].[dbo].[dv_mandant] where mandant_nr = '" + doc.field[ 1 ] + "'" );
						
						if ( row )
						{
							doc.field[ 39 ] = row.mandant_name;
						}
					}
				}
			}
			else
			{
				if ( doc.field[ 39 ] )
				{
					if ( doc.field[ 39 ].indexOf( "|" ) > 0 )
					{
						def werte = doc.field[ 39 ].tokenize( "|" );
						
						if ( werte[ 0 ].length() > 0 ) // Nummer
						{
							doc.field[ 1 ] = werte[ 0 ].trim();
						}
						
						if ( werte[ 1 ] )
						{
							if ( werte[ 1 ].length() > 0 ) // Name
							{
								doc.field[ 39 ] = werte[ 1 ].trim();
							}
						}
					}
				}
			}
		}
		
		
		
		
		
		return 0;
	}
	
	@Entrypoint( entrypoint = "hook_validate_update_entry_10" )
	public int hook_validate_update_entry_10( D3Interface d3, User user, DocumentType docType, Document doc, String nextcall )
	{
		def ret = hook_validate_import_entry_10( d3, user, docType, doc, nextcall );
		
		return ret;
	}
	
	@Entrypoint( entrypoint = "hook_upd_attrib_entry_20" )
	public int hookUpdAttribEntry20(D3Interface d3, Document doc, User user, DocumentType docType, DocumentType docTypeNew)
	{
		d3.log.error("START | hookUpdAttribEntry20")

		// temporäres Objekt holen, um zu prüfen, das sich Eigenschaften geändert haben
		def oldDocAttributes = d3.archive.getDocument(doc.id());
		
		def ergebnis = hook_validate_update_entry_10( d3, user, docTypeNew, doc, "" );
		
		d3.log.error("ENDE | hookUpdAttribEntry20")
		return 0;
	}
	
	@Entrypoint( entrypoint = "hook_insert_entry_10" )
	public int hookInsertEntry10(D3Interface d3, User user, DocumentType docType, Document doc)
	{
		
		d3.log.info("START | hookInsertEntry10 ");
		
		///////////////////////////
		// eingefügt von CALB/d.velop AG / 2024.06.11 / Versionierung von Fertigungsaufträgen
		
		
		if ( ( docType.id == "DFAUF" ) || ( docType.id == "DPEIN" ) || ( docType.id == "DMPRO" ) || ( docType.id == "DPZEU" ) )
		{
			
			if ( doc.field[ 16 ] )
			{
				def sqlQuery = "select doku_id from firmen_spezifisch where kue_dokuart = '" + docType.id + "' and dok_dat_feld_16 = '" + doc.field[ 16 ] + "'";
				
				def treffer = d3.sql.executeAndGet( (String) sqlQuery );
				
				if ( treffer.size() > 1 )
				{
					d3.log.error( "Anzahl Treffer: " + treffer.size() + " => es gibt mehr als ein Dokument fuer Auftragsnummer " + doc.field[ 16 ] + " in der Dokumentart " + docType.id + " !" );
					return -120;
				}
				
				if ( treffer.size() == 1 )
				{
					
					sqlQuery = "select zeich_nr, var_nr from phys_datei where doku_id = '" + treffer[ 0 ].doku_id + "'";
					treffer = d3.sql.executeAndGet( (String) sqlQuery );
					
					if ( treffer.size() > 0 )
					{
						d3.log.info( "Fertigungsauftrag gefunden, setze Dokumentnummer " + doc.number + " bei Auftragsnummer " + doc.field[ 16 ] );
						doc.number = treffer[ 0 ].zeich_nr;
					}
				}
			}
		}
		
		// Einfügung Ende / Versionierung von Fertigungsaufträgen
		///////////////////////////
		
		
		
		d3.log.info("ENDE | hookInsertEntry10 ");
		return 0;
	}
	
	public String getUserIdpId( D3Interface d3, String UserName, String repo_id, String baseUri, String authUserApiKey )
	{
		
		CloseableHttpClient client = HttpClientBuilder.create( ).build( );
		String userId;
		
		try
		{
			
			HttpGet get = new HttpGet( baseUri + "/identityprovider/scim/users?filter=userName%20eq%20rau%5C" + UserName );
			
			//JSON Inhalt
			get.addHeader( "authorization", "Bearer " + authUserApiKey );
			get.addHeader( "origin", baseUri );
			get.addHeader( "Accept", "application/json" );
			
			CloseableHttpResponse response = client.execute( get );
			
			try
			{
				def statusCode = response.getStatusLine( ).getStatusCode( );
				
				if( statusCode != 200 && statusCode != 201 ){
					d3.log.error("getUserIdpId -> Error while trying to read user " + UserName + " status code: " + statusCode );

					HttpEntity re = response.getEntity();
					InputStream errStream = re.getContent();
					String errContent = "";

					if( errStream != null && errStream.available() > 0 ){
						errContent = IOUtils.toString(errStream, StandardCharsets.UTF_8);
					}

					d3.log.error("getUserIdpId -> Error while trying to read user " + UserName + " response line: " + errContent);
					
					xlog( d3, 2, "User-ID nicht gefunden": errContent );
					
					return "";
				}
				
				HttpEntity entity = response.getEntity( );
				
				String json = EntityUtils.toString( entity, StandardCharsets.UTF_8 );
				
				def jsonSlurper = new JsonSlurper();
				
				def returnwert = jsonSlurper.parseText( json );
				
				userId = returnwert.resources.id[ 0 ];
				
				
			}
			finally
			{
				response.close();
			}
		}
		catch ( IOException e )
		{
			e.printStackTrace();
		}
		finally
		{
			try
			{
				client.close();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		
		xlog( d3, 2, "gefundene User-ID: " + userId );
		
		return userId;
		
	}
	
	
	public int xlog( D3Interface d3, int loglevel, String logtext )
	{
		def logdatei		= "d:\\d3\\logs\\d3hooklog.txt";
		def g_loglevel	  = 5;
		def g_logdirect	 = "BEIDE";  // BEIDE oder D3LOG oder DATEI
		def date			= new Date();
		def zeitstempel	 = date.format( "yyyy.MM.dd HH:mm:ss", TimeZone.getTimeZone('CET') );
		def loglevel_lang	   = "[INFO ]";
		
		
		
		
		
		if ( loglevel <= g_loglevel )
		{
			switch ( loglevel )
			{
				case 1:
					loglevel_lang   = "[FATAL]";
					
					if ( ( g_logdirect == "D3LOG" ) || ( g_logdirect == "BEIDE" ) )
					{
						d3.log.critical( logtext );
					}
					break;
				case 2:
					loglevel_lang   = "[ERROR]";
					
					if ( ( g_logdirect == "D3LOG" ) || ( g_logdirect == "BEIDE" ) )
					{
						d3.log.error( logtext );
					}
					break;
				case 3:
					loglevel_lang   = "[WARN ]";
					
					if ( ( g_logdirect == "D3LOG" ) || ( g_logdirect == "BEIDE" ) )
					{
						d3.log.warn( logtext );
					}
					break;
				case 4:
					loglevel_lang   = "[INFO ]";
					
					if ( ( g_logdirect == "D3LOG" ) || ( g_logdirect == "BEIDE" ) )
					{
						d3.log.info( logtext );
					}
					break;
				case 5:
					loglevel_lang   = "[DEBUG]";
					// Da die d.3 Server i.d.R. nicht im Debug-Modus laufen, erscheinen DEBUG-Meldungen nicht im Log.
					if ( ( g_logdirect == "D3LOG" ) || ( g_logdirect == "BEIDE" ) )
					{
						d3.log.debug( logtext );
					}
					break;
			}
			
		}
		
		if ( ( g_logdirect == "DATEI" ) || ( g_logdirect == "BEIDE" ) )
		{
			new File( logdatei ).append( zeitstempel + " " + loglevel_lang + " " + logtext + "\n", "UTF8" );
		}
		
		
		return 0;
	}





	public static int createTask( D3Interface d3, User user, DocumentType docType, Document doc, String subject, String description, ArrayList<String> assignees, String baseUri, String authUsr, String repo_id )
	{
		d3.log.info( "createTask !" );
		String assigneesString = "";
		
		assignees.each
		{
			assigneesString = assigneesString + "\"${it}\",";
		}
		
		if ( assigneesString.length() > 0 )
		{
			assigneesString = assigneesString.substring(0, assigneesString.length()-1);
		}
		
		CloseableHttpClient client = HttpClientBuilder.create( ).build( );

		try
		{
			
			UUID uuid = UUID.randomUUID();
			String randomUUIDString = uuid.toString();
			
			//Post Task
			HttpPost post = new HttpPost( baseUri + "/task/tasks" );
			
			def ddf11;
			if ( doc.field[ 11 ] == null )
			{
				ddf11 = "";
			}
			else
			{
				ddf11 = doc.field[ 11 ];
			}
			
			def ddf12;
			if ( doc.field[ 12 ] == null )
			{
				ddf12 = "";
			}
			else
			{
				ddf12 = doc.field[ 12 ];
			}
			
			//JSON Inhalt
			
			def lJsonString = """{
								"subject" : "${subject}",
									"description" : "${description}",
								"assignees" : [${assigneesString}],
									"correlationKey" : "${randomUUIDString}",
									"context" : {
											"key"  : "returnProcess",
											"type" : "process",
											"name" : "Import in Kundenbestellung"
									},
									"metadata" : [
											{
												"key" : "verkaeuferorg",
												"caption" : "Verkaeuferorganisation",
												"values" : ["${ddf11}"]
											},
											{
												"key" : "verkaeufergruppe",
												"caption" : "Verkaeufergruppe",
												"values" : ["${ddf12}"]
											}
									],
									"_links" : {
											"attachment" : { "href": "/dms/r/${repo_id}/o2/${doc.id()}"}
									}
								}""";
			
			StringEntity params = new StringEntity( lJsonString, StandardCharsets.UTF_8 );
			params.setContentType("application/json");
			
			post.addHeader("authorization", "Bearer ${authUsr}");
			post.addHeader("content-type", "application/json");
			post.addHeader("origin", baseUri );
			post.setEntity( params );
			CloseableHttpResponse response = client.execute( post );

			try
			{
				def statusCode = response.getStatusLine( ).getStatusCode( );
				
				if( statusCode != 200 && statusCode != "200" && statusCode != 201 && statusCode != "201" )
				{
					HttpEntity re = response.getEntity();
					def lErrMsg = "createOfficeTaskFinished - Error while trying to create Task! Status Code: " + statusCode + " / Response: " + re.getContent().text;
					d3.log.info( "createOfficeTaskFinished" + "" + lErrMsg + " -> " + lJsonString);
				}
			}
			finally
			{
				response.close();
			}
		}
		catch ( Exception e )
		{
			d3.log.error( "createOfficeTaskFinished" + "" + e.getMessage() );
		}
		finally
		{
			client.close();
		}
		
		return 0;
	}

	
	private boolean isRepoIdInDocType( D3Interface d3, String docTypeShort, int repoId )
	{
		boolean isRepoIdInDocType = false;
		try
		{
			Document docTemp = d3.archive.newDocument();
			docTemp.setType( docTypeShort );
			DocumentType docType = docTemp.getType();
			if ( docTemp != null && docType != null )
			{
				for ( int i = 1; i <= 89; i++ )
				{
					try
					{
						DocumentTypeAttribute docTypeAttrib = docTemp.getType().getField().getAt( i );
						if ( docTypeAttrib != null )
						{
							RepositoryField repoField = docTypeAttrib.getRepositoryField();
							if ( repoField != null )
							{
								String currRepoId = repoField.getId();
								if ( currRepoId != null )
								{
									int currRepoIdInt = Integer.valueOf( currRepoId );
									if ( currRepoIdInt == repoId )
									{
										isRepoIdInDocType = true;
										break;
									}
								}
							}
						}
					}
					catch ( Exception eField )
					{
						//nix
					}
				}
			}
		}
		catch ( Exception e )
		{
			// wieder nix
		}
		
		//d3.log.error( "Nachricht: " + isRepoIdInDocType );
		
		return isRepoIdInDocType;
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	

}

