#!/usr/bin/env python3
"""
Playground script to test the openbrowser actor API.

This script demonstrates:
- Starting a browser session
- Using the actor API to navigate and interact
- Finding elements, clicking, scrolling, JavaScript evaluation
- Testing most of the available methods
"""

import asyncio
import json
import logging

from openbrowser import Browser

# Configure logging to see what's happening
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


async def main():
	"""Main playground function."""
	logger.info('🚀 Starting browser actor playground')

	# Create browser session
	browser = Browser()

	try:
		# Start the browser
		await browser.start()
		logger.info('✅ Browser session started')

		# Navigate to Wikipedia using integrated methods
		logger.info('📖 Navigating to Wikipedia...')
		page = await browser.new_page('https://en.wikipedia.org')

		# Get basic page info
		url = await page.get_url()
		title = await page.get_title()
		logger.info(f'📄 Page loaded: {title} ({url})')

		# Take a screenshot
		logger.info('📸 Taking initial screenshot...')
		screenshot_b64 = await page.screenshot()
		logger.info(f'📸 Screenshot captured: {len(screenshot_b64)} bytes')

		# Set viewport size
		logger.info('🖥️ Setting viewport to 1920x1080...')
		await page.set_viewport_size(1920, 1080)

		# Execute some JavaScript to count links
		logger.info('🔍 Counting article links using JavaScript...')
		js_code = """() => {
			// Find all article links on the page
			const links = Array.from(document.querySelectorAll('a[href*="/wiki/"]:not([href*=":"])'))
				.filter(link => !link.href.includes('Main_Page') && !link.href.includes('Special:'));
			
			return {
				total: links.length,
				sample: links.slice(0, 3).map(link => ({
					href: link.href,
					text: link.textContent.trim() 
				}))
			};
		}"""

		link_info = json.loads(await page.evaluate(js_code))
		logger.info(f'🔗 Found {link_info["total"]} article links')
		# Try to find and interact with links using CSS selector
		try:
			# Find article links on the page
			links = await page.get_elements_by_css_selector('a[href*="/wiki/"]:not([href*=":"])')

			if links:
				logger.info(f'📋 Found {len(links)} wiki links via CSS selector')

				# Pick the first link
				link_element = links[0]

				# Get link info using available methods
				basic_info = await link_element.get_basic_info()
				link_href = await link_element.get_attribute('href')

				logger.info(f'🎯 Selected element: <{basic_info["nodeName"]}>')
				logger.info(f'🔗 Link href: {link_href}')

				if basic_info['boundingBox']:
					bbox = basic_info['boundingBox']
					logger.info(f'📏 Position: ({bbox["x"]}, {bbox["y"]}) Size: {bbox["width"]}x{bbox["height"]}')

				# Test element interactions with robust implementations
				logger.info('👆 Hovering over the element...')
				await link_element.hover()
				await asyncio.sleep(1)

				logger.info('🔍 Focusing the element...')
				await link_element.focus()
				await asyncio.sleep(0.5)

				# Click the link using robust click method
				logger.info('🖱️ Clicking the link with robust fallbacks...')
				await link_element.click()

				# Wait for navigation
				await asyncio.sleep(3)

				# Get new page info
				new_url = await page.get_url()
				new_title = await page.get_title()
				logger.info(f'📄 Navigated to: {new_title}')
				logger.info(f'🌐 New URL: {new_url}')
			else:
				logger.warning('❌ No links found to interact with')

		except Exception as e:
			logger.warning(f'⚠️ Link interaction failed: {e}')

		# Scroll down the page
		logger.info('📜 Scrolling down the page...')
		mouse = await page.mouse
		await mouse.scroll(x=0, y=100, delta_y=500)
		await asyncio.sleep(1)

		# Test mouse operations
		logger.info('🖱️ Testing mouse operations...')
		await mouse.move(x=100, y=200)
		await mouse.click(x=150, y=250)

		# Execute more JavaScript examples
		logger.info('🧪 Testing JavaScript evaluation...')

		# Simple expressions
		page_height = await page.evaluate('() => document.body.scrollHeight')
		current_scroll = await page.evaluate('() => window.pageYOffset')
		logger.info(f'📏 Page height: {page_height}px, current scroll: {current_scroll}px')

		# JavaScript with arguments
		result = await page.evaluate('(x) => x * 2', 21)
		logger.info(f'🧮 JavaScript with args: 21 * 2 = {result}')

		# More complex JavaScript
		page_stats = json.loads(
			await page.evaluate("""() => {
			return {
				url: window.location.href,
				title: document.title,
				links: document.querySelectorAll('a').length,
				images: document.querySelectorAll('img').length,
				scrollTop: window.pageYOffset,
				viewportHeight: window.innerHeight
			};
		}""")
		)
		logger.info(f'📊 Page stats: {page_stats}')

		# Get page title using different methods
		title_via_js = await page.evaluate('() => document.title')
		title_via_api = await page.get_title()
		logger.info(f'📝 Title via JS: "{title_via_js}"')
		logger.info(f'📝 Title via API: "{title_via_api}"')

		# Take a final screenshot
		logger.info('📸 Taking final screenshot...')
		final_screenshot = await page.screenshot()
		logger.info(f'📸 Final screenshot: {len(final_screenshot)} bytes')

		# Test browser navigation with error handling
		logger.info('⬅️ Testing browser back navigation...')
		try:
			await page.go_back()
			await asyncio.sleep(2)

			back_url = await page.get_url()
			back_title = await page.get_title()
			logger.info(f'📄 After going back: {back_title}')
			logger.info(f'🌐 Back URL: {back_url}')
		except RuntimeError as e:
			logger.info(f'ℹ️ Navigation back failed as expected: {e}')

		# Test creating new page
		logger.info('🆕 Creating new blank page...')
		new_page = await browser.new_page()
		new_page_url = await new_page.get_url()
		logger.info(f'🆕 New page created with URL: {new_page_url}')

		# Get all pages
		all_pages = await browser.get_pages()
		logger.info(f'📑 Total pages: {len(all_pages)}')

		# Test form interaction if we can find a form
		try:
			# Look for search input on the page
			search_inputs = await page.get_elements_by_css_selector('input[type="search"], input[name*="search"]')

			if search_inputs:
				search_input = search_inputs[0]
				logger.info('🔍 Found search input, testing form interaction...')

				await search_input.focus()
				await search_input.fill('test search query')
				await page.press('Enter')

				logger.info('✅ Form interaction test completed')
			else:
				logger.info('ℹ️ No search inputs found for form testing')

		except Exception as e:
			logger.info(f'ℹ️ Form interaction test skipped: {e}')

			# wait 2 seconds before closing the new page
		logger.info('🕒 Waiting 2 seconds before closing the new page...')
		await asyncio.sleep(2)
		logger.info('🗑️ Closing new page...')
		await browser.close_page(new_page)

		logger.info('✅ Playground completed successfully!')

		input('Press Enter to continue...')

	except Exception as e:
		logger.error(f'❌ Error in playground: {e}', exc_info=True)

	finally:
		# Clean up
		logger.info('🧹 Cleaning up...')
		try:
			await browser.stop()
			logger.info('✅ Browser session stopped')
		except Exception as e:
			logger.error(f'❌ Error stopping browser: {e}')


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