// Path: src/main/java/com/frameworkium/core/ui/UITestLifecycle.java
// public class UITestLifecycle {
// 
//   private static final Duration DEFAULT_TIMEOUT = Duration.of(10, SECONDS);
// 
//   private static final ThreadLocal<ScreenshotCapture> capture = new ThreadLocal<>();
//   private static final ThreadLocal<Wait<WebDriver>> wait = new ThreadLocal<>();
//   private static final ThreadLocal<UITestLifecycle> uiTestLifecycle =
//       ThreadLocal.withInitial(UITestLifecycle::new);
// 
//   private static DriverLifecycle driverLifecycle;
//   private static String userAgent;
// 
//   /**
//    * @return a ThreadLocal instance of {@link UITestLifecycle}
//    */
//   public static UITestLifecycle get() {
//     return uiTestLifecycle.get();
//   }
// 
//   /**
//    * @return check to see if class initialised correctly.
//    */
//   public boolean isInitialised() {
//     return wait.get() != null;
//   }
// 
//   /**
//    * Run this before the test suite to initialise a pool of drivers.
//    */
//   public void beforeSuite() {
//     if (Property.REUSE_BROWSER.getBoolean()) {
//       driverLifecycle =
//           new MultiUseDriverLifecycle(
//               Property.THREADS.getIntWithDefault(1));
//     } else {
//       driverLifecycle = new SingleUseDriverLifecycle();
//     }
//     driverLifecycle.initDriverPool(DriverSetup::instantiateDriver);
//   }
// 
//   /**
//    * Run this before each test method to initialise the
//    * browser, wait, capture, and user agent.
//    *
//    * <p>This is useful for times when the testMethod does not contain the required
//    * test name e.g. using data providers for BDD.
//    *
//    * @param testName the test name for Capture
//    */
//   public void beforeTestMethod(String testName) {
//     driverLifecycle.initBrowserBeforeTest(DriverSetup::instantiateDriver);
// 
//     wait.set(newWaitWithTimeout(DEFAULT_TIMEOUT));
// 
//     if (ScreenshotCapture.isRequired()) {
//       capture.set(new ScreenshotCapture(testName));
//     }
// 
//     if (userAgent == null) {
//       userAgent = UserAgent.getUserAgent((JavascriptExecutor) getWebDriver());
//     }
//   }
// 
//   /**
//    * @param testMethod the method about to run, used to extract the test name
//    * @see #beforeTestMethod(String)
//    */
//   public void beforeTestMethod(Method testMethod) {
//     beforeTestMethod(getTestNameForCapture(testMethod));
//   }
// 
//   private String getTestNameForCapture(Method testMethod) {
//     Optional<String> testID = TestIdUtils.getIssueOrTmsLinkValue(testMethod);
//     if (!testID.isPresent() || testID.get().isEmpty()) {
//       testID = Optional.of(StringUtils.abbreviate(testMethod.getName(), 20));
//     }
//     return testID.orElse("n/a");
//   }
// 
//   /**
//    * Run after each test method to clear or tear down the browser
//    */
//   public void afterTestMethod() {
//     driverLifecycle.tearDownDriver();
//   }
// 
//   /**
//    * Run after the entire test suite to:
//    * clear down the browser pool, send remaining screenshots to Capture
//    * and create properties for Allure.
//    */
//   public void afterTestSuite() {
//     driverLifecycle.tearDownDriverPool();
//     ScreenshotCapture.processRemainingBacklog();
//     AllureProperties.createUI();
//   }
// 
//   /**
//    * @return new Wait with default timeout.
//    * @deprecated use {@code UITestLifecycle.get().getWait()} instead.
//    */
//   @Deprecated
//   public Wait<WebDriver> newDefaultWait() {
//     return newWaitWithTimeout(DEFAULT_TIMEOUT);
//   }
// 
//   /**
//    * @param timeout timeout for the new Wait
//    * @return a Wait with the given timeout
//    */
//   public Wait<WebDriver> newWaitWithTimeout(Duration timeout) {
//     return new FluentWait<>(getWebDriver())
//         .withTimeout(timeout)
//         .ignoring(NoSuchElementException.class)
//         .ignoring(StaleElementReferenceException.class);
//   }
// 
//   public WebDriver getWebDriver() {
//     return driverLifecycle.getWebDriver();
//   }
// 
//   public ScreenshotCapture getCapture() {
//     return capture.get();
//   }
// 
//   public Wait<WebDriver> getWait() {
//     return wait.get();
//   }
// 
//   /**
//    * @return the user agent of the browser in the first UI test to run.
//    */
//   public Optional<String> getUserAgent() {
//     return Optional.ofNullable(userAgent);
//   }
// 
//   /**
//    * @return the session ID of the remote WebDriver
//    */
//   public String getRemoteSessionId() {
//     return Objects.toString(((RemoteWebDriver) getWebDriver()).getSessionId());
//   }
// }


