"""
VentraIP DNS Config — V3 (API + Browser Hybrid)
=================================================
Uses browser for login/2FA, then uses API calls for DNS operations.
Much faster and more reliable than UI navigation.

Strategy:
1. Browser (stealth) handles login + 2FA
2. After auth, extract session cookies
3. Discover API endpoints (try new /api/ and old /home/ paths)
4. Use API to add DNS records for all domains

Usage:
    python3 ventraip_api.py                  # Login + discover API + explore
    python3 ventraip_api.py --configure      # Login + configure all domains
    python3 ventraip_api.py --code 123456    # Pre-provide 2FA code
"""

import argparse
import json
import re
import sys
import time
from pathlib import Path

import requests
from playwright.sync_api import sync_playwright
from playwright_stealth import Stealth

VENTRAIP_EMAIL = "kinan@protonmail.com"
VENTRAIP_PASSWORD = "9iphQKcIv0#2J0Ce"
NETLIFY_A_RECORD = "75.2.60.5"

MANIFEST_PATH = "/mnt/e/genesis-system/scripts/gold_pipeline/output/deployment_manifest.json"
SCREENSHOT_DIR = Path("/mnt/e/genesis-system/scripts/gold_pipeline/output/ventraip_screenshots")
OUTPUT_DIR = Path("/mnt/e/genesis-system/scripts/gold_pipeline/output")
CODE_FILE = OUTPUT_DIR / "ventraip_2fa_code.txt"

SCREENSHOT_DIR.mkdir(parents=True, exist_ok=True)

VENTRAIP_DOMAINS = [
    "sydneychatbots.com.au", "brisbanechatbots.com.au", "melbournechatbots.com.au",
    "adelaidechatbots.com.au", "cairnschatbots.com.au", "sunshinecoastchatbots.com.au",
    "townsvillechatbots.com.au", "darwinchatbots.com.au", "aichatbotsbrisbane.au",
    "aichatbotsaustralia.au",
    "tradiechatbots.com.au", "tradiechatbot.com.au", "tradiesvoice.com.au",
    "tradieautomation.com.au", "aitradie.au", "sparkybots.com.au", "plumberbots.com.au",
    "hvacbots.com.au", "electricianbotai.au", "solarbotai.au", "mechanicbot.au",
    "locksmithbot.au", "rooferbot.au",
    "receptionistai.au", "beautybot.com.au", "propertybotai.com.au", "propertybotai.au",
    "dentalbotai.au", "clinicaibot.au", "lawyerbot.au", "legalbotai.au", "rentbot.au",
    "voiceassistant.com.au", "voiceassistant.au", "aivoicereceptionist.au",
    "phonebot.au", "talkbot.au", "bookingbot.au",
]


def get_domain_map():
    with open(MANIFEST_PATH) as f:
        manifest = json.load(f)
    result = {}
    for domain in VENTRAIP_DOMAINS:
        if domain in manifest:
            match = re.search(r"https://([^.]+)\.netlify\.app", manifest[domain])
            if match:
                result[domain] = match.group(1)
    return result


def wait_for_code(timeout_secs=300) -> str:
    if CODE_FILE.exists():
        CODE_FILE.unlink()
    print(f"WAITING_FOR_CODE:{CODE_FILE}")
    sys.stdout.flush()
    start = time.time()
    while time.time() - start < timeout_secs:
        if CODE_FILE.exists():
            code = CODE_FILE.read_text().strip()
            if code:
                CODE_FILE.unlink()
                return code
        time.sleep(0.5)
    return ""


