#!/usr/bin/env python3
"""
GHL Sub-Account API Key Generator — Collaborative Browser Handoff Version
Step 1: Script sends email verification code
Step 2: Kinan provides the code (via command-line argument or stdin)
Step 3: Script continues to generate the API key

Usage:
  python3 ghl_generate_api_key_handoff.py send      # Step 1: sends the email code
  python3 ghl_generate_api_key_handoff.py verify CODE  # Step 2: verifies code and generates key
"""

import os
import sys
import time
import json
import re
import pickle

# GHL Credentials
GHL_EMAIL = "kinan@agileadapt.com"
GHL_PASSWORD = "SystemBird505*"

# Target sub-account
TARGET_LOCATION_ID = "7UExU3gWmZqJEKbAeAq4"
INTEGRATION_NAME = "Genesis-SA008-API"

# State & screenshot dirs
STATE_DIR = "/mnt/e/genesis-system/scripts/ghl_state"
SCREENSHOT_DIR = "/mnt/e/genesis-system/scripts/screenshots"
os.makedirs(STATE_DIR, exist_ok=True)
os.makedirs(SCREENSHOT_DIR, exist_ok=True)

STORAGE_STATE_FILE = os.path.join(STATE_DIR, "ghl_storage_state.json")


def screenshot(page, name):
    path = os.path.join(SCREENSHOT_DIR, f"{name}.png")
    page.screenshot(path=path)
    print(f"[SCREENSHOT] {path}")
    return path


def send_verification_code():
    """Step 1: Login and trigger email verification code."""
    from playwright.sync_api import sync_playwright

    with sync_playwright() as p:
        browser = p.chromium.launch(
            headless=True,
            args=['--no-sandbox', '--disable-blink-features=AutomationControlled', '--disable-dev-shm-usage']
        )
        context = browser.new_context(
            viewport={'width': 1920, 'height': 1080},
            user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
        )
        page = context.new_page()

        # Navigate to GHL
        print("[STEP 1] Navigating to GHL login...")
        page.goto("https://app.gohighlevel.com/", wait_until="networkidle", timeout=30000)
        time.sleep(2)

        # Fill login
        email_input = page.wait_for_selector('input[type="email"], input[name="email"]', timeout=10000)
        email_input.fill(GHL_EMAIL)
        time.sleep(0.3)

        password_input = page.query_selector('input[type="password"]')
        password_input.fill(GHL_PASSWORD)
        time.sleep(0.3)

        sign_in_btn = page.query_selector('button[type="submit"]')
        sign_in_btn.click()
        print("[STEP 2] Submitted login credentials...")

        # Wait for verification page
        time.sleep(5)
        screenshot(page, "handoff_01_after_login")

        # Check if we're at the verification page
        page_text = page.inner_text('body')
        if 'verify security code' in page_text.lower() or 'verification' in page_text.lower():
            # "Send code to email" should be selected by default
            # Click "Send Security Code"
            send_btn = page.query_selector('button:has-text("Send Security Code"), button:has-text("Send Code")')
            if send_btn:
                send_btn.click()
                print("[STEP 3] Clicked 'Send Security Code' — email sent to ki***@agileadapt.com")
                time.sleep(3)
                screenshot(page, "handoff_02_code_sent")

                # Save browser state so we can resume
                context.storage_state(path=STORAGE_STATE_FILE)
                print(f"[STATE SAVED] {STORAGE_STATE_FILE}")

                # Also save cookies separately for robustness
                cookies = context.cookies()
                with open(os.path.join(STATE_DIR, "cookies.json"), "w") as f:
                    json.dump(cookies, f)

                print("\n" + "=" * 60)
                print("VERIFICATION CODE SENT TO EMAIL: ki***@agileadapt.com")
                print("=" * 60)
                print("\nNext step: Run this script with the code:")
                print(f"  python3 {__file__} verify <CODE>")
                print("\nExample:")
                print(f"  python3 {__file__} verify 123456")
                print("=" * 60)

                browser.close()
                return {"status": "code_sent", "next": "provide_code"}
            else:
                print("[ERROR] Could not find Send Security Code button")
                screenshot(page, "handoff_error_no_send_btn")
                browser.close()
                return {"status": "error", "reason": "no_send_button"}
        elif '/dashboard' in page.url or '/v2/' in page.url:
            # No 2FA needed! Save state and proceed
            print("[SUCCESS] Logged in without 2FA!")
            context.storage_state(path=STORAGE_STATE_FILE)
            browser.close()
            return {"status": "logged_in", "next": "generate_key"}
        else:
            print(f"[ERROR] Unexpected state. URL: {page.url}")
            screenshot(page, "handoff_error_unexpected")
            browser.close()
            return {"status": "error", "reason": "unexpected_state", "url": page.url}


