refactor using playwright library
import os
import time
import logging
from concurrent.futures import ProcessPoolExecutor
from selenium import webdriver
from selenium.common import TimeoutException, NoSuchElementException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.service import Service as ChromeService

# Create a logs directory if it doesn't exist
if not os.path.exists('logs'):
    os.makedirs('logs')

start = time.time()


def threading_task(
        url_param, process_id, name_ids, residence_ids, birth_years, usernames, passwords
):
    process_log_path = f'logs/{time.strftime("%Y-%m-%d_%H-%M-%S")}/process_{process_id}.log'
    os.makedirs(os.path.dirname(process_log_path), exist_ok=True)
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.INFO)
    file_handler = logging.FileHandler(process_log_path)
    formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
    file_handler.setFormatter(formatter)
    logger.addHandler(file_handler)

    chrome_options = webdriver.ChromeOptions()
    service = ChromeService(executable_path="chromedriver.exe")
    driver = webdriver.Chrome(options=chrome_options, service=service)

    for name_id, residence_id, birth_year, username, password in zip(
            name_ids, residence_ids, birth_years, usernames, passwords
    ):
        threading(driver, url_param, process_id, name_id, residence_id, birth_year, username, password, logger)
    driver.quit()


def threading(
        driver, url_param, process_id, name_id, residence_id, birth_year, username, password, logger
):
    driver.get(url_param)
    start_time = time.time()
    try:
        username_field = WebDriverWait(driver, 10).until(
            EC.visibility_of_element_located(
                (
                    By.ID,
                    "EmaratechSG_Theme_wtLayoutBlock_block_wtMainContent_wtLoginBlock_WebPatterns_wtNavigationTabs_block_wtContent2_wtEstablishmentLogin_wtinpUsername",
                )
            )
        )
        logger.info(f"Clicked new button with id {username_field.get_attribute('id')}")
        username_field.send_keys(username)
        logger.info("Username entered successfully.")

        password_field = WebDriverWait(driver, 10).until(
            EC.visibility_of_element_located(
                (
                    By.ID,
                    "EmaratechSG_Theme_wtLayoutBlock_block_wtMainContent_wtLoginBlock_WebPatterns_wtNavigationTabs_block_wtContent2_wtEstablishmentLogin_wtinpPassword",
                )
            )
        )
        logger.info(f"Clicked new button with id {password_field.get_attribute('id')}")
        password_field.send_keys(password)
        logger.info("Password entered successfully.")

        submit_password = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable(
                (
                    By.ID,
                    "EmaratechSG_Theme_wtLayoutBlock_block_wtMainContent_wtLoginBlock_WebPatterns_wtNavigationTabs_block_wtContent2_wtEstablishmentLogin_wt15",
                )
            )
        )
        logger.info(f"Clicked checkbox with id {submit_password.get_attribute('id')}")
        submit_password.click()
        logger.info("Password submitted successfully.")

        new_button = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable(
                (By.ID, "EmaratechSG_Theme_wt11_block_wtMainContent_wt6_wtRow2")
            )
        )
        logger.info(f"Clicked new button with id {new_button.get_attribute('id')}")
        new_button.click()
        logger.info("Button clicked successfully.")

        dropdown = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.ID, "select2-chosen-1"))
        )
        logger.info(f"Clicked dropdown with id {dropdown.get_attribute('id')}")
        dropdown.click()
        logger.info("Dropdown clicked successfully.")

        option_element = WebDriverWait(driver, 10).until(
            EC.visibility_of_element_located((By.ID, "select2-result-label-7"))
        )
        logger.info(f"Selected option from dropdown {option_element.get_attribute('id')}")
        option_element.click()
        logger.info("Selected option successfully.")

        residence_input = WebDriverWait(driver, 10).until(
            EC.visibility_of_element_located(
                (
                    By.ID,
                    "EmaratechSG_Theme_wt32_block_wtMainContent_wt50_wtSubmitterResidenceNumber",
                )
            )
        )
        logger.info(f"Entered residence ID with id {residence_input.get_attribute('id')}")
        residence_input.send_keys(residence_id)
        logger.info("Entered residence ID successfully.")

        country_dropdown = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable(
                (
                    By.ID,
                    "s2id_EmaratechSG_Theme_wt32_block_wtMainContent_wt50_wtApplicantNationality",
                )
            )
        )
        logger.info(f"Clicking country dropdown with id {country_dropdown.get_attribute('id')}")
        country_dropdown.click()
        logger.info("Clicked country dropdown ID successfully.")

        india_option = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable(
                (
                    By.XPATH,
                    "//div[contains(@id, 'select2-result-label-') and contains(text(), 'INDIA')]",
                )
            )
        )
        logger.info(f"Selected India from country dropdown with id {india_option.get_attribute('id')}")
        india_option.click()
        logger.info("Selected India from country dropdown successfully.")

        birth_year_input = WebDriverWait(driver, 10).until(
            EC.visibility_of_element_located(
                (
                    By.ID,
                    "EmaratechSG_Theme_wt32_block_wtMainContent_wt50_wtApplicantYearOfBirth",
                )
            )
        )
        logger.info(f"Entered birth year with id {birth_year_input.get_attribute('id')}")
        birth_year_input.send_keys(birth_year)
        logger.info("Entered birth year successfully.")

        login_container = WebDriverWait(driver, 20).until(
            EC.visibility_of_element_located((By.CLASS_NAME, "loginContainer"))
        )
        login_container.click()

        logout = WebDriverWait(driver, 20).until(
            EC.visibility_of_element_located(
                (
                    By.ID,
                    "EmaratechSG_Theme_wt32_block_wtHeader_SmartChannels_Th_wt45_block_wtwbThHeaderGdrfa_wtMenuItems_wtTopAccessibilityBar_wt53_WebPatterns_wt21_block_wtMenuLink6_wt15",
                )
            )
        )
        logout.click()

        end_time = time.time()
        duration = end_time - start_time
        logger.info(f"Thread ID: {name_id}, Duration: {duration:.2f} seconds")
        logger.info(
            f"Process ID: {process_id}, Thread Name ID: {name_id}, Residence ID: {residence_id}, Birth Year: {birth_year}, Username: {username}, Password: {password}"
        )
    except TimeoutException as te:
        logger.error(f"Timeout occurred in thread {name_id}: {te}")
    except NoSuchElementException as nse:
        logger.error(f"Element not found in thread {name_id}: {nse}")
    except Exception as e:
        logger.error(f"An error occurred in thread {name_id}: {e}")