import static java.util.Objects.nonNull;
import com.frameworkium.core.common.properties.Property;
import com.frameworkium.core.ui.UITestLifecycle;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
  private static String obfuscatePasswordValue(Property p) {
    String key = p.toString();
    String value = p.getValue();
    if (key.toLowerCase().contains("password")) {
      return value.replaceAll(".", "*");
    }
    return value;
  }

  private static Properties getCommonProps() {
    Properties props = new Properties();

    if (nonNull(System.getenv("BUILD_URL"))) {
      props.setProperty("CI build URL", System.getenv("BUILD_URL"));
    }
    if (nonNull(System.getProperty("config"))) {
      props.setProperty("Config file", System.getProperty("config"));
    }

    if (Property.JIRA_URL.isSpecified()) {
      final String jiraPattern = Property.JIRA_URL.getValue() + "/browse/%s";
      props.setProperty("allure.issues.tracker.pattern", jiraPattern);
      props.setProperty("allure.tests.management.pattern", jiraPattern);
    }

    return props;
  }

  private static Properties getUIProperties() {
    Properties props = new Properties();
// Path: src/main/java/com/frameworkium/core/ui/UITestLifecycle.java
// public class UITestLifecycle {
// 
//   private static final Duration DEFAULT_TIMEOUT = Duration.of(10, SECONDS);
// 
//   private static final ThreadLocal<ScreenshotCapture> capture = new ThreadLocal<>();
//   private static final ThreadLocal<Wait<WebDriver>> wait = new ThreadLocal<>();
//   private static final ThreadLocal<UITestLifecycle> uiTestLifecycle =
//       ThreadLocal.withInitial(UITestLifecycle::new);
// 
//   private static DriverLifecycle driverLifecycle;
//   private static String userAgent;
// 
//   /**
//    * @return a ThreadLocal instance of {@link UITestLifecycle}
//    */
//   public static UITestLifecycle get() {
//     return uiTestLifecycle.get();
//   }
// 
//   /**
//    * @return check to see if class initialised correctly.
//    */
//   public boolean isInitialised() {
//     return wait.get() != null;
//   }
// 
//   /**
//    * Run this before the test suite to initialise a pool of drivers.
//    */
//   public void beforeSuite() {
//     if (Property.REUSE_BROWSER.getBoolean()) {
//       driverLifecycle =
//           new MultiUseDriverLifecycle(
//               Property.THREADS.getIntWithDefault(1));
//     } else {
//       driverLifecycle = new SingleUseDriverLifecycle();
//     }
//     driverLifecycle.initDriverPool(DriverSetup::instantiateDriver);
//   }
// 
//   /**
//    * Run this before each test method to initialise the
//    * browser, wait, capture, and user agent.
//    *
//    * <p>This is useful for times when the testMethod does not contain the required
//    * test name e.g. using data providers for BDD.
//    *
//    * @param testName the test name for Capture
//    */
//   public void beforeTestMethod(String testName) {
//     driverLifecycle.initBrowserBeforeTest(DriverSetup::instantiateDriver);
// 
//     wait.set(newWaitWithTimeout(DEFAULT_TIMEOUT));
// 
//     if (ScreenshotCapture.isRequired()) {
//       capture.set(new ScreenshotCapture(testName));
//     }
// 
//     if (userAgent == null) {
//       userAgent = UserAgent.getUserAgent((JavascriptExecutor) getWebDriver());
//     }
//   }
// 
//   /**
//    * @param testMethod the method about to run, used to extract the test name
//    * @see #beforeTestMethod(String)
//    */
//   public void beforeTestMethod(Method testMethod) {
//     beforeTestMethod(getTestNameForCapture(testMethod));
//   }
// 
//   private String getTestNameForCapture(Method testMethod) {
//     Optional<String> testID = TestIdUtils.getIssueOrTmsLinkValue(testMethod);
//     if (!testID.isPresent() || testID.get().isEmpty()) {
//       testID = Optional.of(StringUtils.abbreviate(testMethod.getName(), 20));
//     }
//     return testID.orElse("n/a");
//   }
// 
//   /**
//    * Run after each test method to clear or tear down the browser
//    */
//   public void afterTestMethod() {
//     driverLifecycle.tearDownDriver();
//   }
// 
//   /**
//    * Run after the entire test suite to:
//    * clear down the browser pool, send remaining screenshots to Capture
//    * and create properties for Allure.
//    */
//   public void afterTestSuite() {
//     driverLifecycle.tearDownDriverPool();
//     ScreenshotCapture.processRemainingBacklog();
//     AllureProperties.createUI();
//   }
// 
//   /**
//    * @return new Wait with default timeout.
//    * @deprecated use {@code UITestLifecycle.get().getWait()} instead.
//    */
//   @Deprecated
//   public Wait<WebDriver> newDefaultWait() {
//     return newWaitWithTimeout(DEFAULT_TIMEOUT);
//   }
// 
//   /**
//    * @param timeout timeout for the new Wait
//    * @return a Wait with the given timeout
//    */
//   public Wait<WebDriver> newWaitWithTimeout(Duration timeout) {
//     return new FluentWait<>(getWebDriver())
//         .withTimeout(timeout)
//         .ignoring(NoSuchElementException.class)
//         .ignoring(StaleElementReferenceException.class);
//   }
// 
//   public WebDriver getWebDriver() {
//     return driverLifecycle.getWebDriver();
//   }
// 
//   public ScreenshotCapture getCapture() {
//     return capture.get();
//   }
// 
//   public Wait<WebDriver> getWait() {
//     return wait.get();
//   }
// 
//   /**
//    * @return the user agent of the browser in the first UI test to run.
//    */
//   public Optional<String> getUserAgent() {
//     return Optional.ofNullable(userAgent);
//   }
// 
//   /**
//    * @return the session ID of the remote WebDriver
//    */
//   public String getRemoteSessionId() {
//     return Objects.toString(((RemoteWebDriver) getWebDriver()).getSessionId());
//   }
// }


// Path: src/main/java/com/frameworkium/core/common/reporting/allure/AllureProperties.java
import static java.util.Objects.nonNull;
import com.frameworkium.core.common.properties.Property;
import com.frameworkium.core.ui.UITestLifecycle;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

  private static String obfuscatePasswordValue(Property p) {
    String key = p.toString();
    String value = p.getValue();
    if (key.toLowerCase().contains("password")) {
      return value.replaceAll(".", "*");
    }
    return value;
  }

  private static Properties getCommonProps() {
    Properties props = new Properties();

    if (nonNull(System.getenv("BUILD_URL"))) {
      props.setProperty("CI build URL", System.getenv("BUILD_URL"));
    }
    if (nonNull(System.getProperty("config"))) {
      props.setProperty("Config file", System.getProperty("config"));
    }

    if (Property.JIRA_URL.isSpecified()) {
      final String jiraPattern = Property.JIRA_URL.getValue() + "/browse/%s";
      props.setProperty("allure.issues.tracker.pattern", jiraPattern);
      props.setProperty("allure.tests.management.pattern", jiraPattern);
    }

    return props;
  }

  private static Properties getUIProperties() {
    Properties props = new Properties();
    UITestLifecycle.get().getUserAgent()