def browser_login(code=None):
    """Login via stealth browser, return session cookies on success."""
    with sync_playwright() as pw:
        browser = pw.chromium.launch(
            headless=True,
            args=["--no-sandbox", "--disable-blink-features=AutomationControlled"],
        )
        context = browser.new_context(
            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",
            viewport={"width": 1920, "height": 1080},
            locale="en-AU",
            timezone_id="Australia/Brisbane",
        )
        page = context.new_page()

        stealth = Stealth()
        stealth.apply_stealth_sync(page)
        page.add_init_script("""
            Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
            window.chrome = { runtime: {}, loadTimes: function(){}, csi: function(){} };
            Object.defineProperty(navigator, 'languages', { get: () => ['en-AU', 'en-US', 'en'] });
            Object.defineProperty(navigator, 'platform', { get: () => 'Win32' });
        """)

        # LOGIN
        print("[LOGIN] Navigating to VIPcontrol...")
        sys.stdout.flush()
        page.goto("https://vip.ventraip.com.au/login/", timeout=60000)
        page.wait_for_timeout(3000)

        page.mouse.move(500, 400)
        page.wait_for_timeout(300)

        email_input = page.query_selector('input[name="email"], input[type="email"]')
        if email_input:
            email_input.click()
            page.wait_for_timeout(200)
            email_input.type(VENTRAIP_EMAIL, delay=50)

        page.wait_for_timeout(300)

        pass_input = page.query_selector('input[name="password"], input[type="password"]')
        if pass_input:
            pass_input.click()
            page.wait_for_timeout(200)
            pass_input.type(VENTRAIP_PASSWORD, delay=30)

        page.wait_for_timeout(500)

        btn = page.query_selector('button:has-text("Login")') or page.query_selector('button[type="submit"]')
        if btn:
            btn.hover()
            page.wait_for_timeout(200)
            btn.click()

        print("[LOGIN] Waiting for 2FA...")
        sys.stdout.flush()
        page.wait_for_timeout(6000)

        content = page.content()

        if "two-factor" in content.lower() or "authentication" in content.lower() or "verify" in content.lower():
            print("[2FA] Code required. Check kinan@protonmail.com")
            sys.stdout.flush()

            if not code:
                code = wait_for_code(timeout_secs=300)
            if not code:
                print("[2FA] No code received")
                sys.stdout.flush()
                browser.close()
                return None

            print(f"[2FA] Entering code: {code}")
            sys.stdout.flush()

            code_input = (
                page.query_selector('input[placeholder*="Authentication"]')
                or page.query_selector('input[placeholder*="Code"]')
                or page.query_selector('input[placeholder*="code"]')
                or page.query_selector('input[name*="code"]')
                or page.query_selector('input[name*="token"]')
            )
            if not code_input:
                inputs = page.query_selector_all('input[type="text"], input[type="number"], input:not([type])')
                for inp in inputs:
                    if inp.is_visible():
                        code_input = inp
                        break

            if not code_input:
                print("[2FA] Could not find code input")
                sys.stdout.flush()
                browser.close()
                return None

            code_input.click()
            page.wait_for_timeout(300)
            code_input.type(code, delay=80)
            page.wait_for_timeout(800)

            verify_btn = (
                page.query_selector('button:has-text("Verify")')
                or page.query_selector('button:has-text("Login")')
                or page.query_selector('button[type="submit"]')
            )
            if verify_btn:
                verify_btn.hover()
                page.wait_for_timeout(300)
                verify_btn.click()

            page.wait_for_timeout(10000)
            page.screenshot(path=str(SCREENSHOT_DIR / "v3_after_2fa.png"))

            url = page.url
            print(f"[2FA] URL: {url}")
            sys.stdout.flush()

            if "login" in url.lower() and "dashboard" not in url.lower():
                print("[2FA] FAILED")
                sys.stdout.flush()
                browser.close()
                return None

        print("[LOGIN] SUCCESS!")
        sys.stdout.flush()

        # EXTRACT COOKIES
        cookies = context.cookies()
        cookie_dict = {}
        for c in cookies:
            cookie_dict[c["name"]] = c["value"]

        print(f"[COOKIES] Extracted {len(cookies)} cookies")
        sys.stdout.flush()

        # Also try API discovery from within the browser
        print("[API] Discovering API endpoints from authenticated browser...")
        sys.stdout.flush()

        # Try fetching domain list via various API paths
        api_discovery = {}
        for api_path in [
            "/api/domains",
            "/api/domain",
            "/api/services",
            "/api/products",
            "/home/domain/",
            "/api/v1/domains",
        ]:
            try:
                resp = page.evaluate(f"""
                    async () => {{
                        try {{
                            const r = await fetch('{api_path}', {{credentials: 'include'}});
                            return {{status: r.status, url: r.url, text: (await r.text()).substring(0, 2000)}};
                        }} catch(e) {{
                            return {{error: e.message}};
                        }}
                    }}
                """)
                api_discovery[api_path] = resp
                status = resp.get("status", "error")
                print(f"  {api_path} → {status}")
                sys.stdout.flush()
            except Exception as e:
                print(f"  {api_path} → exception: {e}")
                sys.stdout.flush()

        # Save API discovery results
        discovery_path = OUTPUT_DIR / "ventraip_api_discovery.json"
        with open(discovery_path, "w") as f:
            json.dump(api_discovery, f, indent=2, default=str)
        print(f"[API] Discovery saved to {discovery_path}")
        sys.stdout.flush()

        # Try to get the dashboard HTML to find domain IDs
        page.goto("https://vip.ventraip.com.au/", timeout=30000)
        page.wait_for_timeout(3000)

        # Click SHOW ALL DOMAINS
        show_all = page.query_selector('a:has-text("SHOW ALL DOMAINS")') or page.query_selector('button:has-text("SHOW ALL")')
        if show_all:
            show_all.click()
            page.wait_for_timeout(3000)
            print("[DASHBOARD] Expanded all domains")
            sys.stdout.flush()

        page.screenshot(path=str(SCREENSHOT_DIR / "v3_dashboard.png"))

        # Extract domain rows with their DNS link hrefs
        domain_info = page.evaluate("""
            () => {
                const results = [];
                // Find all links/buttons with text "DNS"
                const dnsElements = document.querySelectorAll('a, button');
                for (const el of dnsElements) {
                    if (el.textContent.trim() === 'DNS' || el.textContent.trim().includes('DNS')) {
                        const href = el.getAttribute('href') || '';
                        // Get the parent row's text to find the domain name
                        let row = el.closest('tr') || el.closest('[class*="row"]') || el.parentElement?.parentElement;
                        let rowText = row ? row.textContent : '';
                        results.push({
                            href: href,
                            tag: el.tagName,
                            text: el.textContent.trim(),
                            rowText: rowText.substring(0, 200),
                        });
                    }
                }
                return results;
            }
        """)

        print(f"[DASHBOARD] Found {len(domain_info)} DNS elements")
        sys.stdout.flush()

        # Save domain info
        domain_info_path = OUTPUT_DIR / "ventraip_domain_info.json"
        with open(domain_info_path, "w") as f:
            json.dump(domain_info, f, indent=2)

        # Print first few for debugging
        for item in domain_info[:5]:
            print(f"  href={item['href'][:80]}, tag={item['tag']}, row={item['rowText'][:60]}")
            sys.stdout.flush()

        # Now navigate to ONE domain's DNS page to understand the layout
        if domain_info:
            first = domain_info[0]
            if first["href"]:
                href = first["href"]
                full_url = href if href.startswith("http") else f"https://vip.ventraip.com.au{href}"
                print(f"\n[EXPLORE] Navigating to first DNS page: {full_url}")
                sys.stdout.flush()
                page.goto(full_url, timeout=30000)
                page.wait_for_timeout(3000)
                page.screenshot(path=str(SCREENSHOT_DIR / "v3_dns_page.png"))
                print(f"[EXPLORE] DNS page URL: {page.url}")
                sys.stdout.flush()

                # Save HTML
                html = page.content()
                html_path = SCREENSHOT_DIR / "v3_dns_page.html"
                html_path.write_text(html[:200000], encoding="utf-8")

                # Try to find the DNS API from this page
                dns_api = page.evaluate("""
                    () => {
                        // Check for any form actions
                        const forms = document.querySelectorAll('form');
                        const formData = [];
                        for (const f of forms) {
                            formData.push({action: f.action, method: f.method, id: f.id});
                        }

                        // Check for any fetch/XHR interceptors or data attributes
                        const inputs = document.querySelectorAll('input, select, button');
                        const inputData = [];
                        for (const i of inputs) {
                            inputData.push({
                                tag: i.tagName,
                                type: i.type,
                                name: i.name,
                                id: i.id,
                                placeholder: i.placeholder,
                                value: i.value?.substring(0, 50),
                                className: i.className?.substring(0, 50),
                            });
                        }

                        return {forms: formData, inputs: inputData};
                    }
                """)
                dns_api_path = OUTPUT_DIR / "ventraip_dns_page_elements.json"
                with open(dns_api_path, "w") as f:
                    json.dump(dns_api, f, indent=2)
                print(f"[EXPLORE] DNS page elements saved to {dns_api_path}")
                sys.stdout.flush()

        browser.close()

        return {
            "cookies": cookie_dict,
            "domain_info": domain_info,
            "api_discovery": api_discovery,
        }


