package ibase.utility.training;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.rmi.RemoteException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;

import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

import ibase.scheduler.utility.interfaces.Schedule;
import ibase.utility.BaseLogger;
import ibase.utility.E12GenericUtility;
import ibase.utility.UserInfoBean;
import ibase.webitm.ejb.ActionHandlerEJB;
import ibase.webitm.ejb.DBAccessEJB;
import ibase.webitm.utility.ITMException;

public class ScheduledSFTPUploader implements Schedule {
	
	E12GenericUtility e12GenericUtility = new E12GenericUtility();
	UserInfoBean userInfoGlobal = new UserInfoBean();
	DBAccessEJB dbAccessEJB = new DBAccessEJB();
	
	NodeList argNodeList = null;
	boolean Bankcodetobool = false;
	String BankCode = "";
	String payIntArgsStr = "";

	JsonObject payIntArgsJSON = parseJsonString(payIntArgsStr);

	// get values from json

	String bankIntegrationXMLFilePath = getValueFromJson(payIntArgsJSON, "private_key_file_path");

	public static JsonObject parseJsonString(String jsonString) {
		JsonReader jsonReader = Json.createReader(new StringReader(jsonString));
		return jsonReader.readObject();
	}

	// Method to convert a JSON string to a JsonObject
	public static String getValueFromJson(JsonObject jsonObject, String key) {
		if (jsonObject.containsKey(key)) {
			return jsonObject.getString(key);
		} else {
			return null; // or throw an exception, handle accordingly
		}
	}

	@Override
	public String schedule(HashMap arg0) throws Exception {
		return null;
	}

	@Override
	public String schedule(String name) throws Exception {
		BaseLogger.log("2", null, null, "ScheduledSFTPUploader calling------------------");
		BaseLogger.log("3", null, null, "name::[ " + name + " ]");

		Document schdulerInfoDocument = e12GenericUtility.parseString(name);
		UserInfoBean userInfo = new UserInfoBean(e12GenericUtility.serializeDom(
				schdulerInfoDocument.getElementsByTagName("USERINFOXML").item(0).getChildNodes().item(0)));
		userInfoGlobal = userInfo;
		argNodeList = schdulerInfoDocument.getElementsByTagName("ACTUALPARAMETER");

		for (int i = 0; i < argNodeList.getLength(); i++) {
			Node childNode = argNodeList.item(i);
			if (childNode.getNodeType() != Node.ELEMENT_NODE) {
				continue;
			}
			if (childNode != null) {
				System.out.println("childNode=[" + childNode + "]");
				Bankcodetobool = isParameterPresent(childNode, "Bank_Code");

				if (Bankcodetobool) {
					if (childNode.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase("Bank_Code")) {
						BankCode = E12GenericUtility.checkNull(childNode.getFirstChild().getNodeValue());
						System.out.println("BankCode = [" + BankCode + "]");
					}
				}
			}

			scheduledSFTPUploading(userInfo, BankCode);
		}

		return null;
	}

	@Override
	public String schedulePriority(String arg0) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	private boolean isParameterPresent(Node childNode, String attribName) throws ITMException {
		boolean attribFound = false;
		try {
			System.out.println("attribFound test= [" + childNode.getAttributes() + "]");
			if (childNode != null && childNode.getAttributes() != null) {
				System.out.println(
						"attribFound name= [" + childNode.getAttributes().getNamedItem("name").getNodeValue() + "]");
				if (childNode.getAttributes().getNamedItem("name").getNodeValue().equalsIgnoreCase(attribName)) {
					attribFound = true;
				}
			}

		} catch (Exception e) {
			throw new ITMException(e);
		}
		System.out.println("attribFound = [" + attribFound + "]");
		return attribFound;
	}