if __name__ == "__main__":
    url = "https://smart.gdrfad.gov.ae/HomePage.aspx?GdfraLocale=en-US"
    num_threads = 3

    user_groups = {
        1: {
            "name_ids": ["Muskan 1"] * num_threads,
            "residence_ids": ["444"] * num_threads,
            "birth_years": ["2000"] * num_threads,
            "usernames": ["muskan123"] * num_threads,
            "passwords": ["Kumari@3011"] * num_threads
        },
        2: {
            "name_ids": ["Muskan 2"] * num_threads,
            "residence_ids": ["555"] * num_threads,
            "birth_years": ["1999"] * num_threads,
            "usernames": ["muskankum"] * num_threads,
            "passwords": ["Muskan@3012"] * num_threads
        },
        3: {
            "name_ids": ["Pratiksha"] * num_threads,
            "residence_ids": ["555"] * num_threads,
            "birth_years": ["1999"] * num_threads,
            "usernames": ["Pratiksha122"] * num_threads,
            "passwords": ["P@ss123455"] * num_threads
        }
        # Uncomment and add more groups as needed
        # 4: {
        #     "name_ids": ["Sara"] * num_threads,
        #     "residence_ids": ["555"] * num_threads,
        #     "birth_years": ["1999"] * num_threads,
        #     "usernames": ["SaraShahh"] * num_threads,
        #     "passwords": ["Abcd@123"] * num_threads
        # },
        # 5: {
        #     "name_ids": ["Kat"] * num_threads,
        #     "residence_ids": ["555"] * num_threads,
        #     "birth_years": ["1999"] * num_threads,
        #     "usernames": ["katz"] * num_threads,
        #     "passwords": ["P@ss12344444"] * num_threads
        # }
    }

    with ProcessPoolExecutor(max_workers=len(user_groups)) as exe:
        for group_id, data in user_groups.items():
            exe.submit(
                threading_task,
                url,
                group_id,
                data["name_ids"],
                data["residence_ids"],
                data["birth_years"],
                data["usernames"],
                data["passwords"]
            )

    end = time.time()
    print(end - start)