import pytest
from pytest_httpserver import HTTPServer

from browser_use.agent.views import ActionResult
from browser_use.browser import BrowserSession
from browser_use.browser.profile import BrowserProfile
from browser_use.tools.service import Tools


@pytest.fixture(scope='session')
def http_server():
	"""Create and provide a test HTTP server that serves static content."""
	server = HTTPServer()
	server.start()

	# Add route for ARIA menu test page
	server.expect_request('/aria-menu').respond_with_data(
		"""
		<!DOCTYPE html>
		<html>
		<head>
			<title>ARIA Menu Test</title>
			<style>
				.menu {
					list-style: none;
					padding: 0;
					margin: 0;
					border: 1px solid #ccc;
					background: white;
					width: 200px;
				}
				.menu-item {
					padding: 10px 20px;
					border-bottom: 1px solid #eee;
				}
				.menu-item:hover {
					background: #f0f0f0;
				}
				.menu-item-anchor {
					text-decoration: none;
					color: #333;
					display: block;
				}
				#result {
					margin-top: 20px;
					padding: 10px;
					border: 1px solid #ddd;
					min-height: 20px;
				}
			</style>
		</head>
		<body>
			<h1>ARIA Menu Test</h1>
			<p>This menu uses ARIA roles instead of native select elements</p>
			
			<!-- Exactly like the HTML provided in the issue -->
			<ul class="menu menu-format-standard menu-regular" role="menu" id="pyNavigation1752753375773" style="display: block;">
				<li class="menu-item menu-item-enabled" role="presentation">
					<a href="#" onclick="pd(event);" class="menu-item-anchor" tabindex="0" role="menuitem">
						<span class="menu-item-title-wrap"><span class="menu-item-title">Filter</span></span>
					</a>
				</li>
				<li class="menu-item menu-item-enabled" role="presentation" id="menu-item-$PpyNavigation1752753375773$ppyElements$l2">
					<a href="#" onclick="pd(event);" class="menu-item-anchor menu-item-expand" tabindex="0" role="menuitem" aria-haspopup="true">
						<span class="menu-item-title-wrap"><span class="menu-item-title">Sort</span></span>
					</a>
					<div class="menu-panel-wrapper">
						<ul class="menu menu-format-standard menu-regular" role="menu" id="$PpyNavigation1752753375773$ppyElements$l2">
							<li class="menu-item menu-item-enabled" role="presentation">
								<a href="#" onclick="pd(event);" class="menu-item-anchor" tabindex="0" role="menuitem">
									<span class="menu-item-title-wrap"><span class="menu-item-title">Lowest to highest</span></span>
								</a>
							</li>
							<li class="menu-item menu-item-enabled" role="presentation">
								<a href="#" onclick="pd(event);" class="menu-item-anchor" tabindex="0" role="menuitem">
									<span class="menu-item-title-wrap"><span class="menu-item-title">Highest to lowest</span></span>
								</a>
							</li>
						</ul>
					</div>
				</li>
				<li class="menu-item menu-item-enabled" role="presentation">
					<a href="#" onclick="pd(event);" class="menu-item-anchor" tabindex="0" role="menuitem">
						<span class="menu-item-title-wrap"><span class="menu-item-title">Appearance</span></span>
					</a>
				</li>
				<li class="menu-item menu-item-enabled" role="presentation">
					<a href="#" onclick="pd(event);" class="menu-item-anchor" tabindex="0" role="menuitem">
						<span class="menu-item-title-wrap"><span class="menu-item-title">Summarize</span></span>
					</a>
				</li>
				<li class="menu-item menu-item-enabled" role="presentation">
					<a href="#" onclick="pd(event);" class="menu-item-anchor" tabindex="0" role="menuitem">
						<span class="menu-item-title-wrap"><span class="menu-item-title">Delete</span></span>
					</a>
				</li>
			</ul>
			
			<div id="result">Click an option to see the result</div>
			
			<script>
				// Mock the pd function that prevents default
				function pd(event) {
					event.preventDefault();
					const text = event.target.closest('[role="menuitem"]').textContent.trim();
					document.getElementById('result').textContent = 'Clicked: ' + text;
				}
			</script>
		</body>
		</html>
		""",
		content_type='text/html',
	)

	yield server
	server.stop()


@pytest.fixture(scope='session')
def base_url(http_server):
	"""Return the base URL for the test HTTP server."""
	return f'http://{http_server.host}:{http_server.port}'


@pytest.fixture(scope='module')
async def browser_session():
	"""Create and provide a Browser instance with security disabled."""
	browser_session = BrowserSession(
		browser_profile=BrowserProfile(
			headless=True,
			user_data_dir=None,
			keep_alive=True,
			chromium_sandbox=False,  # Disable sandbox for CI environment
		)
	)
	await browser_session.start()
	yield browser_session
	await browser_session.kill()


@pytest.fixture(scope='function')
def tools():
	"""Create and provide a Tools instance."""
	return Tools()