	public void scheduledSFTPUploading(UserInfoBean userInfo, String bankCode) {

		String payIntArgs = "";

		try {
			payIntArgs = dbAccessEJB.getDBColumnValue("BANK", "PAY_INT_ARGS", "BANK_CODE  = '" + bankCode + "'",
					userInfo.getTransDB());
			BaseLogger.log("3", null, null, "Value of payIntArgs... [" + payIntArgs + "]");

		} catch (RemoteException | ITMException e) {
			e.printStackTrace();
		}
	}

	public static void uploadFiles(String bankIntegrationXMLFilePath, String remoteDirectoryPath,
			JsonObject payIntArgsJSON) {
		final String username = payIntArgsJSON.getString("username");
		final String hostName = payIntArgsJSON.getString("host_name");
		final int port = Integer.parseInt(payIntArgsJSON.getString("port"));
		final String privatekeyfilePath = payIntArgsJSON.getString("private_key_file_path");

		JSch jsch = new JSch();

		Session session = null;
		ChannelSftp channelSftp = null;

		try {
			jsch.addIdentity(privatekeyfilePath);

			session = jsch.getSession(username, hostName, port);
			session.setConfig("StrictHostKeyChecking", "no");
			session.connect();

			channelSftp = (ChannelSftp) session.openChannel("sftp");
			channelSftp.connect();

			File localDirectory = new File(bankIntegrationXMLFilePath);
			File[] files = localDirectory.listFiles();

			if (files != null) {
				for (File file : files) {
					if (file.isFile()) {
						String remoteFilePath = remoteDirectoryPath + "/" + file.getName();
						try (InputStream inputStream = new FileInputStream(file)) {
							// Create the remote directory if it doesn't exist
							String remoteDirectory = remoteFilePath.substring(0, remoteFilePath.lastIndexOf("/"));
							createRemoteDirectory(channelSftp, remoteDirectory);

							// Upload the file to the SFTP server
							channelSftp.put(inputStream, remoteFilePath);

							System.out.println("File '" + file.getName() + "' uploaded successfully.");

							// Move the file to the Archive Folder with date-wise subfolder
							moveFileToArchive(file);
						} catch (IOException | SftpException e) {
							e.printStackTrace();
						}
					}
				}
			}

			System.out.println("All files uploaded successfully.");
		} catch (JSchException e) {
			e.printStackTrace();
		} finally {
			if (channelSftp != null && channelSftp.isConnected()) {
				channelSftp.disconnect();
			}
			if (session != null && session.isConnected()) {
				session.disconnect();
			}
		}
	}

	private static void moveFileToArchive(File file) {
		// Create the archive directory if it doesn't exist
		String archiveDirectoryPath = "/wildfly/BankIntegration/UNS_HSBC/XML_files";
		File archiveDir = new File(archiveDirectoryPath);
		if (!archiveDir.exists()) {
			archiveDir.mkdirs();
			System.out.println("Archive directory created: " + archiveDir.getAbsolutePath());
		}

		// Create a date-wise subfolder in the archive directory
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		String dateFolderName = dateFormat.format(new Date());
		File dateFolder = new File(archiveDir, dateFolderName);
		if (!dateFolder.exists()) {
			dateFolder.mkdir();
		}

		// Move the file to the date-wise subfolder in the archive directory
		Path destination = new File(dateFolder, file.getName()).toPath();
		try {
			Files.move(file.toPath(), destination, StandardCopyOption.REPLACE_EXISTING);
			System.out.println("File moved to archive: " + destination.toAbsolutePath());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void createRemoteDirectory(ChannelSftp channelSftp, String directory) throws SftpException {
		try {
			channelSftp.cd(directory);
		} catch (SftpException e) {
			// Directory does not exist, so create it
			String[] dirs = directory.split("/");
			for (String dir : dirs) {
				if (dir.length() > 0) {
					try {
						channelSftp.cd(dir);
					} catch (SftpException ex) {
						channelSftp.mkdir(dir);
						channelSftp.cd(dir);
					}
				}
			}
		}
	}

}
