"""
VentraIP DNS Configuration via Browser Automation
===================================================
Logs into VIPcontrol, navigates to each domain's DNS panel,
and adds A + CNAME records pointing to Netlify.

For each domain:
  - A record:     @ → 75.2.60.5 (Netlify load balancer)
  - CNAME record:  www → {site}.netlify.app

Usage:
    python3 ventraip_dns_config.py                    # All 38 VentraIP domains
    python3 ventraip_dns_config.py --domain sydneychatbots.com.au  # Single domain
    python3 ventraip_dns_config.py --dry-run           # Explore without changes
    python3 ventraip_dns_config.py --headed             # Show browser window
"""

import argparse
import json
import os
import re
import sys
import time
from pathlib import Path
from playwright.sync_api import sync_playwright, Page, BrowserContext

VENTRAIP_LOGIN_URL = "https://vip.ventraip.com.au/login/"
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"
OUTPUT_DIR = Path("/mnt/e/genesis-system/scripts/gold_pipeline/output")
SCREENSHOT_DIR = OUTPUT_DIR / "ventraip_screenshots"

# Domain → Netlify site mapping (loaded from manifest)
DOMAIN_MAP = {}


def extract_netlify_subdomain(netlify_url: str) -> str:
    """Extract site subdomain from Netlify URL."""
    match = re.search(r"https://([^.]+)\.netlify\.app", netlify_url)
    return match.group(1) if match else ""


def load_domain_map():
    """Load domain → Netlify subdomain mapping."""
    global DOMAIN_MAP
    with open(MANIFEST_PATH) as f:
        manifest = json.load(f)

    # VentraIP domains only (Tiers 4-9)
    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",
    ]

    for domain in ventraip_domains:
        if domain in manifest:
            DOMAIN_MAP[domain] = extract_netlify_subdomain(manifest[domain])


def login(page: Page) -> bool:
    """Login to VentraIP VIPcontrol."""
    print("[LOGIN] Navigating to VIPcontrol...")
    page.goto(VENTRAIP_LOGIN_URL, timeout=60000)
    page.wait_for_load_state("networkidle", timeout=30000)

    # Fill email
    email_input = page.query_selector('input[name="email"], input[type="email"], #email')
    if email_input:
        email_input.fill(VENTRAIP_EMAIL)
    else:
        print("[LOGIN] Could not find email input")
        page.screenshot(path=str(SCREENSHOT_DIR / "login_no_email.png"))
        return False

    # Fill password
    pass_input = page.query_selector('input[name="password"], input[type="password"], #password')
    if pass_input:
        pass_input.fill(VENTRAIP_PASSWORD)
    else:
        print("[LOGIN] Could not find password input")
        page.screenshot(path=str(SCREENSHOT_DIR / "login_no_password.png"))
        return False

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

    # Click login button
    login_btn = (
        page.query_selector('button:has-text("Login")')
        or page.query_selector('button:has-text("Sign In")')
        or page.query_selector('button[type="submit"]')
        or page.query_selector('input[type="submit"]')
    )
    if login_btn:
        login_btn.click()
    else:
        page.keyboard.press("Enter")

    # Wait for navigation
    page.wait_for_timeout(5000)
    page.wait_for_load_state("networkidle", timeout=30000)
    page.screenshot(path=str(SCREENSHOT_DIR / "login_result.png"))

    current_url = page.url
    print(f"[LOGIN] URL after login: {current_url}")

    # Check if login succeeded (should redirect away from login page)
    if "login" not in current_url.lower() or "dashboard" in current_url.lower():
        print("[LOGIN] Success!")
        return True
    else:
        print("[LOGIN] May have failed — still on login page")
        return False


def navigate_to_domain_dns(page: Page, domain: str) -> bool:
    """Navigate to a domain's DNS management page in VIPcontrol."""
    # VIPcontrol typically has domain management at:
    # https://vip.ventraip.com.au/domains/{domain}/dns
    # or via the domains list page

    # Try direct URL first
    dns_url = f"https://vip.ventraip.com.au/domains/{domain}/dns"
    print(f"[DNS] Navigating to {dns_url}")
    page.goto(dns_url, timeout=30000)
    page.wait_for_load_state("networkidle", timeout=20000)
    page.wait_for_timeout(2000)

    current_url = page.url
    print(f"[DNS] Landed on: {current_url}")
    page.screenshot(path=str(SCREENSHOT_DIR / f"dns_{domain.replace('.', '_')}.png"))

    # Check if we're on a DNS page
    page_content = page.content()
    if "dns" in current_url.lower() or "DNS" in page_content or "records" in page_content.lower():
        return True

    # Try alternative URL pattern
    alt_url = f"https://vip.ventraip.com.au/domain/{domain}/dns"
    print(f"[DNS] Trying alternative: {alt_url}")
    page.goto(alt_url, timeout=30000)
    page.wait_for_load_state("networkidle", timeout=20000)
    page.wait_for_timeout(2000)
    page.screenshot(path=str(SCREENSHOT_DIR / f"dns_alt_{domain.replace('.', '_')}.png"))

    return "dns" in page.url.lower()


