import static com.kms.katalon.core.checkpoint.CheckpointFactory.findCheckpoint
import static com.kms.katalon.core.testcase.TestCaseFactory.findTestCase
import static com.kms.katalon.core.testdata.TestDataFactory.findTestData
import static com.kms.katalon.core.testobject.ObjectRepository.findTestObject
import static com.kms.katalon.core.testobject.ObjectRepository.findWindowsObject
import com.kms.katalon.core.checkpoint.Checkpoint as Checkpoint
import com.kms.katalon.core.cucumber.keyword.CucumberBuiltinKeywords as CucumberKW
import com.kms.katalon.core.mobile.keyword.MobileBuiltInKeywords as Mobile
import com.kms.katalon.core.model.FailureHandling as FailureHandling
import com.kms.katalon.core.testcase.TestCase as TestCase
import com.kms.katalon.core.testdata.TestData as TestData
import com.kms.katalon.core.testng.keyword.TestNGBuiltinKeywords as TestNGKW
import com.kms.katalon.core.testobject.TestObject as TestObject
import com.kms.katalon.core.webservice.keyword.WSBuiltInKeywords as WS
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
import com.kms.katalon.core.windows.keyword.WindowsBuiltinKeywords as Windows
import internal.GlobalVariable as GlobalVariable

/**
 * Read GMail 2FA Code Test Case
 * Tags: AUTH, P1, SMOKE, 2FA, API
 * 
 * This test verifies that the system can read 2FA validation codes from Gmail.
 * It connects to Gmail via IMAP and retrieves the latest 2FA email.
 */

import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;
import java.util.Date;
import java.text.SimpleDateFormat;

import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.search.SubjectTerm;
import javax.mail.internet.MimeMessage;
import java.io.ByteArrayOutputStream;

// Configure SSL/TLS properties
Properties props = new Properties();
props.put("mail.store.protocol", "imaps");
props.put("mail.imaps.host", GlobalVariable.imap_host);
props.put("mail.imaps.port", GlobalVariable.imap_port);
props.put("mail.imaps.ssl.enable", "true");
props.put("mail.imaps.ssl.trust", "*");

// Force TLS 1.2 or higher
props.put("mail.imaps.ssl.protocols", "TLSv1.2 TLSv1.3");

// Configure cipher suites (optional - let Java choose appropriate ones)
// props.put("mail.imaps.ssl.ciphersuites", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384");

// Additional security settings
props.put("mail.imaps.ssl.checkserveridentity", "false");
props.put("mail.imaps.ssl.trust", GlobalVariable.imap_host);

// Create session with debug enabled (optional - for troubleshooting)
Session session = Session.getInstance(props, null);
session.setDebug(false); // Set to false in production

