#!/usr/bin/env python3
"""
Polymarket User Betting History Scraper
Scrapes all betting activity for a given username and saves to CSV
"""

import sys
import csv
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, NoSuchElementException
import re

def setup_driver():
    """Setup Chrome driver with appropriate options"""
    options = webdriver.ChromeOptions()
    options.add_argument('--headless')
    options.add_argument('--no-sandbox')
    options.add_argument('--disable-dev-shm-usage')
    options.add_argument('--disable-blink-features=AutomationControlled')
    options.add_argument('--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')
    
    driver = webdriver.Chrome(options=options)
    driver.set_window_size(1920, 1080)
    return driver

def click_activity_tab(driver):
    """Click on the Activity tab"""
    try:
        # Wait for page to load
        time.sleep(3)
        
        # Try to find and click Activity button
        activity_button = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Activity')]"))
        )
        activity_button.click()
        time.sleep(2)
        print("✓ Clicked Activity tab")
        return True
    except Exception as e:
        print(f"✗ Could not click Activity tab: {e}")
        return False

def extract_activity_rows(driver):
    """Extract all activity rows from the current page state"""
    script = """
    return (function() {
        // Find all activity rows
        const allDivs = Array.from(document.querySelectorAll('div'));
        const activityRows = allDivs.filter(div => {
            const firstChild = div.querySelector(':scope > div:first-child p');
            if (!firstChild) return false;
            const text = firstChild.textContent?.trim();
            return text && ['Buy', 'Sell', 'Redeem', 'Convert'].includes(text);
        });

        return activityRows.map(row => {
            // Get type
            const type = row.querySelector('p')?.textContent?.trim();
            
            // Get market link and text
            const marketLink = row.querySelector('a[href*="/event/"]');
            const market = marketLink?.textContent?.trim() || '';
            
            // Get all direct child divs
            const childDivs = Array.from(row.querySelectorAll(':scope > div'));
            
            // Extract shares and outcome from the middle section
            let shares = '';
            let outcome = '';
            let outcomePrice = '';
            
            // Look for shares in the text
            for (let div of childDivs) {
                const text = div.textContent;
                const sharesMatch = text.match(/([0-9.]+)\\s+shares/);
                if (sharesMatch) {
                    shares = sharesMatch[1];
                }
                
                const outcomeMatch = text.match(/(Yes|No)\\s+([0-9]+)¢/);
                if (outcomeMatch) {
                    outcome = outcomeMatch[1];
                    outcomePrice = outcomeMatch[2] + '¢';
                }
            }
            
            // Get amount from the last column (rightmost div with amount)
            let amount = '';
            const amountDiv = childDivs[childDivs.length - 1];
            if (amountDiv) {
                const amountText = amountDiv.textContent;
                const amountMatch = amountText.match(/\\$([0-9.]+)/);
                if (amountMatch) {
                    amount = '$' + amountMatch[1];
                }
            }
            
            // Get timestamp - look for the specific link element with time
            let timestamp = '';
            const timeLink = row.querySelector('a.flex.items-center.text-xs.text-text-secondary');
            if (timeLink) {
                timestamp = timeLink.textContent.trim();
            }
            
            return {
                type: type,
                market: market,
                outcome: outcome,
                outcomePrice: outcomePrice,
                shares: shares,
                amount: amount,
                timestamp: timestamp
            };
        });
    })();
    """
    
    try:
        rows = driver.execute_script(script)
        if rows is None:
            return []
        return rows
    except Exception as e:
        print(f"Error extracting rows: {e}")
        return []