def intercept_api_calls(page: Page):
    """Monitor network requests to discover VIPcontrol API endpoints."""
    api_calls = []

    def on_request(request):
        try:
            url = request.url
            if "api" in url.lower() or "dns" in url.lower():
                post_data = None
                try:
                    post_data = request.post_data
                except Exception:
                    post_data = "(binary)"
                api_calls.append({
                    "url": url,
                    "method": request.method,
                    "post_data": post_data,
                })
        except Exception:
            pass

    page.on("request", on_request)
    return api_calls


def explore_dns_page(page: Page, domain: str):
    """Explore DNS page structure to understand form elements."""
    print(f"\n[EXPLORE] Analyzing DNS page for {domain}")

    # Get all form elements
    inputs = page.query_selector_all("input, select, textarea, button")
    for inp in inputs:
        tag = inp.evaluate("el => el.tagName")
        name = inp.get_attribute("name") or ""
        type_ = inp.get_attribute("type") or ""
        placeholder = inp.get_attribute("placeholder") or ""
        text = inp.inner_text() if tag == "BUTTON" else ""
        if name or type_ or placeholder or text:
            print(f"  {tag}: name={name} type={type_} placeholder={placeholder} text={text[:50]}")

    # Get page title and headings
    headings = page.query_selector_all("h1, h2, h3")
    for h in headings:
        print(f"  HEADING: {h.inner_text()[:80]}")

    # Look for DNS record type dropdowns
    selects = page.query_selector_all("select")
    for s in selects:
        name = s.get_attribute("name") or ""
        options = s.query_selector_all("option")
        opts_text = [o.inner_text() for o in options[:10]]
        print(f"  SELECT: name={name} options={opts_text}")

    # Look for "Add Record" buttons
    add_btns = page.query_selector_all('button:has-text("Add"), a:has-text("Add"), button:has-text("Create")')
    for btn in add_btns:
        print(f"  ADD BUTTON: {btn.inner_text()[:50]}")


def add_dns_record_via_ui(page: Page, domain: str, record_type: str, name: str, value: str, ttl: int = 3600) -> bool:
    """Add a DNS record through VIPcontrol UI."""
    print(f"[ADD] {record_type} record: {name}.{domain} → {value}")

    # Look for "Add Record" button
    add_btn = (
        page.query_selector('button:has-text("Add Record")')
        or page.query_selector('button:has-text("Add DNS Record")')
        or page.query_selector('a:has-text("Add Record")')
        or page.query_selector('button:has-text("Add")')
    )

    if add_btn:
        add_btn.click()
        page.wait_for_timeout(1000)

    # Select record type
    type_select = page.query_selector('select[name*="type"], select[name*="record_type"]')
    if type_select:
        type_select.select_option(value=record_type)
        page.wait_for_timeout(500)

    # Fill name/hostname
    name_input = page.query_selector('input[name*="name"], input[name*="hostname"], input[name*="host"], input[placeholder*="Name"]')
    if name_input:
        name_input.fill(name)

    # Fill value/content
    value_input = page.query_selector('input[name*="content"], input[name*="value"], input[name*="address"], input[name*="target"], input[placeholder*="Content"], input[placeholder*="Value"]')
    if value_input:
        value_input.fill(value)

    # Fill TTL if available
    ttl_input = page.query_selector('input[name*="ttl"], select[name*="ttl"]')
    if ttl_input:
        tag = ttl_input.evaluate("el => el.tagName")
        if tag == "SELECT":
            ttl_input.select_option(value=str(ttl))
        else:
            ttl_input.fill(str(ttl))

    page.screenshot(path=str(SCREENSHOT_DIR / f"add_{record_type}_{domain.replace('.', '_')}.png"))

    # Submit
    submit_btn = (
        page.query_selector('button:has-text("Save")')
        or page.query_selector('button:has-text("Add")')
        or page.query_selector('button:has-text("Create")')
        or page.query_selector('button[type="submit"]')
    )
    if submit_btn:
        submit_btn.click()
        page.wait_for_timeout(2000)
        page.screenshot(path=str(SCREENSHOT_DIR / f"after_add_{record_type}_{domain.replace('.', '_')}.png"))
        return True

    print(f"[ADD] Could not find submit button for {record_type} record")
    return False


