import os
import time
from playwright.sync_api import sync_playwright

username = "abona@iadb.org"
password = "mP2*6UkgfqD%S*" # Replace with your actual password

def run(playwright):
    # Set headless=False so you can watch the magic happen. Change to True later.
    browser = playwright.chromium.launch(
        headless=True, 
        args=["--disable-blink-features=AutomationControlled"]
    )

    # Use the exact same user agent as your booking script to prevent session mismatch
    user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"

    # ==========================================
    # 1. TEST EXISTING SESSION
    # ==========================================
    # Dynamically build the absolute path so TriggerCMD/cron can always find it
    script_dir = os.path.dirname(os.path.abspath(__file__))
    state_file_path = os.path.join(script_dir, "state.json")

    if os.path.exists(state_file_path):
        print(f"Found existing state file at {state_file_path}. Testing if session is still valid...")
        try:
            # Load the existing session into a test context
            test_context = browser.new_context(
                storage_state=state_file_path,
                user_agent=user_agent,
                viewport={"width": 1920, "height": 1080}
            )
            test_page = test_context.new_page()
            
            # Navigate to the portal
            test_page.goto('https://iadb.service-now.com/sp?id=parking_pass_screen', wait_until='domcontentloaded')
            test_page.wait_for_timeout(5000) # Give SSO bounces time to settle

            print("⚠️ Session has expired. Generating a new one...")
            test_context.close() # Close the dead context and move on            
            # Check the URL to see if Microsoft kicked us out
            # if "login.microsoftonline.com" not in test_page.url:
            #     print("✅ Existing session is still fully valid! No new authentication needed.")
            #     browser.close()
            #     return
            # else:
            #     print("⚠️ Session has expired. Generating a new one...")
            #     test_context.close() # Close the dead context and move on
        
        except Exception as e:
            print(f"⚠️ Error testing state.json: {e}")
    else:
        print(f"No existing state file found at {state_file_path}. Starting fresh authentication...")

    # ==========================================
    # 2. FRESH AUTHENTICATION FLOW
    # ==========================================
    
    # Create a completely fresh context (no storage_state)
    context = browser.new_context(
        user_agent=user_agent,
        viewport={"width": 1920, "height": 1080}
    )
    page = context.new_page()

    print("Navigating to ServiceNow...")
    page.goto('https://iadb.service-now.com/sp?id=parking_pass_screen')
    time.sleep(2) # Wait for the page to load
    
    # Microsoft Login Flow
    print("Entering credentials...")
    
    # Fill username
    page.fill('input[name="loginfmt"]', username)
    
    # 💥 The Nuclear Option: Click the Next button using raw JavaScript
    page.evaluate("document.querySelector('input[type=\"submit\"]').click()")
    
    # Explicitly wait for the password field to become visible
    page.wait_for_selector('input[name="passwd"]', state="visible", timeout=10000)
    
    # Fill password
    page.fill('input[name="passwd"]', password)
    
    # 💥 The Nuclear Option: Click the Sign In button using raw JavaScript
    page.evaluate("document.querySelector('input[type=\"submit\"]').click()")

    # Wait for the Microsoft 2FA Number to appear on screen
    print("Waiting for 2FA prompt...")
    try:
        # Wait up to 15 seconds for the authenticator screen to load
        page.wait_for_selector('.displaySign, #idRichContext_DisplaySign, #idDiv_SAOTCAS_Title', timeout=15000)
        
        # Target the specific elements that hold the number
        number_locator = page.locator('.displaySign, #idRichContext_DisplaySign').first
        
        # Check if the element exists and is visible
        if number_locator.is_visible():
            # Wait specifically for the text to not be empty
            page.wait_for_function('el => el.innerText.trim().length > 0', arg=number_locator.element_handle())
            auth_number = number_locator.inner_text().strip()
            
            print("\n" + "="*50)
            print(f"🚨 ACTION REQUIRED 🚨")
            print(f"Open Microsoft Authenticator on your phone.")
            print(f"Enter this number: {auth_number}")
            print("="*50 + "\n")
        else:
            print("\n🚨 No number match required. Please check your phone for a standard 'Approve' prompt. 🚨")
            screenshot_path = os.path.join(script_dir, "2fa_screen.png")
            page.screenshot(path=screenshot_path)
            print(f"📸 Captura de tela salva por precaução em: {screenshot_path}\n")
            
    except Exception as e:
        print("\nCould not scrape a 2FA number. Look at the browser window if headless=False!")
        screenshot_path = os.path.join(script_dir, "2fa_error.png")
        page.screenshot(path=screenshot_path)
        print(f"📸 ERRO: Captura de tela do problema salva em: {screenshot_path}\n")

    # ---------------------------------------------------------
    # Smart loop to handle "Stay signed in" and Redirects
    # ---------------------------------------------------------
    print("Waiting for your phone approval and handling redirects...")
    
    for _ in range(60): # 60 second timeout loop
        # 1. If we successfully reach the ServiceNow portal, break the loop
        if "iadb.service-now.com" in page.url and "login" not in page.url:
            print("Successfully redirected to ServiceNow!")
            break
            
        # 2. If the "Stay signed in?" button appears, click it immediately
        if page.locator('id=idSIButton9').is_visible():
            print("Accepting 'Stay signed in?' prompt...")
            page.click('id=idSIButton9')
            time.sleep(2) # Give it a moment to process the click
            
        time.sleep(1)
    else:
        print("Timeout: Did not reach the ServiceNow portal within 60 seconds.")
        browser.close()
        return

    # Wait for the page to fully load its elements before saving
    page.wait_for_load_state('networkidle')

    # Save the authenticated state
    context.storage_state(path="state.json")
    print("✅ Authentication successful! Session saved to state.json")

    browser.close()

if __name__ == "__main__":
    with sync_playwright() as playwright:
        run(playwright)