import asyncio
import random
import time
import json
from fake_useragent import UserAgent
from faker import Faker
from playwright.async_api import async_playwright
import requests
from collections import deque
import urllib3

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

# Configuration
MAIN_URL = "https://awards.travelandleisureasia.com/luxuryawards2026/maldives/resorts"

NOMIN_ID = "466"
NOMINC_ID = "38"
CAT_ID = "11"
TABLE_PREFIX = "wp_28_"

PROXY_FILE = "proxies_scape.txt"

EMAIL_DOMAINS = [
    "gmail.com", "yahoo.com", "outlook.com", "hotmail.com", "live.com", "msn.com",
    "yandex.com", "protonmail.com", "icloud.com", "zoho.com"
]

CITIES = [
    "Singapore", "Mumbai", "Bangkok", "Delhi", "Kuala Lumpur", "Jakarta",
    "Dubai", "Hong Kong", "Colombo", "Malé", "Chennai", "Bangalore",
    "Manila", "Hanoi", "Phuket", "Penang", "Ho Chi Minh City"
]

MAX_VOTES_PER_MINUTE = 8
MAX_VOTES_PER_HOUR = 50

fake = Faker(["en_IN", "en_US", "th_TH", "id_ID", "en_GB", "en_PH", "hi_IN"])
ua = UserAgent()

minute_votes = deque()
hour_votes = deque()
total_votes = 0
attempt = 1


def load_local_proxies():
    proxies = []
    try:
        with open(PROXY_FILE, "r", encoding="utf-8") as f:
            for line in f:
                proxy = line.strip()
                if proxy and not proxy.startswith("#"):
                    proxies.append(proxy)
        print(f"✅ Loaded {len(proxies)} HTTP proxies from {PROXY_FILE}")
        return proxies
    except FileNotFoundError:
        print(f"❌ '{PROXY_FILE}' not found!")
        return []
    except Exception as e:
        print(f"❌ Error reading file: {e}")
        return []


def verify_proxy(proxy):
    """Verify HTTP proxy"""
    try:
        session = requests.Session()
        session.proxies = {
            "http": f"http://{proxy}",
            "https": f"http://{proxy}"
        }
        session.verify = False
        response = session.get("http://httpbin.org/ip", timeout=12)
        if response.status_code == 200:
            ip_data = json.loads(response.text)
            return True, ip_data.get("origin", "Unknown")
    except:
        pass
    return False, None


def can_vote():
    current_time = time.time()
    while minute_votes and current_time - minute_votes[0] > 60:
        minute_votes.popleft()
    while hour_votes and current_time - hour_votes[0] > 3600:
        hour_votes.popleft()

    if len(minute_votes) >= MAX_VOTES_PER_MINUTE:
        wait_time = 60 - (current_time - minute_votes[0])
        print(f"⏰ Minute limit reached. Waiting {wait_time:.2f}s...")
        return False, wait_time

    if len(hour_votes) >= MAX_VOTES_PER_HOUR:
        wait_time = 3600 - (current_time - hour_votes[0])
        print(f"⏰ Hour limit reached. Waiting {wait_time:.2f}s...")
        return False, wait_time

    return True, 0


async def cast_vote(page, proxy_ip):
    name = fake.name()
    base = fake.user_name() or name.lower().replace(" ", ".")[:20]
    email = f"{base}{random.randint(10, 99)}@{random.choice(EMAIL_DOMAINS)}"
    city = random.choice(CITIES)

    payload = {
        "name": name,
        "email": email,
        "city": city,
        "user_ip": proxy_ip,
        "user_agent": "Chrome",
        "device_type": random.choice(["Desktop", "Mobile"]),
        "is_subscribed": "0",
        "nominId": NOMIN_ID,
        "nomincId": NOMINC_ID,
        "catId": CAT_ID,
        "tablePrefix": TABLE_PREFIX,
    }

    try:
        response = await page.evaluate("""async (payload) => {
            const formData = new URLSearchParams();
            for (const [key, value] of Object.entries(payload)) {
                formData.append(key, value);
            }
            const res = await fetch("https://awards.travelandleisureasia.com/wp-content/themes/award-theme/voting_detail_form_ajax.php", {
                method: "POST",
                headers: {
                    "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
                    "X-Requested-With": "XMLHttpRequest",
                    "Accept": "application/json, text/javascript, */*; q=0.01",
                    "Referer": "https://awards.travelandleisureasia.com/luxuryawards2026/maldives/resorts",
                },
                body: formData.toString(),
                credentials: "include"
            });
            return { status: res.status, text: await res.text() };
        }""", payload)

        print(f"📧 {name} | {email}")
        print(f"🌍 Proxy IP: {proxy_ip}")

        text_lower = response['text'].lower()
        if response['status'] == 200 and any(k in text_lower for k in ["success", "thank", "voted", "1", "true", "ok"]):
            print("✅ Vote accepted!")
            return True
        else:
            print(f"❌ Vote rejected: {response['text'][:150]}")
            return False
    except Exception as e:
        print(f"Error in cast_vote: {e}")
        return False


async def main():
    global total_votes, attempt

    print("🚀 Voting Script Started - Using Local HTTP Proxies")
    print("=" * 60)

    proxies = load_local_proxies()
    if not proxies:
        print("❌ No proxies loaded. Exiting...")
        return

    random.shuffle(proxies)

    async with async_playwright() as p:
        browser = await p.chromium.launch(
            headless=True,
            args=['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage']
        )

        proxy_index = 0

        while True:
            print(f"\n{'=' * 60}")
            print(f"Attempt {attempt} | Total votes: {total_votes}")
            print(f"{'=' * 60}")

            can_proceed, wait_time = can_vote()
            if not can_proceed:
                await asyncio.sleep(wait_time)
                continue

            if proxy_index >= len(proxies):
                print("🔄 Restarting proxy list...")
                random.shuffle(proxies)
                proxy_index = 0

            proxy = proxies[proxy_index]
            proxy_index += 1

            print(f"🔍 Testing proxy: {proxy}")
            is_valid, proxy_ip = verify_proxy(proxy)
            if not is_valid:
                print(f"❌ Proxy not working. Skipping...")
                continue

            print(f"✅ Proxy working! IP: {proxy_ip}")

            context = None
            try:
                # HTTP Proxy configuration (this was the main bug)
                context = await browser.new_context(
                    proxy={"server": f"http://{proxy}"},   # Correct for HTTP proxies
                    user_agent=ua.random,
                    viewport={"width": 1280, "height": 720},
                    locale='en-US',
                    timezone_id='Asia/Shanghai',
                )

                page = await context.new_page()

                await page.add_init_script("""
                    Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
                    Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5] });
                    Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'] });
                """)

                print("🌐 Visiting main page...")
                await page.goto(MAIN_URL, timeout=60000, wait_until="domcontentloaded")

                success = await cast_vote(page, proxy_ip)

                if success:
                    current_time = time.time()
                    minute_votes.append(current_time)
                    hour_votes.append(current_time)
                    total_votes += 1
                    print("✅ Vote successful!")
                else:
                    print("❌ Vote failed.")

            except Exception as e:
                print(f"❌ Error: {e}")

            finally:
                if context:
                    await context.close()

            attempt += 1
            await asyncio.sleep(5)   # Small delay between attempts


if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        print("\n👋 Stopped by user")
        print(f"Final stats: {total_votes} votes cast")