def configure_domain_dns(page: Page, domain: str, netlify_subdomain: str, dry_run: bool = False) -> dict:
    """Configure DNS for a single domain."""
    result = {"domain": domain, "status": "unknown", "a_record": False, "cname_record": False}

    if not navigate_to_domain_dns(page, domain):
        result["status"] = "navigation_failed"
        return result

    if dry_run:
        explore_dns_page(page, domain)
        result["status"] = "explored"
        return result

    # Add A record: @ → 75.2.60.5
    a_ok = add_dns_record_via_ui(page, domain, "A", "@", NETLIFY_A_RECORD)
    result["a_record"] = a_ok

    page.wait_for_timeout(1000)

    # Add CNAME record: www → {site}.netlify.app
    cname_value = f"{netlify_subdomain}.netlify.app"
    cname_ok = add_dns_record_via_ui(page, domain, "CNAME", "www", cname_value)
    result["cname_record"] = cname_ok

    result["status"] = "configured" if (a_ok and cname_ok) else "partial"
    return result


def main():
    parser = argparse.ArgumentParser(description="VentraIP DNS Configuration")
    parser.add_argument("--domain", help="Single domain to configure")
    parser.add_argument("--dry-run", action="store_true", help="Explore without making changes")
    parser.add_argument("--headed", action="store_true", help="Show browser window")
    parser.add_argument("--explore-first", action="store_true", help="Explore first domain only to understand UI")
    args = parser.parse_args()

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

    # Filter domains
    if args.domain:
        if args.domain not in DOMAIN_MAP:
            print(f"Domain {args.domain} not in VentraIP mapping")
            sys.exit(1)
        domains = {args.domain: DOMAIN_MAP[args.domain]}
    else:
        domains = DOMAIN_MAP

    print(f"\n{'='*60}")
    print(f"VentraIP DNS Configuration — {len(domains)} domains")
    print(f"Mode: {'DRY RUN' if args.dry_run else 'LIVE'}")
    print(f"{'='*60}\n")

    with sync_playwright() as p:
        browser = p.chromium.launch(
            headless=not args.headed,
            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/120.0.0.0 Safari/537.36",
            viewport={"width": 1920, "height": 1080},
        )
        page = context.new_page()

        # Monitor API calls
        api_calls = intercept_api_calls(page)

        # Login
        if not login(page):
            print("[ERROR] Login failed. Check credentials and screenshots.")
            browser.close()
            sys.exit(1)

        # If explore-first, just look at the first domain
        if args.explore_first:
            first_domain = list(domains.keys())[0]
            print(f"\n[EXPLORE] Exploring {first_domain}...")
            navigate_to_domain_dns(page, first_domain)
            explore_dns_page(page, first_domain)

            # Dump intercepted API calls
            if api_calls:
                print(f"\n[API] Intercepted {len(api_calls)} API calls:")
                for call in api_calls:
                    print(f"  {call['method']} {call['url']}")
                    if call['post_data']:
                        print(f"    POST data: {call['post_data'][:200]}")

            api_path = SCREENSHOT_DIR / "api_calls.json"
            with open(api_path, "w") as f:
                json.dump(api_calls, f, indent=2, default=str)
            print(f"\nAPI calls saved: {api_path}")

            browser.close()
            return

        # Configure each domain
        results = []
        for i, (domain, netlify_sub) in enumerate(domains.items(), 1):
            print(f"\n[{i}/{len(domains)}] {domain} → {netlify_sub}.netlify.app")
            result = configure_domain_dns(page, domain, netlify_sub, dry_run=args.dry_run)
            results.append(result)
            print(f"  Status: {result['status']}")

            if i < len(domains):
                time.sleep(1)  # Don't hammer the server

        browser.close()

    # Save results
    results_path = OUTPUT_DIR / "ventraip_dns_results.json"
    with open(results_path, "w") as f:
        json.dump(results, f, indent=2)

    # Summary
    configured = sum(1 for r in results if r["status"] == "configured")
    partial = sum(1 for r in results if r["status"] == "partial")
    failed = sum(1 for r in results if r["status"] in ("navigation_failed", "unknown"))

    print(f"\n{'='*60}")
    print(f"RESULTS: {configured} configured, {partial} partial, {failed} failed")
    print(f"Results saved: {results_path}")
    print(f"Screenshots: {SCREENSHOT_DIR}")
    print(f"{'='*60}")

    # Dump API calls for analysis
    if api_calls:
        api_path = OUTPUT_DIR / "ventraip_api_calls.json"
        with open(api_path, "w") as f:
            json.dump(api_calls, f, indent=2, default=str)
        print(f"API calls captured: {api_path}")


if __name__ == "__main__":
    main()