def configure_dns_api(session_data, domain_map, configure=False):
    """Use discovered API to configure DNS records."""
    if not session_data:
        print("[ERROR] No session data")
        return

    domain_info = session_data.get("domain_info", [])
    api_discovery = session_data.get("api_discovery", {})

    # Build a map of domain name → DNS href
    dns_href_map = {}
    for item in domain_info:
        row_text = item.get("rowText", "")
        href = item.get("href", "")
        for domain in VENTRAIP_DOMAINS:
            if domain in row_text:
                dns_href_map[domain] = href
                break

    print(f"\n[DNS MAP] Matched {len(dns_href_map)} domains to DNS hrefs")
    sys.stdout.flush()

    # Save the map
    map_path = OUTPUT_DIR / "ventraip_dns_href_map.json"
    with open(map_path, "w") as f:
        json.dump(dns_href_map, f, indent=2)

    for domain, href in list(dns_href_map.items())[:3]:
        print(f"  {domain} → {href}")
    sys.stdout.flush()


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--configure", action="store_true")
    parser.add_argument("--code", help="Pre-provide 2FA code")
    args = parser.parse_args()

    domain_map = get_domain_map()
    print(f"[INIT] {len(domain_map)} domains in deployment manifest")
    sys.stdout.flush()

    # Phase 1: Browser login + API discovery
    session_data = browser_login(code=args.code)

    if not session_data:
        print("[FATAL] Login failed")
        sys.stdout.flush()
        return

    # Phase 2: Configure DNS via API
    configure_dns_api(session_data, domain_map, configure=args.configure)


if __name__ == "__main__":
    main()
