"""
VentraIP DNS Config — FINAL
=============================
1. Stealth browser login + 2FA (proven)
2. Extract DNS link hrefs from dashboard (no URL guessing)
3. Navigate to each DNS page via href
4. Add A record + CNAME record

Usage:
    python3 ventraip_final.py                  # Login + explore
    python3 ventraip_final.py --configure      # Login + configure ALL
    python3 ventraip_final.py --code 123456    # Pre-provide 2FA code
"""

import argparse
import json
import re
import sys
import time
from pathlib import Path
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 flush():
    sys.stdout.flush()


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}")
    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 do_login(page, code=None):
    """Handle full login + 2FA flow. Returns True on success."""
    print("[LOGIN] Navigating to VIPcontrol..."); flush()
    page.goto("https://vip.ventraip.com.au/login/", timeout=60000)
    page.wait_for_timeout(3000)

    # Human-like mouse
    page.mouse.move(500, 400); page.wait_for_timeout(300)

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

    page.wait_for_timeout(300)

    pwd = page.query_selector('input[name="password"], input[type="password"]')
    if pwd:
        pwd.click(); page.wait_for_timeout(200)
        pwd.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..."); 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"); flush()

        if not code:
            code = wait_for_code(timeout_secs=300)
        if not code:
            print("[2FA] No code received"); flush()
            return False

        print(f"[2FA] Entering code: {code}"); flush()

        ci = (
            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 ci:
            for inp in page.query_selector_all('input[type="text"], input[type="number"], input:not([type])'):
                if inp.is_visible():
                    ci = inp; break
        if not ci:
            print("[2FA] No code input found"); flush()
            return False

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

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

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

        if "login" in page.url.lower() and "dashboard" not in page.url.lower():
            print("[2FA] FAILED — still on login page"); flush()
            return False

    print("[LOGIN] SUCCESS!"); flush()
    return True


def expand_dashboard(page):
    """Ensure all domains are visible on the dashboard.
    IMPORTANT: Don't navigate away — SPA loses domain data on fresh load."""

    page.screenshot(path=str(SCREENSHOT_DIR / "final_pre_extract.png"))
    print(f"[DASHBOARD] Current URL: {page.url}"); flush()

    has_domains = page.query_selector('text="DNS"') or page.query_selector('text="SHOW ALL DOMAINS"')
    if not has_domains:
        print("[DASHBOARD] Domains not visible yet, waiting..."); flush()
        domains_tab = page.query_selector('text="Domains"')
        if domains_tab:
            domains_tab.click()
            page.wait_for_timeout(5000)
        else:
            page.wait_for_timeout(8000)

    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(5000)
        print("[DASHBOARD] Expanded all domains"); flush()
    else:
        print("[DASHBOARD] No 'SHOW ALL' link found"); flush()

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


def get_visible_domains(page):
    """Get list of OUR domains visible on the dashboard.
    Match against known VENTRAIP_DOMAINS list to avoid junk matches."""
    domain_list = page.evaluate("""
        (knownDomains) => {
            const found = [];
            const bodyText = document.body?.textContent || '';
            for (const domain of knownDomains) {
                if (bodyText.includes(domain)) {
                    found.push(domain);
                }
            }
            return found;
        }
    """, VENTRAIP_DOMAINS)
    return domain_list


def click_dns_for_domain(page, target_domain):
    """Find and click the DNS button for a specific domain on the dashboard.
    Returns True if clicked successfully, False otherwise."""

    clicked = page.evaluate(r"""
        (targetDomain) => {
            // Find all leaf elements with text "DNS"
            const all = document.querySelectorAll('*');
            const dnsButtons = [];
            for (const el of all) {
                if (el.children.length === 0 && el.textContent.trim() === 'DNS') {
                    dnsButtons.push(el);
                }
            }

            for (const btn of dnsButtons) {
                // Walk up to find container with the target domain name
                let container = btn;
                for (let i = 0; i < 10; i++) {
                    container = container.parentElement;
                    if (!container) break;
                    const text = container.textContent || '';
                    if (text.includes(targetDomain)) {
                        // Found it — click the DNS button
                        btn.click();
                        return true;
                    }
                }
            }
            return false;
        }
    """, target_domain)

    if clicked:
        page.wait_for_timeout(5000)
        print(f"  [CLICK] DNS button clicked for {target_domain}"); flush()
        print(f"  [CLICK] Now on: {page.url}"); flush()
    else:
        print(f"  [CLICK] DNS button NOT found for {target_domain}"); flush()

    return clicked


def switch_to_dns_hosting(page, domain_safe):
    """Switch to DNS Hosting tab on the domain manage page.
    This enables VentraIP's free DNS hosting where we can add A/CNAME records.

    CRITICAL FLOW (proven from screenshot analysis):
    1. Click "DNS Hosting" tab
    2. If zone not enabled: click "Enable" button → opens lightbox modal
    3. In lightbox: check the "I understand..." checkbox
    4. Click "Set DNS" button (becomes enabled after checkbox)
    5. Wait for lightbox to close and zone to activate
    6. Now records table is available for Add New Host

    Returns True if DNS Hosting is ready for record management."""

    # Click "DNS Hosting" tab (name="free_dns")
    dns_tab = page.query_selector('button[name="free_dns"]')
    if not dns_tab:
        print("    [TAB] DNS Hosting tab not found"); flush()
        return False

    dns_tab.evaluate("el => el.click()")
    page.wait_for_timeout(3000)
    print("    [TAB] Clicked DNS Hosting tab"); flush()

    # Check if DNS Hosting is already fully enabled (has record table, no Enable button)
    enable_btn = page.query_selector('button:has-text("Enable")')
    has_add_host = page.query_selector('button:has-text("Add New Host")')
    lightbox = page.query_selector('.lightbox__close')

    # If no Enable button and Add New Host is visible, zone is already active
    if not enable_btn and has_add_host and has_add_host.is_visible() and not lightbox:
        print("    [TAB] DNS Hosting already enabled with record table"); flush()
        return True

    # Check if Enable button needs to be clicked
    if enable_btn and enable_btn.is_visible():
        print("    [TAB] Clicking Enable to activate DNS Hosting zone..."); flush()
        enable_btn.evaluate("el => el.click()")
        page.wait_for_timeout(3000)

    # Now handle the lightbox modal: "Current DNS settings will be overridden"
    # The lightbox contains:
    # - Warning text about changing from Custom Nameservers to DNS Hosting
    # - Checkbox: "I understand that DNS Propagation may take up to 1 hour..."
    # - "Set DNS" button (DISABLED until checkbox is checked)
    # - "NO, KEEP MY CURRENT DNS SETTINGS" link

    # Step 1: Find and click the checkbox
    checkbox = page.query_selector('button.CheckBox')
    if not checkbox:
        checkbox = page.query_selector('.CheckBox')
    if checkbox and checkbox.is_visible():
        print("    [TAB] Checking 'I understand' checkbox..."); flush()
        checkbox.evaluate("el => el.click()")
        page.wait_for_timeout(1500)

        # Step 2: Click "Set DNS" button (should now be enabled)
        set_dns_btn = page.query_selector('button:has-text("Set DNS")')
        if set_dns_btn:
            # Wait a moment for the button to become enabled
            page.wait_for_timeout(1000)
            btn_class = set_dns_btn.get_attribute("class") or ""
            if "disabled" in btn_class.lower():
                print("    [TAB] Set DNS still disabled, trying checkbox again..."); flush()
                # Try clicking checkbox via different selector
                page.evaluate("""
                    () => {
                        const cbs = document.querySelectorAll('.CheckBox, [class*="CheckBox"]');
                        for (const cb of cbs) {
                            if (cb.offsetParent !== null) { cb.click(); break; }
                        }
                    }
                """)
                page.wait_for_timeout(1500)

            print("    [TAB] Clicking 'Set DNS' to change nameservers..."); flush()
            set_dns_btn.evaluate("el => el.click()")
            page.wait_for_timeout(8000)  # Wait for NS change + page update
            print("    [TAB] Set DNS clicked, waiting for zone activation..."); flush()
        else:
            print("    [TAB] WARNING: 'Set DNS' button not found"); flush()
    else:
        # No checkbox visible — might be a different dialog or already past this step
        # Try clicking submit button that contains "I understand..."
        submit_btn = page.query_selector('button[type="submit"]')
        if submit_btn and submit_btn.is_visible():
            txt = submit_btn.text_content() or ""
            if "understand" in txt.lower() or "propagation" in txt.lower():
                print(f"    [TAB] Clicking submit: {txt[:50]}"); flush()
                submit_btn.evaluate("el => el.click()")
                page.wait_for_timeout(8000)

    # Close any remaining lightbox
    close_btn = page.query_selector('.lightbox__close')
    if close_btn and close_btn.is_visible():
        print("    [TAB] Closing lightbox..."); flush()
        close_btn.evaluate("el => el.click()")
        page.wait_for_timeout(2000)

    page.screenshot(path=str(SCREENSHOT_DIR / f"final_{domain_safe}_dns_hosting.png"))

    # Verify zone is now active — look for "Add New Host" button
    add_host = page.query_selector('button:has-text("Add New Host")')
    if add_host and add_host.is_visible():
        print("    [TAB] DNS Hosting zone active — record table ready"); flush()
        return True

    # Check if we need to wait more or if tab shows active
    dns_tab2 = page.query_selector('button[name="free_dns"]')
    if dns_tab2:
        cls = dns_tab2.get_attribute("class") or ""
        if "active" in cls.lower():
            print("    [TAB] DNS Hosting tab active"); flush()
            # May need to wait for the zone to load
            page.wait_for_timeout(3000)
            return True

    print("    [TAB] DNS Hosting state unclear — proceeding anyway"); flush()
    return True


def add_dns_record(page, record_type, hostname, value, domain_safe):
    """Add a single DNS record on the DNS Hosting page.

    CRITICAL: Must verify lightbox/modal is closed before attempting.
    VentraIP DNS Hosting form flow:
    1. Click 'Add New Host' button to open inline form row
    2. Select record type from dropdown (A, AAAA, CNAME, MX, TXT, SRV)
    3. Fill hostname input (blank = root domain '@')
    4. Fill value/content input (IP for A, hostname for CNAME)
    5. Click 'Save Changes' or similar save button
    """

    # SAFETY: Ensure no lightbox/modal is blocking the form
    lightbox = page.query_selector('.lightbox__close')
    if lightbox and lightbox.is_visible():
        print("    WARNING: Lightbox still open — closing before add record"); flush()
        lightbox.evaluate("el => el.click()")
        page.wait_for_timeout(2000)

    # Verify "Add New Host" button is actually visible and clickable
    add_btn = None
    for sel in [
        'button:has-text("Add New Host")',
        'button:has-text("Add Record")',
        'button:has-text("Add Host")',
    ]:
        btn = page.query_selector(sel)
        if btn and btn.is_visible():
            add_btn = btn
            break

    if not add_btn:
        print(f"    ERROR: No 'Add New Host' button found — zone may not be enabled"); flush()
        page.screenshot(path=str(SCREENSHOT_DIR / f"final_{domain_safe}_{record_type}_no_add_btn.png"))
        return False

    add_btn.evaluate("el => el.click()")
    page.wait_for_timeout(2000)
    print(f"    Clicked: {add_btn.text_content().strip()[:30]}"); flush()

    page.screenshot(path=str(SCREENSHOT_DIR / f"final_{domain_safe}_{record_type}_form.png"))

    # Dump visible form elements for debugging
    form_els = page.evaluate("""
        () => {
            const els = document.querySelectorAll('input, select, textarea');
            return Array.from(els).filter(e => e.offsetParent !== null).map(e => ({
                tag: e.tagName, type: e.type || '', name: e.name || '',
                placeholder: e.placeholder || '', class: e.className?.substring(0, 60),
                options: e.tagName === 'SELECT' ? Array.from(e.options).map(o => o.text + '=' + o.value) : [],
            }));
        }
    """)
    print(f"    Form fields: {len(form_els)}"); flush()
    for fe in form_els:
        opts = f" opts={fe['options']}" if fe['options'] else ""
        print(f"      {fe['tag']} name={fe['name']} ph={fe['placeholder'][:30]} type={fe['type']}{opts}"); flush()

    if len(form_els) == 0:
        print(f"    ERROR: No form fields visible — Add New Host may not have opened"); flush()
        return False

    # CRITICAL FIX: After "Add New Host", VentraIP adds a new row at the bottom of
    # the record table. The new row contains:
    #   - A <select> for record type (A, AAAA, CNAME, etc.)
    #   - input[name="hostname"] for the subdomain (blank = root @)
    #   - input[name="ip_address"] for the value (IP for A, hostname for CNAME)
    #   - input[name="ttl"] for TTL
    #
    # BUT the page also has OTHER inputs: search, existing record edit fields, etc.
    # We must target the LAST hostname and ip_address inputs (the new record row).

    # Select record type from the LAST visible dropdown (new row's dropdown)
    type_sels = page.query_selector_all('select')
    visible_selects = [s for s in type_sels if s.is_visible()]
    if visible_selects:
        # Use the LAST visible select (new record row)
        last_select = visible_selects[-1]
        opts_text = last_select.evaluate("el => Array.from(el.options).map(o => o.text).join(',')")
        if record_type in opts_text or "A" in opts_text:
            try:
                last_select.select_option(label=record_type)
                print(f"    Selected type: {record_type} (from last dropdown)"); flush()
            except Exception:
                try:
                    last_select.select_option(value=record_type.lower())
                except Exception:
                    last_select.select_option(value=record_type)
            page.wait_for_timeout(1000)  # Wait for form to update after type change

    # Target the LAST input[name="hostname"] — this is the new record's hostname field
    hostname_inputs = page.query_selector_all('input[name="hostname"]')
    visible_hostnames = [i for i in hostname_inputs if i.is_visible()]
    host_inp = visible_hostnames[-1] if visible_hostnames else None

    # Target input[name="ip_address"] — this is the new record's value field
    # After selecting record type, the field name might change for CNAME
    val_inp = None
    for field_name in ['ip_address', 'content', 'target', 'value', 'destination']:
        candidates = page.query_selector_all(f'input[name="{field_name}"]')
        visible = [i for i in candidates if i.is_visible()]
        if visible:
            val_inp = visible[-1]  # Last visible = new record row
            print(f"    Value field: input[name='{field_name}']"); flush()
            break

    if not val_inp:
        # Fallback: look for input with IP/address placeholder
        candidates = page.query_selector_all('input[placeholder*="Address" i], input[placeholder*="IP" i], input[placeholder*="Target" i]')
        visible = [i for i in candidates if i.is_visible()]
        if visible:
            val_inp = visible[-1]

    if host_inp:
        host_inp.fill("")
        if hostname:
            host_inp.type(hostname, delay=50)
        print(f"    Hostname: {'(blank/root)' if not hostname else hostname}"); flush()

    if val_inp:
        val_inp.fill("")
        val_inp.type(value, delay=20)
        print(f"    Value: {value}"); flush()
    else:
        print(f"    ERROR: No value input found — cannot add record"); flush()
        return False

    page.wait_for_timeout(500)
    page.screenshot(path=str(SCREENSHOT_DIR / f"final_{domain_safe}_{record_type}_filled.png"))

    # Save (use JS click to bypass overlay)
    saved = False
    for sel in [
        'button:has-text("Save Changes")',
        'button:has-text("Save")',
        'button:has-text("Add Record")',
        'button:has-text("Create")',
        'button:has-text("Submit")',
        'button[type="submit"]',
    ]:
        btn = page.query_selector(sel)
        if btn and btn.is_visible():
            btn.evaluate("el => el.click()")
            saved = True
            print(f"    Clicked save: {btn.text_content().strip()[:30]}"); flush()
            break

    if saved:
        page.wait_for_timeout(3000)
        page.screenshot(path=str(SCREENSHOT_DIR / f"final_{domain_safe}_{record_type}_after_save.png"))

        # Verify the record was actually saved by checking the record TABLE
        # (not just any input field — that was a false positive before)
        verified = page.evaluate("""
            (targetValue) => {
                // Look for the value in table cells (td, span, div inside table rows)
                const rows = document.querySelectorAll('.sharedTable__row, tr, [class*="result-row"]');
                for (const row of rows) {
                    const text = row.textContent || '';
                    if (text.includes(targetValue)) return 'in_table';
                }
                // Fallback: check if value appears in any non-input text
                const body = document.body.innerText || '';
                if (body.includes(targetValue)) return 'in_page_text';
                return 'not_found';
            }
        """, value)

        if verified == 'in_table':
            print(f"    {record_type} record VERIFIED in DNS table"); flush()
        elif verified == 'in_page_text':
            print(f"    {record_type} record found in page text (likely saved)"); flush()
        else:
            # Check for error messages
            content = page.content()
            if "error" in content.lower() or "fail" in content.lower():
                print(f"    {record_type} record may have FAILED"); flush()
            elif "already" in content.lower() or "exists" in content.lower():
                print(f"    {record_type} record already exists"); flush()
            else:
                print(f"    {record_type} record submitted but NOT verified in table"); flush()
    else:
        print(f"    ERROR: Save button NOT found"); flush()

    return saved


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--configure", action="store_true", help="Configure all domains")
    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"); flush()

    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' });
        """)

        # STEP 1: Login
        if not do_login(page, code=args.code):
            print("[FATAL] Login failed"); flush()
            browser.close()
            return

        # STEP 2: Expand dashboard to show all domains
        expand_dashboard(page)

        # Get list of visible domains
        visible = get_visible_domains(page)
        print(f"[DASHBOARD] {len(visible)} domains visible on page"); flush()
        for v in visible[:10]:
            print(f"  {v}"); flush()

        if not visible:
            print("[ERROR] No domains visible. Dumping HTML for analysis."); flush()
            html = page.content()
            debug_path = SCREENSHOT_DIR / "final_dashboard_debug.html"
            debug_path.write_text(html[:200000], encoding="utf-8")
            print(f"Dashboard HTML: {debug_path}"); flush()
            browser.close()
            return

        if not args.configure:
            # EXPLORE mode: click DNS button for first domain, explore the page
            first_domain = None
            for d in VENTRAIP_DOMAINS:
                if d in visible:
                    first_domain = d
                    break
            if not first_domain and visible:
                first_domain = visible[0]

            if first_domain:
                print(f"\n[EXPLORE] Clicking DNS for {first_domain}..."); flush()
                if click_dns_for_domain(page, first_domain):
                    page.screenshot(path=str(SCREENSHOT_DIR / "final_explore_dns.png"))
                    print(f"[EXPLORE] DNS page URL: {page.url}"); flush()

                    # Switch to DNS Hosting tab
                    safe = first_domain.replace(".", "_")
                    switch_to_dns_hosting(page, safe)

                    # Dump visible form elements after switching tab
                    elements = page.evaluate("""
                        () => {
                            const els = document.querySelectorAll('input, select, button, a, textarea');
                            return Array.from(els).filter(e => e.offsetParent !== null).map(e => ({
                                tag: e.tagName, type: e.type || '', name: e.name || '',
                                id: e.id || '', text: e.textContent?.trim().substring(0, 80),
                                placeholder: e.placeholder || '', href: e.getAttribute('href') || '',
                                class: e.className?.substring(0, 80),
                                value: e.value?.substring(0, 50) || '',
                            }));
                        }
                    """)
                    el_path = OUTPUT_DIR / "ventraip_dns_elements.json"
                    with open(el_path, "w") as f:
                        json.dump(elements, f, indent=2)
                    print(f"[EXPLORE] {len(elements)} visible elements on DNS Hosting tab"); flush()
                    for e in elements:
                        if e['tag'] in ('INPUT', 'SELECT', 'TEXTAREA') or 'Add' in e.get('text', ''):
                            print(f"  {e['tag']} name={e['name']} ph={e['placeholder'][:30]} text={e['text'][:40]}"); flush()

                    # Save HTML
                    html = page.content()
                    html_path = SCREENSHOT_DIR / "final_explore_dns.html"
                    html_path.write_text(html[:200000], encoding="utf-8")
                    print(f"[EXPLORE] HTML saved: {html_path}"); flush()

                    # Try adding a test A record for the first domain
                    netlify_sub = domain_map.get(first_domain)
                    if netlify_sub:
                        print(f"\n[EXPLORE] Testing record creation for {first_domain}..."); flush()
                        print(f"  Adding A record: (root) → {NETLIFY_A_RECORD}"); flush()
                        a_ok = add_dns_record(page, "A", "", NETLIFY_A_RECORD, safe)
                        page.wait_for_timeout(1000)
                        print(f"  Adding CNAME: www → {netlify_sub}.netlify.app"); flush()
                        cname_ok = add_dns_record(page, "CNAME", "www", f"{netlify_sub}.netlify.app", safe)
                        print(f"  Result: A={a_ok} CNAME={cname_ok}"); flush()
                        page.screenshot(path=str(SCREENSHOT_DIR / "final_explore_after_records.png"))
                else:
                    print("[EXPLORE] Could not click DNS button"); flush()
            else:
                print("[EXPLORE] No matching domain found on dashboard"); flush()

        else:
            # CONFIGURE mode: configure all domains
            print(f"\n{'='*60}")
            print(f"CONFIGURING DNS — {len(domain_map)} domains")
            print(f"{'='*60}\n"); flush()

            results = []
            for i, (domain, netlify_sub) in enumerate(domain_map.items(), 1):
                if domain not in visible:
                    print(f"[{i}/{len(domain_map)}] {domain} — SKIP (not visible on dashboard)"); flush()
                    results.append({"domain": domain, "status": "not_visible", "a_record": False, "cname_record": False})
                    continue

                print(f"[{i}/{len(domain_map)}] {domain}"); flush()
                netlify_target = f"{netlify_sub}.netlify.app"
                safe = domain.replace(".", "_")

                # Click DNS button for this domain
                if not click_dns_for_domain(page, domain):
                    print(f"  → DNS button not found"); flush()
                    results.append({"domain": domain, "status": "no_dns_button", "a_record": False, "cname_record": False})
                    continue

                page.screenshot(path=str(SCREENSHOT_DIR / f"final_dns_{safe}.png"))

                # Check we're on a DNS page (not 404)
                content = page.content().lower()
                if "404" in content and "check the url" in content:
                    print(f"  → 404 error"); flush()
                    results.append({"domain": domain, "status": "404", "a_record": False, "cname_record": False})
                    page.go_back()
                    page.wait_for_timeout(3000)
                    continue

                # Switch to DNS Hosting tab
                switch_to_dns_hosting(page, safe)

                # Add A record
                print(f"  Adding A record: (root) → {NETLIFY_A_RECORD}"); flush()
                a_ok = add_dns_record(page, "A", "", NETLIFY_A_RECORD, safe)

                page.wait_for_timeout(1000)

                # Add CNAME record
                print(f"  Adding CNAME: www → {netlify_target}"); flush()
                cname_ok = add_dns_record(page, "CNAME", "www", netlify_target, safe)

                status = "configured" if (a_ok and cname_ok) else ("partial" if (a_ok or cname_ok) else "failed")
                results.append({"domain": domain, "netlify": netlify_target, "status": status, "a_record": a_ok, "cname_record": cname_ok})
                print(f"  → {status} | A={a_ok} CNAME={cname_ok}"); flush()

                page.screenshot(path=str(SCREENSHOT_DIR / f"final_dns_{safe}_after.png"))

                # Go back to dashboard for next domain
                page.go_back()
                page.wait_for_timeout(3000)
                # Re-expand if needed
                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)

                time.sleep(1)

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

            configured = sum(1 for r in results if r["status"] == "configured")
            partial = sum(1 for r in results if r["status"] == "partial")
            failed = len(results) - configured - partial
            print(f"\n{'='*60}")
            print(f"DONE: {configured} configured, {partial} partial, {failed} failed")
            print(f"Results: {results_path}")
            print(f"{'='*60}"); flush()

        browser.close()
        print("\n[DONE]"); flush()


if __name__ == "__main__":
    main()
