#!/usr/bin/env python3
"""Booking.com search scraper using Camoufox stealth browser.
Bypasses DataDome anti-bot protection via binary-level Firefox patches.

Usage:
    /tmp/camoufox-venv/bin/python booking_search.py \
        --destination "San Martin de los Andes" \
        --checkin 2026-05-01 --checkout 2026-05-02
"""
import json
import sys
import time
import argparse
from camoufox.sync_api import Camoufox


def search_booking(destination, checkin, checkout, adults=2, rooms=1,
                   max_price=None, currency="EUR"):
    """Search Booking.com and return hotel results."""

    base = "https://www.booking.com/searchresults.html"
    params = {
        "ss": destination,
        "checkin": checkin,
        "checkout": checkout,
        "group_adults": adults,
        "no_rooms": rooms,
        "selected_currency": currency,
    }
    url = base + "?" + "&".join(f"{k}={v}" for k, v in params.items())

    print(f"🔍 Searching: {destination}", file=sys.stderr)

    with Camoufox(
        headless=True,
        geoip=True,
        humanize=True,
    ) as browser:
        page = browser.new_page(ignore_https_errors=True)
        page.set_default_timeout(60000)

        page.goto(url, wait_until="domcontentloaded")
        print("⏳ Waiting for results...", file=sys.stderr)
        time.sleep(8)

        # Progressive scroll to trigger lazy loading
        for i in range(8):
            page.evaluate(f"window.scrollBy(0, {600 + i * 200})")
            time.sleep(1.5 + i * 0.2)

        page.evaluate("window.scrollTo(0, 0)")
        time.sleep(2)

        # Extract results
        results = page.evaluate("""
            () => {
                const hotels = [];
                const cards = document.querySelectorAll(
                    '[data-testid="property-card"]'
                );

                cards.forEach(card => {
                    try {
                        const titleEl = card.querySelector(
                            '[data-testid="title"]'
                        );
                        const priceEl = card.querySelector(
                            '[data-testid="price-and-discounted-price"]'
                        );
                        const scoreEl = card.querySelector(
                            '[data-testid="review-score"]'
                        );
                        const linkEl = card.querySelector(
                            'a[data-testid="title-link"]'
                        );
                        const distanceEl = card.querySelector(
                            '[data-testid="distance"]'
                        );

                        const scoreText = scoreEl
                            ? scoreEl.textContent.trim() : '';
                        const scoreMatch = scoreText.match(/([\\d.]+)/);

                        hotels.push({
                            name: titleEl
                                ? titleEl.textContent.trim() : '',
                            price: priceEl
                                ? priceEl.textContent.trim() : '',
                            score: scoreMatch
                                ? parseFloat(scoreMatch[1]) : null,
                            distance: distanceEl
                                ? distanceEl.textContent.trim() : '',
                            url: linkEl ? linkEl.href : '',
                        });
                    } catch (e) {}
                });

                if (hotels.length === 0) {
                    const altCards = document.querySelectorAll('.sr_item');
                    altCards.forEach(card => {
                        try {
                            const titleEl = card.querySelector(
                                '.sr-hotel__name'
                            );
                            const priceEl = card.querySelector(
                                '.bui-price-display__value'
                            );
                            const scoreEl = card.querySelector(
                                '.bui-review-score__badge'
                            );
                            hotels.push({
                                name: titleEl
                                    ? titleEl.textContent.trim()
                                    : card.textContent.slice(0, 80),
                                price: priceEl
                                    ? priceEl.textContent.trim() : '',
                                score: scoreEl
                                    ? parseFloat(
                                        scoreEl.textContent.trim()
                                      ) : null,
                                url: card.querySelector('a')
                                    ? card.querySelector('a').href : '',
                            });
                        } catch (e) {}
                    });
                }

                return hotels;
            }
        """)

        print(f"✅ Found {len(results)} hotels", file=sys.stderr)

    return results


def main():
    parser = argparse.ArgumentParser(
        description="Search Booking.com with Camoufox"
    )
    parser.add_argument("--destination", required=True)
    parser.add_argument("--checkin", required=True,
                        help="Check-in date YYYY-MM-DD")
    parser.add_argument("--checkout", required=True,
                        help="Check-out date YYYY-MM-DD")
    parser.add_argument("--adults", type=int, default=2)
    parser.add_argument("--rooms", type=int, default=1)
    parser.add_argument("--max-price", type=int,
                        help="Max price in specified currency")
    parser.add_argument("--currency", default="EUR")
    parser.add_argument("--json", action="store_true",
                        help="Output JSON only")
    parser.add_argument("--limit", type=int, default=50,
                        help="Max results to show")

    args = parser.parse_args()

    try:
        results = search_booking(
            destination=args.destination,
            checkin=args.checkin,
            checkout=args.checkout,
            adults=args.adults,
            rooms=args.rooms,
            max_price=args.max_price,
            currency=args.currency,
        )

        # Filter by max price
        filtered = []
        for h in results:
            if args.max_price:
                price_str = (h.get("price", "")
                             .replace("€", "").replace("US$", "")
                             .replace(",", ".").strip())
                try:
                    price_num = float(price_str.split()[0])
                    if price_num > args.max_price:
                        continue
                except (ValueError, IndexError):
                    pass
            filtered.append(h)

        if args.json:
            print(json.dumps(filtered[:args.limit],
                             indent=2, ensure_ascii=False))
        else:
            if not filtered:
                print("No results found.")
                return

            print(f"\n📋 {len(filtered[:args.limit])} results "
                  f"for {args.destination} "
                  f"({args.checkin} → {args.checkout}):\n")
            for i, h in enumerate(filtered[:args.limit], 1):
                name = h.get("name", "?")
                price = h.get("price", "?")
                score = h.get("score", "?")
                dist = h.get("distance", "")
                url = h.get("url", "")
                print(f"{i}. {name}")
                print(f"   💰 {price}  ⭐ {score}  📍 {dist}")
                if url:
                    print(f"   🔗 {url}")
                print()

    except Exception as e:
        print(f"❌ Error: {e}", file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    main()