def scroll_and_load_more(driver, max_scrolls=1000):
    """Scroll down and click 'Load more' buttons to load all activity"""
    print("Starting to scroll and load all activity...")
    
    last_count = 0
    no_change_count = 0
    scroll_count = 0
    
    while scroll_count < max_scrolls:
        # Get current count
        current_rows = extract_activity_rows(driver)
        current_count = len(current_rows)
        
        if current_count > last_count:
            print(f"  Loaded {current_count} activities...")
            last_count = current_count
            no_change_count = 0
        else:
            no_change_count += 1
        
        # If no change after multiple attempts, we're done
        if no_change_count >= 5:
            print(f"✓ No more activities to load. Total: {current_count}")
            break
        
        # Scroll to bottom
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        time.sleep(1)
        
        # Try to click "Load more" button if it exists
        try:
            load_more_button = driver.find_element(By.XPATH, "//button[contains(text(), 'Load more')]")
            if load_more_button.is_displayed():
                driver.execute_script("arguments[0].scrollIntoView(true);", load_more_button)
                time.sleep(0.5)
                load_more_button.click()
                time.sleep(2)
                print("  Clicked 'Load more' button")
        except NoSuchElementException:
            pass
        except Exception as e:
            pass
        
        scroll_count += 1
    
    return extract_activity_rows(driver)

def calculate_result(row):
    """Calculate the result (win/loss) based on the activity type and amounts"""
    activity_type = row['type']
    
    if activity_type == 'Redeem':
        # For redeem, if amount > 0, it's a win
        try:
            amount = float(row['amount'].replace('$', ''))
            if amount > 0:
                return 'Win'
            else:
                return 'Loss'
        except:
            return 'Unknown'
    elif activity_type == 'Convert':
        # Convert is neutral - converting shares
        return 'Convert'
    elif activity_type in ['Buy', 'Sell']:
        # For buy/sell, we can't determine win/loss until redemption
        return 'Pending'
    
    return 'Unknown'

def save_to_csv(username, activities):
    """Save activities to CSV file"""
    filename = f"{username}_bets.csv"
    
    # Define CSV columns
    fieldnames = [
        'type',
        'result',
        'market_description',
        'outcome',
        'outcome_price',
        'shares',
        'total_bet',
        'amount_won',
        'timestamp'
    ]
    
    with open(filename, 'w', newline='', encoding='utf-8') as csvfile:
        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
        writer.writeheader()
        
        for activity in activities:
            result = calculate_result(activity)
            
            # For Buy/Sell, total_bet is the amount
            # For Redeem, amount_won is the amount
            total_bet = ''
            amount_won = ''
            
            if activity['type'] in ['Buy', 'Sell']:
                total_bet = activity['amount']
            elif activity['type'] == 'Redeem':
                amount_won = activity['amount']
            elif activity['type'] == 'Convert':
                total_bet = activity['amount']
            
            writer.writerow({
                'type': activity['type'],
                'result': result,
                'market_description': activity['market'],
                'outcome': activity['outcome'],
                'outcome_price': activity['outcomePrice'],
                'shares': activity['shares'],
                'total_bet': total_bet,
                'amount_won': amount_won,
                'timestamp': activity['timestamp']
            })
    
    print(f"\n✓ Saved {len(activities)} activities to {filename}")
    return filename

def scrape_user_bets(username):
    """Main function to scrape all bets for a user"""
    print(f"Starting scraper for user: {username}")
    print("=" * 60)
    
    driver = setup_driver()
    
    try:
        # Navigate to user profile
        url = f"https://polymarket.com/@{username}"
        print(f"Navigating to {url}...")
        driver.get(url)
        
        # Click Activity tab
        if not click_activity_tab(driver):
            print("Failed to access Activity tab")
            return None
        
        # Scroll and load all activities
        activities = scroll_and_load_more(driver)
        
        if not activities:
            print("No activities found!")
            return None
        
        print(f"\n✓ Successfully extracted {len(activities)} activities")
        
        # Save to CSV
        filename = save_to_csv(username, activities)
        
        return filename
        
    except Exception as e:
        print(f"Error during scraping: {e}")
        import traceback
        traceback.print_exc()
        return None
    finally:
        driver.quit()

def main():
    if len(sys.argv) < 2:
        print("Usage: python poly_user_scraper.py <username>")
        print("Example: python poly_user_scraper.py ZXWP")
        sys.exit(1)
    
    username = sys.argv[1]
    result = scrape_user_bets(username)
    
    if result:
        print("\n" + "=" * 60)
        print(f"SUCCESS! Data saved to {result}")
        print("=" * 60)
    else:
        print("\n" + "=" * 60)
        print("FAILED to scrape data")
        print("=" * 60)
        sys.exit(1)

if __name__ == "__main__":
    main()
