#!/usr/bin/env python3
"""
Control existing Chrome browser via CDP for X engagement.
Connects to Chrome running with --remote-debugging-port=9222
"""

import asyncio
import json
import random
import sys
import urllib.request
from datetime import datetime
from pathlib import Path

try:
    from patchright.async_api import async_playwright
except ImportError:
    print("pip install patchright")
    sys.exit(1)

LOG_PATH = Path("/workspace/PROGRESS-LOG.md")
CDP_URL = "http://localhost:9222"

VOICE_PROFILE = """You are a Florida medical cannabis patient in your late 20s. Sassy, funny, self-deprecating. 
Lowercase twitter speak, 1-2 emojis max. Never sound like a brand. React to what they ACTUALLY said."""

TARGET_ACCOUNTS = [
    "Trulieve", "MUV_FL", "TheFloweryFL", "GrowHealthyFL",
    "SunburnCannabis", "curaleaffl", "JungleBoysFlorida"
]


def log_action(action: str, details: str = ""):
    ts = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    print(f"[{ts}] {action}: {details}", flush=True)
    try:
        content = LOG_PATH.read_text() if LOG_PATH.exists() else "# PROGRESS-LOG.md\n"
        today = datetime.now().strftime("%Y-%m-%d")
        if f"### {today}" not in content:
            content += f"\n### {today}\n| Time | Action | Details |\n|------|--------|--------|\n"
        content += f"| {ts} | {action} | {details} |\n"
        LOG_PATH.write_text(content)
    except:
        pass


def generate_reply(tweet_text: str, username: str) -> str:
    """Generate reply via LLM."""
    if not tweet_text or len(tweet_text.strip()) < 10:
        return random.choice(["👀", "say less", "on my way"])
    
    prompt = f"""{VOICE_PROFILE}

Tweet from @{username}: "{tweet_text[:200]}"

Write ONE reply (under 140 chars). Just the reply text:"""

    try:
        payload = json.dumps({
            "model": "claude-sonnet-4-20250514",
            "max_tokens": 60,
            "messages": [{"role": "user", "content": prompt}]
        }).encode()
        
        req = urllib.request.Request(
            "https://api.z.ai/api/anthropic/v1/messages",
            data=payload,
            headers={
                "Content-Type": "application/json",
                "x-api-key": "3887e2ed1a0a42ada0f9dc04461d3dce.O9dPzq1s2KQB2uMm",
                "anthropic-version": "2023-06-01"
            }
        )
        with urllib.request.urlopen(req, timeout=15) as resp:
            data = json.loads(resp.read().decode())
            reply = data["content"][0]["text"].strip().strip('"\'')
            if 5 < len(reply) <= 280:
                return reply
    except Exception as e:
        print(f"  LLM error: {e}", flush=True)
    
    return random.choice(["my wallet is crying", "say less 🏃‍♂️", "📝"])


async def human_type(page, text: str):
    """Type like a human."""
    for char in text:
        await page.keyboard.type(char, delay=random.randint(30, 80))
        if random.random() < 0.02:
            await asyncio.sleep(random.uniform(0.2, 0.5))


