import subprocess
import time
import traceback
import requests
import os
from appium import webdriver
from appium.options.android import UiAutomator2Options
from selenium.webdriver.common.by import By
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains

# ==========================================
# CONFIGURATION & PARAMETERS
# ==========================================
Password_Here = "G@Udn1w@#8N8"
key = 'dreYWZN6BkiImePegTZ5et'  # Replace with your IFTTT webhook key
event = 'tbn_event'             # Replace with your IFTTT event name

feed_caramelo = True
perform_plus_caramelo = False
perform_confirm_caramelo = False
REDROID_IP = "127.0.0.1:55555"  # Defined globally for easy changes

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 and force start the app."""
    print("Waking up virtual display canvas...")
    
    subprocess.run("killall scrcpy", shell=True, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
    
    try:
        # 1. Connect specifically to the Redroid Docker port
        subprocess.run(f"adb connect {REDROID_IP}", shell=True, timeout=5, stdout=subprocess.DEVNULL)
        
        # 2. Execute wakeup commands specifically on Redroid using the -s flag
        subprocess.run(f"adb -s {REDROID_IP} shell svc power stayon true", shell=True, timeout=10)
        subprocess.run(f"adb -s {REDROID_IP} shell wm dismiss-keyguard", shell=True, timeout=10)

        print("Launching Petlibro via Activity Manager...")
        subprocess.run(f"adb -s {REDROID_IP} shell am start -W -n com.designlibro.petlibro/.MainActivity --receiver-foreground -f 0x10000000", shell=True, timeout=15)
        time.sleep(2)
        
    except subprocess.TimeoutExpired:
        print("CRITICAL: ADB command timed out! The Android network bridge is frozen.")
    time.sleep(2)

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 {REDROID_IP} shell am force-stop com.designlibro.petlibro", shell=True)
    subprocess.run("killall scrcpy", shell=True, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
    print("System optimization cleanup complete. Session closed.")

def wait_for_appium(timeout=30):
    """Prevents crash if a cron schedule triggers during a server reboot."""
    print("Checking Appium Server health...")
    start_time = time.time()
    while time.time() - start_time < timeout:
        try:
            # Ping the Appium status endpoint
            response = requests.get('http://127.0.0.1:4723/status', timeout=2)
            if response.status_code == 200:
                return True
        except requests.ConnectionError:
            time.sleep(1)
    raise Exception("Appium server is offline or unreachable!")

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 = REDROID_IP
    options.udid = REDROID_IP
    options.app_package = "com.designlibro.petlibro"
    options.app_activity = ".MainActivity"
    options.no_reset = True
    options.ensure_webviews_have_pages = True
    options.set_capability("androidHome", "/usr/lib/android-sdk")

    # This dynamically waits for Appium before trying to connect
    wait_for_appium() 
    driver = webdriver.Remote('http://127.0.0.1:4723', options=options)
    return driver

# Pre-wake display canvas and force app execution
pre_launch_wake_and_start()

# Start the Appium UI automation driver session
driver = start_appium_session()
print("Appium session established successfully.")

# ==========================================
# DIAGNÓSTICO INICIAL (DEBUG)
# ==========================================
print("Capturando screenshot e dump XML do estado inicial...")
try:
    # Aguarda 3 segundos para garantir que a tela carregou antes da foto
    time.sleep(3) 
    driver.save_screenshot('/home/ubuntu/caramelo_initial_state.png')
    with open('/home/ubuntu/caramelo_initial_layout.xml', 'w', encoding='utf-8') as f:
        f.write(driver.page_source)
    print("✅ Estado inicial salvo em: /home/ubuntu/caramelo_initial_state.png e /home/ubuntu/caramelo_initial_layout.xml")
except Exception as e:
    print(f"⚠️ Falha ao salvar o diagnóstico inicial: {e}")

# ==========================================
# LOCATORS 
# ==========================================
# Core Feeding Interface
caramelo_locator = (By.XPATH, "//android.widget.Button[@content-desc='Kitchen\nCaramelo Bona\nNext feeding:\nNo Feeding Schedule ']")
dashboard_feed_locator = (By.XPATH, "//android.widget.ImageView[@content-desc='Feed Now']")
plus_locator = (By.XPATH, "//android.view.View[@content-desc='10 g']/android.widget.ImageView[2]") 
confirm_feed_locator = (By.XPATH, "//android.widget.Button[@content-desc='FEED NOW']")
back_locator = (By.XPATH, "//android.widget.FrameLayout[@resource-id='android:id/content']/android.widget.FrameLayout/android.widget.FrameLayout/android.view.View/android.view.View/android.view.View/android.view.View/android.widget.ImageView[1]")

# First-Time Initialization
agree_continue_locator = (By.XPATH, "//android.widget.Button[contains(@content-desc, 'Agree And Continue')]")

try:
# ==========================================
    # GLOBAL PRE-FLIGHT INTERCEPT
    # ==========================================
    print("Checking for hanging OS notification prompts before scanning dashboard...")
    try:
        deny_button = WebDriverWait(driver, 4).until(
            EC.presence_of_element_located((By.XPATH, "//*[@resource-id='com.android.permissioncontroller:id/permission_deny_button' or @resource-id='com.android.permissioncontroller:id/permission_deny_and_dont_ask_again_button']"))
        )
        deny_button.click()
        print("Cleared hanging notification shield!")
        time.sleep(1)
    except Exception:
        pass 

    print("Checking for session expiration popup...")
    try:
        # Gentle DOM query: Check exactly once to avoid Appium boot crashes
        expired_buttons = driver.find_elements(By.XPATH, "//android.widget.Button[contains(@content-desc, 'expired')]")
        dismiss_overlays = driver.find_elements(AppiumBy.ACCESSIBILITY_ID, "Dismiss")

        if len(expired_buttons) > 0:
            print("Session expiration detected! Firing hardware tap on 'OK' button...")
            actions = ActionChains(driver)
            actions.move_to_element(expired_buttons[0]).click().perform()
            time.sleep(2)
            
        elif len(dismiss_overlays) > 0:
            print("Firing absolute coordinate tap on Dismiss overlay (avoiding the center)...")
            # We bypass the center overlap and tap near the top of the screen
            driver.execute_script("mobile: clickGesture", {"x": 540, "y": 200})
            time.sleep(2)
            
        else:
            print("No expiration popup detected. Canvas is clear.")
            
    except Exception as e:
        print(f"Warning: Expiration intercept failed: {e}")

    # ==========================================
    # SMART STATE CHECK
    # ==========================================    print("Checking current screen state...")
    needs_full_login = False
    already_on_pet_page = False
    
    try:
        # 1. First, check if we are already inside Caramelo's feeding page
        WebDriverWait(driver, 5).until(
            EC.presence_of_element_located((By.XPATH, "//android.widget.ImageView[@content-desc='Feed Now']"))
        )
        print("BINGO! Already on Caramelo's profile page. Resuming from current state...")
        already_on_pet_page = True
    except Exception:
        print("Not on the inner pet page. Checking for main dashboard...")
        try:
            # 2. Give the cloud up to 10 seconds to load the dashboard natively
            WebDriverWait(driver, 10).until(
                EC.presence_of_element_located(caramelo_locator)
            )
            print("BINGO! Main dashboard found. Proceeding with standard navigation.")
        except Exception:
            print("Caramelo not found. The app is logged out or corrupted. Initiating full reset...")
            needs_full_login = True

    # ==========================================
    # FULL LOGIN GAUNTLET (Only runs if needed)
    # ==========================================
    if needs_full_login:
        # 2. Terms and Conditions
        try:
            print("Checking for Terms and Conditions prompt...")
            agree_btn = driver.find_elements(*agree_continue_locator)
            if agree_btn:
                element = agree_btn[0]
                rect = element.rect
                target_x = rect['x'] + (rect['width'] // 2)
                target_y = rect['y'] + rect['height'] - 75
                
                print(f"Phantom click bypassed. Firing precision tap at X:{target_x}, Y:{target_y}...")
                driver.execute_script("mobile: clickGesture", {"x": target_x, "y": target_y})
                print("Terms and Conditions prompt handled.")
                time.sleep(2) 
            else:
                print("No Terms and Conditions prompt detected. Moving on...")
        except Exception:
            pass

        # 3. Notification Bypass
        try:
            print("Checking for native notification prompt...")
            deny_button = WebDriverWait(driver, 15).until(
                EC.presence_of_element_located((By.XPATH, "//*[@resource-id='com.android.permissioncontroller:id/permission_deny_button' or @resource-id='com.android.permissioncontroller:id/permission_deny_and_dont_ask_again_button']"))
            )
            deny_button.click()
            print("Handled notification prompt successfully.")
        except Exception:
            print("No notification prompt detected. Moving on...")
        
        # 4. Flutter-Adaptive Login Entry
        try:
            # --- SPLASH SCREEN BYPASS ---
            print("Checking for pre-login splash screen...")
            try:
                splash_login = WebDriverWait(driver, 15).until(
                    EC.element_to_be_clickable((By.XPATH, "//android.widget.Button[@content-desc='Log In']"))
                )
                splash_login.click()
                print("Bypassed splash screen! Entering credential form...")
                time.sleep(2)
            except Exception:
                print("No splash screen detected. Proceeding to credentials...")
            # ----------------------------
            
            print("Waiting for Flutter UI to stabilize...")
            time.sleep(2) 
            
            # 3.5 Location Selection (Smart Check)
            print("Checking current Location setting...")
            try:
                usa_preset = driver.find_elements(By.XPATH, "//*[@content-desc='United States of America' or @text='United States of America']")
                if usa_preset:
                    print("Location is already set to USA. Skipping dropdown navigation.")
                else:
                    print("Opening Location list...")
                    location_dropdown = WebDriverWait(driver, 10).until(
                        EC.element_to_be_clickable((By.XPATH, "//android.widget.ImageView[@content-desc='Location']"))
                    )
                    location_dropdown.click()
                    time.sleep(2)

                    try:
                        alphabet_bar = WebDriverWait(driver, 3).until(
                            EC.presence_of_element_located((By.XPATH, "//android.view.View[contains(@content-desc, 'A') and contains(@content-desc, 'Z')]"))
                        )
                        rect = alphabet_bar.rect
                        target_x = rect['x'] + (rect['width'] // 2)
                        target_y = rect['y'] + int(rect['height'] * 0.80)
                        driver.execute_script("mobile: clickGesture", {"x": target_x, "y": target_y})
                        time.sleep(1.5)
                    except Exception:
                        print("Warning: Could not find alphabet bar. Falling back to scroll...")

                    try:
                        usa_option = WebDriverWait(driver, 3).until(
                            EC.element_to_be_clickable((By.XPATH, "//*[@content-desc='United States of America' or @text='United States of America']"))
                        )
                        usa_option.click()
                    except Exception:
                        window = driver.get_window_size()
                        center_x = window['width'] // 2
                        start_y = int(window['height'] * 0.7)  
                        end_y = int(window['height'] * 0.4)    
                        usa_found = False
                        for _ in range(5): 
                            try:
                                usa_option = WebDriverWait(driver, 1).until(
                                    EC.element_to_be_clickable((By.XPATH, "//*[@content-desc='United States of America' or @text='United States of America']"))
                                )
                                usa_option.click()
                                usa_found = True
                                break
                            except Exception:
                                driver.swipe(center_x, start_y, center_x, end_y, 800)
                                time.sleep(0.5) 
                        if not usa_found:
                            raise Exception("Couldn't find the United States!")
                    print("Location successfully set!")
                    time.sleep(1)
            except Exception as loc_err:
                print(f"Warning: Failed during location check. Error: {loc_err}")

            # 3.6 Email Entry (Smart Check)
            print("Checking if Email is already populated...")
            try:
                email_preset = driver.find_elements(By.XPATH, "//*[contains(@content-desc, 'alexandre.bona@gmail.com') or contains(@text, 'alexandre.bona@gmail.com')]")
                if email_preset:
                    print("Email is already populated. Skipping entry.")
                else:
                    print("Entering email address...")
                    email_field = WebDriverWait(driver, 15).until(
                        EC.element_to_be_clickable((By.XPATH, "//*[@class='android.view.View' and (@text='Email' or contains(@content-desc, 'Email'))] | //android.widget.EditText"))
                    )
                    email_field.click()
                    email_field.clear() 
                    email_field.send_keys("alexandre.bona@gmail.com")
            except Exception as email_err:
                print(f"Warning: Failed during email entry. Error: {email_err}")

            # Password
            print("Entering Password...")
            password_field = driver.find_element(By.XPATH, "//*[@class='android.view.View' and (@text='Password' or contains(@content-desc, 'Password'))] | //android.widget.EditText[2]")
            password_field.click()
            password_field.send_keys(Password_Here)
            driver.press_keycode(66) # Enter
            time.sleep(0.5)
            
            # Checkbox
            checkbox = WebDriverWait(driver, 10).until(
                EC.element_to_be_clickable((By.XPATH, "//android.widget.ImageView[@index='5' and @clickable='true']"))
            )
            checkbox.click()

            # Login Button (Submit form)
            login_button = WebDriverWait(driver, 10).until(
                EC.element_to_be_clickable((By.XPATH, "//android.widget.Button[@index='7' and @content-desc='Log In' and @clickable='true']"))
            )
            login_button.click()
            print("Login payload transmitted!")

            # 5. Post-Login Intercept Gauntlet
            print("Waiting 8 seconds for Kalay cloud sync...")
            time.sleep(8) 
            
            print("Checking for Message Center hijack...")
            try:
                WebDriverWait(driver, 5).until(
                    EC.presence_of_element_located((AppiumBy.XPATH, "//android.view.View[@content-desc='MESSAGE CENTER']"))
                )
                print("Trapped in Message Center! Clicking back arrow...")
                back_arrow = driver.find_element(AppiumBy.XPATH, "//android.widget.ImageView[@index='0' and @clickable='true']")
                back_arrow.click()
                time.sleep(3) 
            except Exception:
                print("No Message Center intercepted.")

        except Exception as login_err:
            print(f"Login routine fault: {login_err}")


    # ==========================================
    # CORE PET FEEDING PIPELINE
    # ==========================================
    if feed_caramelo:
        if not already_on_pet_page:
            print("Locating Caramelo's machine entry profile...")
            driver.find_element(*caramelo_locator).click()
            
            print("Waiting 2 seconds for the device page to load...")
            time.sleep(2)
        else:
            print("Skipping dashboard navigation, already on Caramelo's device page.")

        # INTERCEPT: Device-Level "Done" Tooltip
        print("Checking for First-Time 'Done' tooltip on the device page...")
        try:
            target = WebDriverWait(driver, 5).until(
                EC.presence_of_element_located((AppiumBy.ACCESSIBILITY_ID, "Done"))
            )
            print("Tooltip detected! Firing native click...")
            target.click()
            time.sleep(2)
        except Exception:
            try:
                target = driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().descriptionContains("Done")')
                driver.execute_script("mobile: clickGesture", {"elementId": target.id})
                time.sleep(2)
            except Exception:
                print("No 'Done' tooltip detected. Device screen is clear.")

        # INTERCEPT: Device-Level Firmware Update
        print("Checking for rogue Firmware Update popup on device page...")
        try:
            cancel_update = WebDriverWait(driver, 4).until(
                EC.element_to_be_clickable((By.XPATH, "//android.widget.Button[@content-desc='Cancel']"))
            )
            cancel_update.click()
            print("Firmware update popup dismissed! Canvas is clear.")
            
            send_ifttt_webhook(event, key, "Update Petlibro Firmware")
            time.sleep(2)
        except Exception:
            pass 

        # Execute Feeding
        print("Triggering instant feed canvas overlay...")
        dashboard_feed_btn = WebDriverWait(driver, 15).until(
            EC.element_to_be_clickable((By.XPATH, "//android.widget.ImageView[@content-desc='Feed Now']"))
        )
        dashboard_feed_btn.click()

        if perform_plus_caramelo:
            print("Incrementing weight portion size (+10g)...")
            driver.find_element(*plus_locator).click()
            time.sleep(2)

        if not perform_confirm_caramelo:
            print("Aborting feeding action loop: issuing back keycode.")
            driver.press_keycode(4)
            time.sleep(2)

        if perform_confirm_caramelo:
            print("Feeding validation confirmed. Delivering treats immediately.")
            confirm_feed_btn = WebDriverWait(driver, 10).until(
                EC.element_to_be_clickable((By.XPATH, "//android.widget.Button[@content-desc='FEED NOW']"))
            )
            confirm_feed_btn.click()

        print("Returning interface map to root layer...")
        driver.find_element(*back_locator).click()
        time.sleep(2)

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

    try:
        print("\nSnapping emergency triage screenshots and layout XML...")
        driver.save_screenshot('/home/ubuntu/caramelo_fault.png')
        with open('/home/ubuntu/caramelo_layout.xml', 'w', encoding='utf-8') as f:
            f.write(driver.page_source)
        print("✅ Diagnostics saved to /home/ubuntu/caramelo_fault.png and /home/ubuntu/caramelo_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/caramelo_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()
