# -*- coding: utf-8 -*-
import os
import subprocess
import time
import requests
import traceback
from appium import webdriver
from appium.options.android import UiAutomator2Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# ==========================================
# CONFIGURATION & PARAMETERS
# ==========================================
key = 'dreYWZN6BkiImePegTZ5et'  # Replace with your IFTTT webhook key
event = 'tbn_event'             # Replace with your IFTTT event name
login = 'alexandre.bona@gmail.com'  # Replace with your actual login
password = 'd6p!2Kv5k#X1'       # Ensure this environment variable is set securely

TARGET_DEVICE = '127.0.0.1:55555' 

def send_ifttt_webhook(event, key, message):
    """Send a webhook message to IFTTT."""
    url = f'https://maker.ifttt.com/trigger/{event}/with/key/{key}'
    data = {'value1': message}
    try:
        requests.post(url, json=data, timeout=10)
        print(f"Webhook sent with message: {message}")
    except Exception as e:
        print(f"Failed to transmit webhook: {e}")
    return None

def pre_launch_wake_and_start():
    """Ensure the headless canvas is awake, open visual feed, and force start the app."""
    print("Waking up virtual display canvas...")
    
    subprocess.run("killall scrcpy", shell=True, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
    
    print("Launching live visual feed via Scrcpy on RDP display :10...")
    subprocess.Popen(
        "export DISPLAY=:10 && scrcpy -s 127.0.0.1:55555 -f --bit-rate=2M --max-fps=30", 
        shell=True, 
        stdout=subprocess.DEVNULL, 
        stderr=subprocess.DEVNULL
    )
    time.sleep(2) 

    try:
        subprocess.run(f"adb connect {TARGET_DEVICE}", shell=True, timeout=5, stdout=subprocess.DEVNULL)
        subprocess.run(f"adb -s {TARGET_DEVICE} shell svc power stayon true", shell=True, timeout=10)
        subprocess.run(f"adb -s {TARGET_DEVICE} shell wm dismiss-keyguard", shell=True, timeout=10)

        print("Launching Verizon FamilyBase via Activity Manager...")
        subprocess.run(f"adb -s {TARGET_DEVICE} shell am start -W -n com.verizon.familybase.parent/com.verizon.familybase.MainActivity --receiver-foreground -f 0x10000000", shell=True, timeout=15)
        time.sleep(3)

    except subprocess.TimeoutExpired:
        print("CRITICAL: ADB command timed out! The Android network bridge is frozen.")
    time.sleep(5)

def force_close_app():
    """Force stops the Android app and spins down the headless session."""
    print("Force-stopping application package execution layers cleanly...")
    subprocess.run(f"adb -s {TARGET_DEVICE} shell am force-stop com.verizon.familybase.parent", shell=True)
    subprocess.run("killall scrcpy", shell=True, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
    print("System optimization cleanup complete. Session closed.")

def start_appium_session():
    """Initialize the cloud Appium options object matching Redroid architecture."""
    options = UiAutomator2Options()
    options.platform_name = "Android"
    options.automation_name = "UiAutomator2"
    options.device_name = TARGET_DEVICE
    options.udid = TARGET_DEVICE 
    options.app_package = "com.verizon.familybase.parent"
    options.app_wait_activity = "*" 
    options.no_reset = True
    options.ensure_webviews_have_pages = True
    options.set_capability("androidHome", "/usr/lib/android-sdk")

    driver = webdriver.Remote('http://127.0.0.1:4723', options=options)
    return driver

# ==========================================
# EXECUTION PIPELINE
# ==========================================
if __name__ == "__main__":
    pre_launch_wake_and_start()
    driver = start_appium_session()
    print("Appium session established successfully.")

    # Menu & Navigation Locators
    timeout_login_locator = (By.ID, "com.verizon.familybase.parent:id/positive")
    enable_long_term_locator = (By.XPATH, "//*[@text='Enable']")
    close_permissions_locator = (By.XPATH, "//*[@content-desc='Close']")
    profiles_locator = (By.ID, "com.verizon.familybase.parent:id/menu_item_profile")
    restrict_data_locator = (By.XPATH, "//*[contains(@text, 'Restrict Data, Text & Calls') or contains(@text, 'Restrict Data')]")
    
    # Original Limit Logic Locators
    limit_locator = (By.ID, "com.verizon.familybase.parent:id/tv_dataLimitCount")
    rightArrow_locator = (By.ID, "com.verizon.familybase.parent:id/ivRightArrowData")
    changeLimit_locator = (By.ID, "com.verizon.familybase.parent:id/ll_et_limit")
    newLimit_locator = (By.ID, "com.verizon.familybase.parent:id/et_limit")
    save_locator = (By.ID, "com.verizon.familybase.parent:id/btn_save")
    edit_text_locator = (By.CLASS_NAME, "android.widget.EditText")
    
    # Initialization Locators
    get_started_locator = (By.XPATH, "//*[@text='Get Started']")
    sign_in_locator = (By.XPATH, "//*[@text='Sign in to Verizon']")
    login_field_locator = (By.XPATH, "(//android.widget.EditText)[1]")
    password_field_locator = (By.XPATH, "//android.widget.EditText[@password='true']")
    webview_submit_button = (By.XPATH, "//android.widget.Button[@text='Sign in']")

    try:
        # ==========================================
        # 1. SMART STATE CHECK & INITIALIZATION
        # ==========================================
        print("Checking if we are already logged in...")

        try:
            # Check if we bypassed login entirely
            WebDriverWait(driver, 8).until(
                EC.presence_of_element_located(profiles_locator)
            )
            print("Dashboard detected. Skipping login flow.")
        
        except:
            print("Dashboard not found. Intercepting login flow...")
            
            # --- STEP A: Handle the "Security Session Timeout" popup ---
            try:
                timeout_btn = WebDriverWait(driver, 5).until(
                    EC.element_to_be_clickable(timeout_login_locator)
                )
                timeout_btn.click()
                print("Session Timeout popup detected and dismissed. App resetting to splash screen...")
                time.sleep(2) 
            except Exception:
                print("No Session Timeout popup detected. Proceeding...")
                
            # --- STEP B: Standard 'Get Started' Flow ---
            try:
                get_started_btn = WebDriverWait(driver, 8).until(
                    EC.element_to_be_clickable(get_started_locator)
                )
                get_started_btn.click()
                print("Clicked 'Get Started'...")
            except Exception:
                print("No 'Get Started' button found. Proceeding to look for 'Sign In'...")
            
            sign_in_btn = WebDriverWait(driver, 10).until(
                EC.element_to_be_clickable(sign_in_locator)
            )
            sign_in_btn.click()
            print("Navigating to WebView Authentication Portal...")

            # --- STEP C: Inject Credentials into the WebView ---
            login_field = WebDriverWait(driver, 20).until(
                EC.element_to_be_clickable(login_field_locator)
            )
            login_field.click()
            login_field.clear()
            login_field.send_keys(login)

            password_field = driver.find_element(*password_field_locator)
            password_field.click()
            password_field.clear()
            password_field.send_keys(password)
            time.sleep(1)

            submit_btn = driver.find_element(*webview_submit_button)
            submit_btn.click()
            print("Authentication submitted. Analyzing network routing...")
            sleep(5)
            raise Exception("Deliberate crash after login submission to capture post-login state for debugging. This is expected behavior to ensure we can analyze the routing logic in the next steps.")
            
            # ==========================================
            # THE SMART ROUTER (REPLACES BLIND WAITING)
            # ==========================================
            current_state = "UNKNOWN"
            for i in range(20): # Up to 60 seconds
                try:
                    page_src = driver.page_source.lower()
                    
                    if "menu_item_profile" in page_src or "profiles" in page_src:
                        current_state = "DASHBOARD"
                        print("--> Routed directly to Dashboard!")
                        break
                    elif "long-term sign in" in page_src or "enable" in page_src:
                        current_state = "ENABLE"
                        print("--> Routed to Long-Term Sign In prompt!")
                        break
                    elif "code" in page_src or "verify" in page_src or "verification" in page_src:
                        current_state = "2FA"
                        print("--> Routed to 2FA Verification Screen!")
                        break
                except:
                    pass
                time.sleep(3)
                print(f"   ... analyzing network state ({i+1}/20) ...")

            if current_state == "UNKNOWN":
                 raise Exception("Routing Timeout! The app never moved past the loading spinner.")

            # --- STEP D: Interactive 2FA Interceptor ---
            if current_state == "2FA":
                time.sleep(5) # Let WebView finish rendering inputs
                try:
                    two_fa_field = driver.find_element(By.XPATH, "//android.widget.EditText")
                    
                    print("\n" + "="*60)
                    two_fa_code = input("🚨 2FA REQUIRED: Check your phone, type the code here, and hit ENTER: ")
                    print("="*60 + "\n")
                    
                    two_fa_field.click()
                    time.sleep(1)
                    two_fa_field.clear()
                    two_fa_field.send_keys(two_fa_code)
                    time.sleep(1)
                    
                    two_fa_submit_btn = driver.find_element(By.XPATH, "//android.widget.Button[contains(@text, 'Continue') or contains(@text, 'Verify') or contains(@text, 'Submit')]")
                    two_fa_submit_btn.click()
                    
                    print("2FA code injected and submitted! Waiting for token handoff...")
                    time.sleep(8)
                    
                    # Re-evaluate routing after submitting 2FA (it might go to ENABLE next)
                    post_2fa_src = driver.page_source.lower()
                    if "long-term sign in" in post_2fa_src or "enable" in post_2fa_src:
                        current_state = "ENABLE"
                    else:
                        current_state = "DASHBOARD"
                        
                except Exception as e:
                    # DELIBERATE CRASH TO DROP THE XML
                    raise Exception("2FA Screen detected, but Appium could not locate the input fields! Forcing a crime-scene dump.")

            # --- STEP E: Long-Term Sign In (Enable) Interceptor ---
            if current_state == "ENABLE":
                print("Checking for 'Long-term sign in' prompt...")
                try:
                    enable_btn = WebDriverWait(driver, 15).until(
                        EC.element_to_be_clickable(enable_long_term_locator)
                    )
                    enable_btn.click()
                    print("Clicked 'Enable' for 6-month token preservation.")
                    time.sleep(3)
                except Exception:
                    print("No 'Enable' prompt detected. Proceeding...")

            # Anti-Spinner Nudge Logic
            try:
                WebDriverWait(driver, 25).until(
                    EC.presence_of_element_located(profiles_locator)
                )
            except Exception:
                print("App appears stuck on the loading spinner. Attempting a UI Redraw Nudge...")
                driver.background_app(2)
                WebDriverWait(driver, 15).until(
                    EC.presence_of_element_located(profiles_locator)
                )

        # ==========================================
        # 2. DASHBOARD NAVIGATION TRAVERSAL
        # ==========================================
        
        try:
            close_btn = driver.find_element(*close_permissions_locator)
            close_btn.click()
            print("Intercepted and dismissed the Onboarding Permissions screen.")
            time.sleep(2)
        except Exception:
            pass 

        print("Waiting for Dashboard...")
        profiles_btn = WebDriverWait(driver, 15).until(
            EC.element_to_be_clickable(profiles_locator)
        )
        profiles_btn.click()
        print("Clicked 'Profiles'.")

        restrict_btn = WebDriverWait(driver, 15).until(
            EC.element_to_be_clickable(restrict_data_locator)
        )
        restrict_btn.click()
        print("Clicked 'Restrict Data, Text & Calls'.")

        WebDriverWait(driver, 15).until(
            EC.presence_of_element_located(limit_locator)
        )

        # ==========================================
        # 3. CORE AUTOMATION STEPS (LIMIT LOGIC)
        # ==========================================
        print("Executing data limit automation steps...")
        
        currentUsage = driver.find_element(*limit_locator).text
        usage = currentUsage.split('/')[0].strip()
        usage_float = round(float(usage), 1)
        if usage_float < 0.5:
            usage_float = 0.5
        time.sleep(2)
        
        driver.find_element(*rightArrow_locator).click()
        time.sleep(2)
        
        limit_field = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable(changeLimit_locator)
        )
        time.sleep(2)
        limit_field.click()
        time.sleep(2)
        
        edit_text = WebDriverWait(driver, 10).until(
            EC.visibility_of_element_located(edit_text_locator)
        )
        time.sleep(0.5)
        
        edit_text.send_keys(" ")
        time.sleep(0.5)
        edit_text.send_keys(f"{usage_float:.1f}")
        time.sleep(3)
        
        driver.find_element(*save_locator).click()
        time.sleep(5)
        print("Verizon Limit Automation complete.")

    except Exception as e:
        print("\n=======================================================")
        print(f"❌ CRITICAL FAULT TRIPPED: {e}")
        print("=======================================================")
        
        traceback.print_exc() 
        send_ifttt_webhook(event, key, "Mobile Limit Failed!")

        try:
            print("\nSnapping emergency triage screenshots and layout XML...")
            driver.save_screenshot('/home/ubuntu/verizon_fault.png')
            with open('/home/ubuntu/verizon_layout.xml', 'w', encoding='utf-8') as f:
                f.write(driver.page_source)
            print("✅ Diagnostics saved to /home/ubuntu/verizon_fault.png and /home/ubuntu/verizon_layout.xml")
            
            print("\n🚨 EXECUTION PAUSED FOR DEBUGGING 🚨")
            print("The script has failed, but the Appium driver is still alive.")
            print("1. Look at your scrcpy window to see where the app is stuck.")
            print("2. Open /home/ubuntu/verizon_layout.xml in VS Code to inspect the current UI tree.")
            input("\n👉 Press [ENTER] in this terminal when you are ready to kill the app and exit...")

        except Exception as diag_err:
            print(f"Failed to capture diagnostics: {diag_err}")

    finally:
        print("Safely disconnecting client driver stream links...")
        try:
            driver.quit()
        except:
            pass
        
        force_close_app()