async def run_engagement(reply_count: int = 2, like_count: int = 5):
    """Connect to existing Chrome and run engagement."""
    print("🥷 Browser Engagement (CDP)", flush=True)
    print("=" * 50, flush=True)
    
    stats = {"likes": 0, "replies": 0}
    
    async with async_playwright() as p:
        # Connect to existing browser
        print("🔌 Connecting to Chrome via CDP...", flush=True)
        browser = await p.chromium.connect_over_cdp(CDP_URL)
        
        # Get existing context and page
        context = browser.contexts[0]
        pages = context.pages
        
        if not pages:
            page = await context.new_page()
        else:
            page = pages[0]
        
        print(f"📱 Connected! Current URL: {page.url}", flush=True)
        log_action("CDP_SESSION", f"Connected to {page.url}")
        
        try:
            # Navigate to home if not already on X
            if "x.com" not in page.url:
                await page.goto("https://x.com/home")
                await asyncio.sleep(3)
            
            # Warmup scroll
            print("🔥 Warming up...", flush=True)
            for _ in range(3):
                await page.mouse.wheel(0, random.randint(200, 400))
                await asyncio.sleep(random.uniform(1, 2))
            
            # Engage with targets
            targets = random.sample(TARGET_ACCOUNTS, min(3, len(TARGET_ACCOUNTS)))
            
            for username in targets:
                if stats["likes"] >= like_count and stats["replies"] >= reply_count:
                    break
                
                print(f"\n👤 @{username}...", flush=True)
                
                try:
                    await page.goto(f"https://x.com/{username}", wait_until="domcontentloaded")
                    await asyncio.sleep(random.uniform(3, 5))
                    
                    # Scroll
                    for _ in range(2):
                        await page.mouse.wheel(0, random.randint(200, 350))
                        await asyncio.sleep(random.uniform(0.8, 1.5))
                    
                    tweets = await page.locator('[data-testid="tweet"]').all()
                    
                    for i, tweet in enumerate(tweets[:3]):
                        if stats["likes"] >= like_count and stats["replies"] >= reply_count:
                            break
                        
                        try:
                            # Like
                            if stats["likes"] < like_count:
                                like_btn = tweet.locator('[data-testid="like"]')
                                if await like_btn.is_visible():
                                    await like_btn.click()
                                    stats["likes"] += 1
                                    log_action("LIKE", f"@{username}")
                                    print(f"  ❤️ Liked", flush=True)
                                    await asyncio.sleep(random.uniform(1.5, 3))
                            
                            # Reply (first tweet only)
                            if stats["replies"] < reply_count and i == 0:
                                print(f"  💬 Replying...", flush=True)
                                
                                # Get tweet text
                                tweet_text = ""
                                try:
                                    txt = tweet.locator('[data-testid="tweetText"]')
                                    if await txt.count() > 0:
                                        tweet_text = await txt.inner_text()
                                except:
                                    pass
                                
                                # Click tweet to open detail
                                tweet_link = tweet.locator('a[href*="/status/"]').first
                                if await tweet_link.is_visible():
                                    await tweet_link.click()
                                    await asyncio.sleep(random.uniform(2, 3))
                                
                                # Find reply textarea (on detail page it's inline)
                                textarea = page.locator('[data-testid="tweetTextarea_0"]')
                                if await textarea.is_visible(timeout=3000):
                                    reply_text = generate_reply(tweet_text, username)
                                    print(f"     Reply: {reply_text[:50]}...", flush=True)
                                    
                                    await textarea.click()
                                    await asyncio.sleep(0.5)
                                    await human_type(page, reply_text)
                                    await asyncio.sleep(1)
                                    
                                    # Click Reply button
                                    reply_btn = page.locator('[data-testid="tweetButton"], button:has-text("Reply")').first
                                    if await reply_btn.is_visible():
                                        await reply_btn.click()
                                        await asyncio.sleep(2)
                                        
                                        # Handle "Replying to" dialog if shown
                                        done_btn = page.locator('button:has-text("Done")').first
                                        try:
                                            if await done_btn.is_visible(timeout=2000):
                                                await done_btn.click()
                                                await asyncio.sleep(1)
                                        except:
                                            pass
                                        
                                        # Check if posted
                                        try:
                                            still_open = await textarea.is_visible(timeout=2000)
                                        except:
                                            still_open = False
                                        
                                        if not still_open:
                                            stats["replies"] += 1
                                            log_action("REPLY", f"@{username}: {reply_text[:40]}...")
                                            print(f"  ✅ Posted!", flush=True)
                                        else:
                                            print(f"  ⚠️ May not have posted", flush=True)
                                
                                # Go back
                                await page.go_back()
                                await asyncio.sleep(2)
                        
                        except Exception as e:
                            print(f"  Error: {str(e)[:50]}", flush=True)
                    
                    await asyncio.sleep(random.uniform(2, 4))
                    
                except Exception as e:
                    print(f"  Error @{username}: {str(e)[:50]}", flush=True)
            
            print("\n" + "=" * 50, flush=True)
            print(f"📊 DONE - Likes: {stats['likes']}, Replies: {stats['replies']}", flush=True)
            log_action("CDP_DONE", f"L:{stats['likes']} R:{stats['replies']}")
            
        except Exception as e:
            print(f"Error: {e}", flush=True)
        finally:
            # Don't close - leave browser running
            pass
    
    return stats


async def main():
    if "--dry-run" in sys.argv:
        print("DRY RUN - targets:", TARGET_ACCOUNTS[:3])
        return
    
    reply_count = 4 if "--heavy" in sys.argv else 2
    like_count = 10 if "--heavy" in sys.argv else 5
    if "--light" in sys.argv:
        reply_count, like_count = 1, 3
    
    await run_engagement(reply_count, like_count)


if __name__ == "__main__":
    asyncio.run(main())