class TestARIAMenuDropdown:
	"""Test ARIA menu support for get_dropdown_options and select_dropdown_option."""

	@pytest.mark.skip(reason='TODO: fix')
	async def test_get_dropdown_options_with_aria_menu(self, tools, browser_session: BrowserSession, base_url):
		"""Test that get_dropdown_options can retrieve options from ARIA menus."""
		# Navigate to the ARIA menu test page
		await tools.navigate(url=f'{base_url}/aria-menu', new_tab=False, browser_session=browser_session)

		# Wait for the page to load
		from browser_use.browser.events import NavigationCompleteEvent

		await browser_session.event_bus.expect(NavigationCompleteEvent, timeout=10.0)

		# Initialize the DOM state to populate the selector map
		await browser_session.get_browser_state_summary()

		# Find the ARIA menu element by ID
		menu_index = await browser_session.get_index_by_id('pyNavigation1752753375773')

		assert menu_index is not None, 'Could not find ARIA menu element'

		# Execute the action with the menu index
		result = await tools.dropdown_options(index=menu_index, browser_session=browser_session)

		# Verify the result structure
		assert isinstance(result, ActionResult)
		assert result.extracted_content is not None

		# Expected ARIA menu options
		expected_options = ['Filter', 'Sort', 'Appearance', 'Summarize', 'Delete']

		# Verify all options are returned
		for option in expected_options:
			assert option in result.extracted_content, f"Option '{option}' not found in result content"

		# Verify the instruction for using the text in select_dropdown is included
		assert 'Use the exact text string in select_dropdown' in result.extracted_content

	@pytest.mark.skip(reason='TODO: fix')
	async def test_select_dropdown_option_with_aria_menu(self, tools, browser_session: BrowserSession, base_url):
		"""Test that select_dropdown_option can select an option from ARIA menus."""
		# Navigate to the ARIA menu test page
		await tools.navigate(url=f'{base_url}/aria-menu', new_tab=False, browser_session=browser_session)

		# Wait for the page to load
		from browser_use.browser.events import NavigationCompleteEvent

		await browser_session.event_bus.expect(NavigationCompleteEvent, timeout=10.0)

		# Initialize the DOM state to populate the selector map
		await browser_session.get_browser_state_summary()

		# Find the ARIA menu element by ID
		menu_index = await browser_session.get_index_by_id('pyNavigation1752753375773')

		assert menu_index is not None, 'Could not find ARIA menu element'

		# Execute the action with the menu index to select "Filter"
		result = await tools.select_dropdown(index=menu_index, text='Filter', browser_session=browser_session)

		# Verify the result structure
		assert isinstance(result, ActionResult)

		# Core logic validation: Verify selection was successful
		assert result.extracted_content is not None
		assert 'selected option' in result.extracted_content.lower() or 'clicked' in result.extracted_content.lower()
		assert 'Filter' in result.extracted_content

		# Verify the click actually had an effect on the page using CDP
		cdp_session = await browser_session.get_or_create_cdp_session()
		result = await cdp_session.cdp_client.send.Runtime.evaluate(
			params={'expression': "document.getElementById('result').textContent", 'returnByValue': True},
			session_id=cdp_session.session_id,
		)
		result_text = result.get('result', {}).get('value', '')
		assert 'Filter' in result_text, f"Expected 'Filter' in result text, got '{result_text}'"

	@pytest.mark.skip(reason='TODO: fix')
	async def test_get_dropdown_options_with_nested_aria_menu(self, tools, browser_session: BrowserSession, base_url):
		"""Test that get_dropdown_options can handle nested ARIA menus (like Sort submenu)."""
		# Navigate to the ARIA menu test page
		await tools.navigate(url=f'{base_url}/aria-menu', new_tab=False, browser_session=browser_session)

		# Wait for the page to load
		from browser_use.browser.events import NavigationCompleteEvent

		await browser_session.event_bus.expect(NavigationCompleteEvent, timeout=10.0)

		# Initialize the DOM state to populate the selector map
		await browser_session.get_browser_state_summary()

		# Get the selector map
		selector_map = await browser_session.get_selector_map()

		# Find the nested ARIA menu element in the selector map
		nested_menu_index = None
		for idx, element in selector_map.items():
			# Look for the nested UL with id containing "$PpyNavigation"
			if (
				element.tag_name.lower() == 'ul'
				and '$PpyNavigation' in str(element.attributes.get('id', ''))
				and element.attributes.get('role') == 'menu'
			):
				nested_menu_index = idx
				break

		# The nested menu might not be in the selector map initially if it's hidden
		# In that case, we should test the main menu
		if nested_menu_index is None:
			# Find the main menu instead
			for idx, element in selector_map.items():
				if element.tag_name.lower() == 'ul' and element.attributes.get('id') == 'pyNavigation1752753375773':
					nested_menu_index = idx
					break

		assert nested_menu_index is not None, (
			f'Could not find any ARIA menu element in selector map. Available elements: {[f"{idx}: {element.tag_name}" for idx, element in selector_map.items()]}'
		)

		# Execute the action with the menu index
		result = await tools.dropdown_options(index=nested_menu_index, browser_session=browser_session)

		# Verify the result structure
		assert isinstance(result, ActionResult)
		assert result.extracted_content is not None

		# The action should return some menu options
		assert 'Use the exact text string in select_dropdown' in result.extracted_content