def verify_and_generate(code):
    """Step 2: Enter verification code, then navigate to generate API key."""
    from playwright.sync_api import sync_playwright

    if not os.path.exists(STORAGE_STATE_FILE):
        print("[ERROR] No saved browser state. Run 'send' first.")
        return {"status": "error", "reason": "no_state"}

    with sync_playwright() as p:
        browser = p.chromium.launch(
            headless=True,
            args=['--no-sandbox', '--disable-blink-features=AutomationControlled', '--disable-dev-shm-usage']
        )
        context = browser.new_context(
            viewport={'width': 1920, 'height': 1080},
            user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36',
            storage_state=STORAGE_STATE_FILE,
        )
        page = context.new_page()

        # Navigate back to GHL — the stored session should remember our login attempt
        print(f"[STEP 1] Resuming GHL session with verification code: {code}")
        page.goto("https://app.gohighlevel.com/", wait_until="networkidle", timeout=30000)
        time.sleep(3)
        screenshot(page, "verify_01_resumed")

        current_url = page.url
        page_text = page.inner_text('body')
        print(f"  Current URL: {current_url}")

        # Check state — we might need to re-login and re-send code
        if 'verify' in page_text.lower() or 'code' in page_text.lower():
            # We're at the code entry page
            print("[STEP 2] Entering verification code...")

            # Look for the code input field
            code_input = page.query_selector('input[type="text"], input[placeholder*="code" i], input[name="code"], input[type="number"]')
            if code_input:
                code_input.fill(code)
                print(f"  Entered code: {code}")
                time.sleep(0.5)
                screenshot(page, "verify_02_code_entered")

                # Click verify button
                verify_btn = page.query_selector('button:has-text("Verify"), button:has-text("Submit"), button:has-text("Confirm"), button[type="submit"]')
                if verify_btn:
                    verify_btn.click()
                    print("  Clicked Verify")
                    time.sleep(5)
                    screenshot(page, "verify_03_after_verify")
                else:
                    print("[ERROR] No verify button found")
                    screenshot(page, "verify_error_no_btn")
                    browser.close()
                    return {"status": "error", "reason": "no_verify_button"}
            else:
                print("[ERROR] No code input field found")
                screenshot(page, "verify_error_no_input")
                # Dump page text for debugging
                print(f"[DEBUG] Page text: {page_text[:1000]}")
                browser.close()
                return {"status": "error", "reason": "no_code_input"}

        elif 'login' in current_url.lower() or 'sign in' in page_text.lower():
            # Session expired, need to re-login
            print("[INFO] Session expired. Re-logging in...")

            email_input = page.query_selector('input[type="email"]')
            if email_input:
                email_input.fill(GHL_EMAIL)
                password_input = page.query_selector('input[type="password"]')
                password_input.fill(GHL_PASSWORD)
                sign_in_btn = page.query_selector('button[type="submit"]')
                sign_in_btn.click()
                time.sleep(5)
                screenshot(page, "verify_01b_relogin")

                # Check for verification again
                page_text = page.inner_text('body')
                if 'verify' in page_text.lower() or 'security code' in page_text.lower():
                    # Need to send code again and enter it
                    send_btn = page.query_selector('button:has-text("Send Security Code")')
                    if send_btn:
                        send_btn.click()
                        time.sleep(3)

                    code_input = page.query_selector('input[type="text"], input[placeholder*="code" i], input[type="number"]')
                    if code_input:
                        code_input.fill(code)
                        verify_btn = page.query_selector('button:has-text("Verify"), button[type="submit"]')
                        if verify_btn:
                            verify_btn.click()
                            time.sleep(5)
                            screenshot(page, "verify_03b_after_verify")

        # Check if we're now in the dashboard
        current_url = page.url
        print(f"[STEP 3] After verification, URL: {current_url}")
        screenshot(page, "verify_04_post_auth")

        if '/dashboard' in current_url or '/v2/' in current_url:
            print("  Successfully authenticated!")
        else:
            page_text = page.inner_text('body')
            print(f"[WARNING] May not be fully authenticated. URL: {current_url}")
            print(f"[DEBUG] Page text: {page_text[:500]}")

        # ===== Navigate to sub-account settings =====
        print("[STEP 4] Navigating to sub-account API settings...")
        settings_url = f"https://app.gohighlevel.com/v2/location/{TARGET_LOCATION_ID}/settings/integrations"
        page.goto(settings_url, wait_until="networkidle", timeout=30000)
        time.sleep(3)
        screenshot(page, "verify_05_settings")

        current_url = page.url
        print(f"  Current URL: {current_url}")

        if 'login' in current_url.lower():
            print("[ERROR] Not authenticated — redirected to login")
            browser.close()
            return {"status": "error", "reason": "not_authenticated"}

        # Look for Private Integration or API Keys section
        page_text = page.inner_text('body')
        print(f"[STEP 5] Looking for API/Integration options...")
        screenshot(page, "verify_06_integrations")

        # Check if there's a "Private Integrations" section (newer GHL)
        # or "API Key" section (legacy GHL)

        # Try clicking on various tabs/links
        for selector_text in ['Private Integrations', 'API Keys', 'API Key', 'API', 'Integrations']:
            els = page.query_selector_all(f'a:has-text("{selector_text}"), button:has-text("{selector_text}"), div:has-text("{selector_text}"), span:has-text("{selector_text}")')
            if els:
                for el in els:
                    text = el.inner_text().strip()
                    if text and selector_text.lower() in text.lower() and len(text) < 50:
                        print(f"  Found and clicking: '{text}'")
                        try:
                            el.click()
                            time.sleep(2)
                            screenshot(page, f"verify_07_clicked_{selector_text.replace(' ','_')}")
                        except Exception:
                            pass
                        break

        # Look for "Create" or "Generate" button
        time.sleep(2)
        screenshot(page, "verify_08_pre_create")

        create_btns = page.query_selector_all('button:has-text("Create"), button:has-text("Generate"), button:has-text("Add")')
        for btn in create_btns:
            text = btn.inner_text().strip()
            if any(kw in text.lower() for kw in ['create', 'generate', 'add new']):
                print(f"  Clicking create button: '{text}'")
                btn.click()
                time.sleep(2)
                screenshot(page, "verify_09_create_modal")
                break

        # Fill in name if modal appeared
        time.sleep(1)
        name_inputs = page.query_selector_all('input[type="text"]')
        for inp in name_inputs:
            placeholder = inp.get_attribute('placeholder') or ''
            if 'name' in placeholder.lower() or not placeholder:
                inp.fill(INTEGRATION_NAME)
                print(f"  Filled name: {INTEGRATION_NAME}")
                screenshot(page, "verify_10_named")
                break

        # Click save/confirm
        save_btns = page.query_selector_all('button:has-text("Save"), button:has-text("Create"), button:has-text("Submit"), button:has-text("Generate")')
        for btn in save_btns:
            text = btn.inner_text().strip()
            visible = btn.is_visible()
            if visible and any(kw in text.lower() for kw in ['save', 'create', 'submit']):
                print(f"  Clicking: '{text}'")
                btn.click()
                time.sleep(3)
                screenshot(page, "verify_11_saved")
                break

        # Extract API key
        time.sleep(2)
        page_text = page.inner_text('body')

        # Look for pit- pattern
        pit_match = re.search(r'pit-[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}', page_text)
        if pit_match:
            api_key = pit_match.group(0)
            print(f"\n[SUCCESS] API Key: {api_key}")
            screenshot(page, "verify_12_key_found")

            # Save state for future use
            context.storage_state(path=STORAGE_STATE_FILE)

            browser.close()
            return {"status": "success", "api_key": api_key}

        # Check inputs for key
        all_inputs = page.query_selector_all('input')
        for inp in all_inputs:
            try:
                val = inp.input_value()
                if val and ('pit-' in val or (len(val) > 30 and '-' in val)):
                    print(f"\n[SUCCESS] API Key from input: {val}")
                    browser.close()
                    return {"status": "success", "api_key": val.strip()}
            except Exception:
                pass

        # Dump final state
        print("\n[INFO] Could not automatically extract API key")
        print(f"[INFO] Final URL: {page.url}")
        print(f"[INFO] Page text (first 2000 chars):\n{page_text[:2000]}")
        screenshot(page, "verify_13_final")

        # Save state for manual inspection
        context.storage_state(path=STORAGE_STATE_FILE)

        browser.close()
        return {"status": "incomplete", "reason": "could_not_extract_key", "url": page.url}


def main():
    if len(sys.argv) < 2:
        print("Usage:")
        print(f"  python3 {__file__} send          # Send verification code")
        print(f"  python3 {__file__} verify <CODE>  # Enter code and generate key")
        sys.exit(1)

    action = sys.argv[1]

    if action == "send":
        result = send_verification_code()
    elif action == "verify":
        if len(sys.argv) < 3:
            print("ERROR: Provide the verification code")
            print(f"  python3 {__file__} verify 123456")
            sys.exit(1)
        code = sys.argv[2]
        result = verify_and_generate(code)
    else:
        print(f"Unknown action: {action}")
        sys.exit(1)

    print(f"\n[RESULT] {json.dumps(result, indent=2)}")


if __name__ == "__main__":
    main()
