#!/usr/bin/env python3
"""
使用 page.setContent() 加载 CAPTCHA 页面（正确加载脚本和资源）。
"""
import asyncio, json, base64, time, requests
from playwright.async_api import async_playwright

YESCAPTCHA_KEY = "ea616d4a088df1899eac549ffe784135fb783282134833"
OUTPUT = "/tmp/waf_token.json"


def solve_captcha(image_b64: str, question: str) -> list:
    payload = {
        "clientKey": YESCAPTCHA_KEY,
        "task": {"type": "AwsClassification", "queries": image_b64, "question": question},
    }
    resp = requests.post("https://api.yescaptcha.com/createTask", json=payload, timeout=30)
    data = resp.json()
    if data.get("errorId") != 0:
        print(f"  [YesCaptcha] err: {data.get('errorDescription')}")
        return []
    task_id = data["taskId"]
    for i in range(30):
        time.sleep(2)
        r = requests.post("https://api.yescaptcha.com/getTaskResult",
                          json={"clientKey": YESCAPTCHA_KEY, "taskId": task_id}, timeout=30).json()
        if r.get("status") == "ready":
            return r.get("solution", {}).get("top_k", [])
        if r.get("errorId") != 0:
            return []
    return []


async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch(
            headless=True,
            args=["--no-sandbox", "--disable-gpu", "--disable-dev-shm-usage",
                  "--disable-setuid-sandbox", "--no-first-run", "--no-zygote", "--single-process"],
        )
        context = await browser.new_context(
            user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
            viewport={"width": 1920, "height": 1080},
        )
        page = await context.new_page()

        # 先访问首页建 session
        print("[1] 访问首页...")
        await page.goto("https://chat.deepseek.com/", wait_until="domcontentloaded", timeout=30000)
        await asyncio.sleep(5)
        print(f"  标题: {await page.title()}")

        # 用 fetch 获取 CAPTCHA 页面
        print("[2] 获取 CAPTCHA 页面...")
        captcha_html = await page.evaluate("""
            async () => {
                const resp = await fetch("https://chat.deepseek.com/api/v0/users/login", {
                    method: "POST",
                    headers: {"Content-Type": "application/json"},
                    body: JSON.stringify({email:"test@test.com",password:"test",device_id:"",os:"web"}),
                    credentials: "include",
                });
                return await resp.text();
            }
        """)
        print(f"  HTML 长度: {len(captcha_html)}")

        # 使用 setContent 加载（正确执行脚本）
        print("[3] setContent 加载 CAPTCHA...")
        await page.set_content(captcha_html, wait_until="domcontentloaded", timeout=30000)
        await asyncio.sleep(5)
        print(f"  标题: {await page.title()}")

        # 等待 CAPTCHA 渲染
        print("[4] 等待渲染...")
        for i in range(15):
            await asyncio.sleep(2)
            # 检查各种可能的 CAPTCHA 容器
            containers = await page.locator(
                "#challenge-container > *, #captcha-container > *, "
                "[class*='captcha'] > *, [class*='challenge'] > *"
            ).count()
            imgs = await page.locator("img").count()
            canvases = await page.locator("canvas").count()
            iframes = await page.locator("iframe").count()
            print(f"  子元素:{containers} img:{imgs} canvas:{canvases} iframe:{iframes}")
            if containers > 0 or imgs >= 9 or canvases > 0:
                break

        # 截图
        await page.screenshot(path="/tmp/captcha_setcontent.png", full_page=True)
        print("  截图: /tmp/captcha_setcontent.png")

        # 获取页面文本
        body = await page.locator("body").text_content() or ""
        print(f"  页面文本[:500]: {body[:500]}")

        # 提取问题
        question = ""
        for kw in ["Select all", "选择所有", "Click all", "点击所有", "包含", "contain"]:
            idx = body.find(kw)
            if idx >= 0:
                question = body[idx:idx+200].strip().split("\n")[0]
                break
        print(f"  问题: {question}")

        # 截图送 YesCaptcha
        try:
            cap = page.locator("#challenge-container, #captcha-container, [class*='captcha'], [class*='challenge']").first
            if await cap.count() > 0:
                screenshot = await cap.screenshot(type="png")
            else:
                screenshot = await page.screenshot(type="png")
        except Exception:
            screenshot = await page.screenshot(type="png")

        img_b64 = base64.b64encode(screenshot).decode()

        # 找可点击元素
        all_imgs = page.locator("img")
        img_count = await all_imgs.count()
        clickables = page.locator("img, [class*='tile'], [class*='cell'], [class*='image']")
        clickable_count = await clickables.count()
        print(f"  img:{img_count} clickable:{clickable_count}")

        if question and clickable_count >= 9:
            print("[5] YesCaptcha 识别...")
            indices = solve_captcha(img_b64, question)
            print(f"  结果: {indices}")

            if indices:
                print("[6] 点击...")
                for idx in indices:
                    if idx < clickable_count:
                        try:
                            await clickables.nth(idx).click(timeout=5000)
                            await asyncio.sleep(0.5)
                            print(f"    点击 {idx}")
                        except Exception as e:
                            print(f"    点击 {idx} 失败: {e}")

                await asyncio.sleep(5)
                try:
                    await page.wait_for_load_state("networkidle", timeout=30000)
                except Exception:
                    pass
                print(f"  新标题: {await page.title()}")

        # 提取 cookies
        cookies = await context.cookies()
        waf_token = None
        for c in cookies:
            if "aws-waf" in c["name"].lower():
                waf_token = c["value"]
                print(f"[7] WAF Token: {waf_token[:60]}...")

        result = {"waf_token": waf_token, "cookies": {c["name"]: c["value"] for c in cookies}}
        with open(OUTPUT, "w") as f:
            json.dump(result, f, indent=2)
        print(f"[8] 保存: {OUTPUT}")
        await browser.close()

asyncio.run(main())