try {
    Store store = session.getStore("imaps");
    store.connect(GlobalVariable.imap_host, GlobalVariable.imap_user, GlobalVariable.imap_pass);
    
    Folder inbox = store.getFolder("inbox");
    inbox.open(Folder.READ_ONLY);
	
	// Search for latest email with specific criteria
	SubjectTerm searchTerm = new SubjectTerm("2FA Validation");
	
	// Parse the login date from GlobalVariable
	SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
	Date loginDate = null;
	try {
		loginDate = dateFormat.parse(GlobalVariable.LoginDate);
	} catch (Exception parseException) {
		System.err.println("Error parsing LoginDate: " + parseException.getMessage());
		System.err.println("LoginDate value: " + GlobalVariable.LoginDate);
	}
	
	// Retry logic - try for up to 30 seconds
	long startTime = System.currentTimeMillis();
	long maxWaitTime = 30000; // 30 seconds in milliseconds
	long waitInterval = 5000; // 5 seconds between retries
	Message latestMessage = null;
	String messageContent = "";
	
	while (System.currentTimeMillis() - startTime < maxWaitTime) {
		Message[] messages = inbox.search(searchTerm);
		
		if (messages.length > 0) {
			// Find the newest message that is newer than the login date
			Date latestDate = null;
			
			for (Message message : messages) {
				Date messageDate = message.getSentDate();
				if (messageDate != null && loginDate != null) {
					// Check if message is newer than login date
					if (messageDate.after(loginDate)) {
						// Check if this is the newest message among those newer than login date
						if (latestDate == null || messageDate.after(latestDate)) {
							latestDate = messageDate;
							latestMessage = message;
						}
					}
				}
			}
			
			// If no message found newer than login date, fall back to the newest message overall
			if (latestMessage == null) {
				System.out.println("No messages found newer than login date. Using newest message overall.");
				for (Message message : messages) {
					Date messageDate = message.getSentDate();
					if (messageDate != null && (latestDate == null || messageDate.after(latestDate))) {
						latestDate = messageDate;
						latestMessage = message;
					}
				}
			}
			
			// If still no valid message found, use the last message in array
			if (latestMessage == null) {
				latestMessage = messages[messages.length - 1];
			}
			
			// Try to extract message content
			try {
				if (latestMessage instanceof MimeMessage) {
					MimeMessage mimeMessage = (MimeMessage) latestMessage;
					
					// Try to get the text content directly
					if (mimeMessage.isMimeType("text/plain")) {
						messageContent = (String) mimeMessage.getContent();
					} else if (mimeMessage.isMimeType("multipart/alternative") || 
							   mimeMessage.isMimeType("multipart/mixed")) {
						// For multipart messages, get the text part
						javax.mail.Multipart multipart = (javax.mail.Multipart) mimeMessage.getContent();
						for (int i = 0; i < multipart.getCount(); i++) {
							javax.mail.Part part = multipart.getBodyPart(i);
							if (part.isMimeType("text/plain")) {
								messageContent = (String) part.getContent();
								break;
							}
						}
					}
				} else {
					// Fallback for non-MimeMessage
					messageContent = latestMessage.getContent().toString();
				}
			} catch (Exception contentException) {
				System.err.println("Error getting message content: " + contentException.getMessage());
				// Try alternative approach - get raw message
				try {
					ByteArrayOutputStream baos = new ByteArrayOutputStream();
					latestMessage.writeTo(baos);
					String rawMessage = baos.toString();
					
					// Extract text content from raw message (simplified)
					int textStart = rawMessage.indexOf("Content-Type: text/plain");
					if (textStart != -1) {
						int contentStart = rawMessage.indexOf("\r\n\r\n", textStart);
						if (contentStart != -1) {
							messageContent = rawMessage.substring(contentStart + 4);
							// Remove any remaining headers or boundaries
							int boundaryIndex = messageContent.indexOf("--");
							if (boundaryIndex != -1) {
								messageContent = messageContent.substring(0, boundaryIndex);
							}
						}
					}
				} catch (Exception rawException) {
					System.err.println("Error getting raw message: " + rawException.getMessage());
				}
			}
			
			// Parse the 2FA code from the message content
			if (messageContent && messageContent.length() > 0) {
				String[] lines = messageContent.split('\n');
				for (String line : lines) {
					if (line.contains("Your 2FA code is:")) {
						String[] parts = line.split(':');
						if (parts.length > 1) {
							String code = parts[1].trim();
							System.out.println("2FA Code found: " + code);
							// You can return the code here if needed
							return code;
						}
					}
				}
			}
		}
		
		// If we haven't found a valid 2FA code yet, wait and try again
		long elapsedTime = System.currentTimeMillis() - startTime;
		long remainingTime = maxWaitTime - elapsedTime;
		
		if (remainingTime > waitInterval) {
			System.out.println("2FA email not found yet. Waiting 5 seconds before retry... (Elapsed: " + (elapsedTime/1000) + "s)");
			Thread.sleep(waitInterval);
		} else {
			System.out.println("Timeout reached. No 2FA email found within 30 seconds.");
			break;
		}
	}
	
	if (messageContent && messageContent.length() > 0) {
		System.out.println("Could not extract 2FA code from message content");
	} else {
		System.out.println("No messages found with subject '2FA Validation' within 30 seconds");
	}
    
    inbox.close(true);
    store.close();
    
} catch (Exception e) {
    System.err.println("Error connecting to Gmail IMAP: " + e.getMessage());
    e.printStackTrace();
}