"""One no-proxy Camoufox attempt on the existing Amazon laptop-search URL."""
import json
import os
import platform
import sys
import threading
import time
from datetime import datetime, timezone
from importlib.metadata import version
from pathlib import Path

import psutil
from bs4 import BeautifulSoup

HERE = Path(__file__).resolve().parent
URL = "https://www.amazon.com/s?k=laptop"
BLOCK_MARKERS = (
    "robot check", "enter the characters", "verify you are human",
    "just a moment", "access denied", "checking your browser",
)


def main():
    for key in ("HTTP_PROXY", "HTTPS_PROXY", "ALL_PROXY", "http_proxy", "https_proxy", "all_proxy"):
        os.environ.pop(key, None)
    row = {
        "tool": "Camoufox", "tool_version": version("camoufox"),
        "python_version": platform.python_version(), "runtime": platform.platform(),
        "target": "amazon_search_laptop", "url": URL,
        "started_at": datetime.now(timezone.utc).isoformat(),
        "command": [sys.executable, *sys.argv],
        "config": {"browser": "camoufox", "headless": True, "os": "linux", "proxy": None,
                   "wait_until": "domcontentloaded", "navigation_timeout_ms": 30000,
                   "content_wait_ms": 8000, "settle_ms": 500},
        "network": "this host, direct outbound; common proxy environment variables removed",
        "resource_metric_caveat": "Peak sampled sum of Python and descendant browser PSS/RSS at 0.2-second intervals; may miss brief peaks and is not comparable to the earlier Zenbook browser run.",
    }
    stop = threading.Event()
    samples = []

    def sample_tree():
        root = psutil.Process(os.getpid())
        while not stop.is_set():
            pss = rss = count = 0
            try:
                members = [root, *root.children(recursive=True)]
            except psutil.NoSuchProcess:
                break
            for proc in members:
                try:
                    memory = proc.memory_full_info()
                    pss += getattr(memory, "pss", memory.rss)
                    rss += memory.rss
                    count += 1
                except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
                    pass
            samples.append((pss, rss, count))
            stop.wait(0.2)

    monitor = threading.Thread(target=sample_tree, daemon=True)
    monitor.start()
    start = time.perf_counter()
    try:
        from camoufox.sync_api import Camoufox
        from camoufox.pkgman import launch_path

        row["browser_executable"] = launch_path()
        with Camoufox(headless=True, os="linux") as browser:
            row["browser_version"] = browser.version
            page = browser.new_page()
            try:
                response = page.goto(URL, wait_until="domcontentloaded", timeout=30000)
                row["http_status"] = response.status if response else None
                row["navigation_outcome"] = "returned"
                if row["http_status"] == 200:
                    try:
                        page.wait_for_function("() => document.body && document.body.innerText.length >= 500", timeout=8000)
                    except Exception:
                        pass
                page.wait_for_timeout(500)
                row["final_url"] = page.url
                row["title"] = page.title()
                html = page.content()
                text = page.locator("body").inner_text(timeout=5000)
                (HERE / "rendered-html.txt").write_text(html, encoding="utf-8")
                (HERE / "visible-text.txt").write_text(text, encoding="utf-8")
                row.update(rendered_html="rendered-html.txt", visible_text="visible-text.txt",
                           html_bytes=len(html.encode("utf-8")), visible_text_chars=len(text))
                page.screenshot(path=str(HERE / "screenshot.png"), full_page=False, timeout=10000)
                row["screenshot"] = "screenshot.png"
                soup = BeautifulSoup(html, "html.parser")
                cards = [card for card in soup.select('[data-component-type="s-search-result"]')
                         if card.get("data-asin") and card.select_one("h2")]
                low = (row["title"] + "\n" + text[:2000]).lower()
                block_markers = [marker for marker in BLOCK_MARKERS if marker in low]
                row.update(product_result_count=len(cards), required_term_found="laptop" in text.lower(),
                           block_markers=block_markers, empty_or_short_200=row["http_status"] == 200 and len(text) < 500,
                           usable_content=row["http_status"] == 200 and len(cards) > 0 and "laptop" in text.lower()
                           and len(text) >= 500 and not block_markers)
            finally:
                page.close()
    except Exception as exc:
        row.update(navigation_outcome=row.get("navigation_outcome", "error"),
                   error=f"{type(exc).__name__}: {str(exc)[:500]}", usable_content=False)
    finally:
        row["wall_seconds"] = round(time.perf_counter() - start, 3)
        row["finished_at"] = datetime.now(timezone.utc).isoformat()
        stop.set()
        monitor.join(timeout=1)
        row["sampled_peak_process_tree_pss_mb"] = round(max((s[0] for s in samples), default=0) / 1048576, 1)
        row["sampled_peak_process_tree_rss_sum_mb"] = round(max((s[1] for s in samples), default=0) / 1048576, 1)
        row["sampled_max_process_count"] = max((s[2] for s in samples), default=0)
        row["resource_sample_interval_seconds"] = 0.2
        (HERE / "result.json").write_text(json.dumps(row, indent=2) + "\n", encoding="utf-8")
        print(json.dumps(row, indent=2))


if __name__ == "__main__":
    main()
