"""
Integration guide for Page Object Model refactoring.

This document explains how to refactor the execute_action method incrementally
using the new page objects and action builders.
"""

# ============================================================================
# REFACTORED EXECUTE_ACTION METHOD
# ============================================================================

"""
Example of refactored execute_action method using page objects.

Replace the massive execute_action method (lines 1213-3468 in ai_agents_web.py)
with this more modular approach.
"""

async def execute_action(self, page: Page, action: Dict[str, Any]) -> Dict[str, Any]:
    '''
    Execute a mapped action on the page using Page Object Model pattern.
    
    This refactored version delegates to specialized page objects and builders
    for different action types, improving maintainability and testability.
    '''
    from datetime import datetime
    from backend.utils.action_builders import (
        KeyboardActionBuilder, WaitActionBuilder, NavigationActionBuilder,
        EnsureToggleActionBuilder, ClickActionBuilder, TypeActionBuilder,
        HoverActionBuilder, ScrollActionBuilder, ActionBuilderFactory
    )
    from backend.utils.page_objects import (
        ElementFinder, ClickableElementPage, FormPage, DialogPage
    )
    
    # Initialize result
    result = {
        "success": False,
        "action": action,
        "timestamp": datetime.now().isoformat(),
        "error": None,
        "details": {}
    }
    
    try:
        locator = action["locator"]
        value = action["value"]
        action_type = action["action"]
        input_text = action.get("input_text", "")
        
        # ====================================================================
        # SECTION 1: SIMPLE ACTIONS (No element finding needed)
        # ====================================================================
        
        simple_builder = ActionBuilderFactory.get_simple_action_builder(page, action_type)
        
        if action_type == "press" and locator == "keyboard":
            return await simple_builder.execute(action)
        
        if action_type == "wait":
            return await simple_builder.execute(action)
        
        if action_type in ("navigate", "goto") and locator == "url":
            nav_builder = NavigationActionBuilder(page)
            return await nav_builder.execute_navigate(action)
        
        if action_type in ("back", "go_back", "navigate_back") and locator in ("history", "keyboard", "url", None, ""):
            nav_builder = NavigationActionBuilder(page)
            return await nav_builder.execute_back(action)
        
        if action_type == "ensure_toggle":
            toggle_builder = EnsureToggleActionBuilder(page)
            return await toggle_builder.execute(action)
        
        # ====================================================================
        # SECTION 2: MODAL/DIALOG DETECTION
        # ====================================================================
        
        dialog_page = DialogPage(page)
        modal_present = await dialog_page.detect_modal()
        
        if modal_present:
            modal_root = await dialog_page.get_modal_root()
        else:
            modal_root = None
        
        # ====================================================================
        # SECTION 3: ELEMENT FINDING
        # ====================================================================
        
        finder = ElementFinder(page, page.main_frame, modal_root)
        element = None
        frame = page.main_frame
        scope = modal_root
        
        # Try to find element in main frame or modal scope
        if action_type in ("click", "dblclick", "type", "hover", "scroll"):
            # First try direct finding based on locator
            if locator == "aria-label":
                element = await finder.find_by_aria_label(str(value))
            elif locator == "text":
                element = await finder.find_by_text(str(value))
            elif locator == "id":
                element = await finder.find_by_id(str(value))
            elif locator == "placeholder":
                element = await finder.find_by_placeholder(str(value))
            elif locator == "xpath":
                element = await finder.find_by_xpath(str(value))
            
            # If not found in main scope, search across all frames
            if not element:
                element, found_frame = await finder.find_in_frames(locator, str(value))
                if element and found_frame:
                    frame = found_frame
        
        if not element and action_type in ("click", "dblclick", "type", "hover"):
            result["error"] = f"Element not found with {locator}='{value}'"
            return result
        
        # ====================================================================
        # SECTION 4: ACTION EXECUTION (Element-based actions)
        # ====================================================================
        
        if action_type in ("click", "dblclick"):
            clicker = ClickableElementPage(page, frame, scope)
            if await clicker.click(element, action_type):
                result["success"] = True
                result["details"]["action_performed"] = action_type
            else:
                result["error"] = f"{action_type} failed"
        
        elif action_type == "type":
            form = FormPage(page, frame, scope)
            if await form.type_text(element, input_text):
                result["success"] = True
                result["details"]["action_performed"] = "type"
                result["details"]["input_text"] = input_text
            else:
                result["error"] = "Type failed"
        
        elif action_type == "hover":
            hover_builder = HoverActionBuilder(page)
            return await hover_builder.execute(action, element, frame, scope)
        
        elif action_type == "scroll":
            scroll_builder = ScrollActionBuilder(page)
            return await scroll_builder.execute(action, element, frame, scope)
        
        # ====================================================================
        # POST-ACTION CLEANUP
        # ====================================================================
        
        if result["success"]:
            # Add element info
            try:
                result["details"]["element_info"] = await finder.get_element_info(element) if element else {}
            except Exception:
                result["details"]["element_info"] = {}
            
            result["details"]["frame"] = frame.name if hasattr(frame, 'name') else "main"
        
        # Update action history
        self.action_history.append({
            "step": action.get("step", ""),
            "action": action,
            "result": result,
            "timestamp": datetime.now().isoformat()
        })
        
        return result
    
    except Exception as e:
        result["error"] = str(e)
        result["details"]["exception"] = str(e)
        return result


# ============================================================================
# MIGRATION GUIDE
# ============================================================================

"""
STEP 1: Import the new modules at the top of ai_agents_web.py:

    from backend.utils.page_objects import (
        ElementFinder, ClickableElementPage, FormPage, DialogPage,
        NavigationPage, TogglePage, ScrollPage, LinkPage, BasePage
    )
    from backend.utils.action_builders import (
        KeyboardActionBuilder, WaitActionBuilder, NavigationActionBuilder,
        EnsureToggleActionBuilder, ClickActionBuilder, TypeActionBuilder,
        HoverActionBuilder, ScrollActionBuilder, ActionBuilderFactory
    )


STEP 2: Replace the old execute_action method (lines 1213-3468) with the new refactored version.


STEP 3: Update any internal methods that reference the old inline logic:
    - _wait_for_element_interaction_ready()
    - _is_element_clickable()
    - _type_in_teams_textbox()
    - detect_modal_presence()
    - wait_for_modal_appearance()

These should now use the corresponding page object methods.


STEP 4: Test the changes:
    - Run existing test suite with no changes to behavior
    - Verify all action types still work: click, type, press, navigate, etc.
    - Check that modal detection and dialog handling still works
    - Verify frame and scope detection still works correctly


STEP 5 (Optional): Create page object compositions for specific domains:
    - FamilySafetyPage - for family safety specific UI
    - SettingsPage - for settings interactions
    - ToggleManagerPage - for managing multiple toggles
    - WebsiteFilterPage - for website filtering UI


BENEFITS OF THIS REFACTORING:
    1. Separates concerns (element finding, clicking, typing, etc.)
    2. Improves testability - easier to mock/test individual page objects
    3. Reduces code duplication - shared logic in base classes
    4. Better maintainability - specific logic in dedicated classes
    5. Easier to add new action types - create new builder class
    6. Clearer code flow - logic is distributed by responsibility
    7. Enables reuse across different agents - page objects are generic


HANDLING SPECIAL CASES:
    - For "Always allow educational websites" button: Create a special page object
    - For Teams-specific textbox typing: Extend FormPage with Teams-specific logic
    - For footer links: Create a FooterPage extending LinkPage
    - For navigation landmarks: Create specific page objects per section
"""


# ============================================================================
# EXAMPLE: CREATING CUSTOM PAGE OBJECTS FOR SPECIFIC DOMAINS
# ============================================================================

"""
# backend/utils/family_safety_pages.py

from backend.utils.page_objects import BasePage, ElementFinder, ClickableElementPage


class FamilySafetyPage(BasePage):
    '''Page object for Family Safety specific UI elements.'''
    
    async def find_app_toggle(self, app_name: str):
        '''Find toggle for specific app.'''
        finder = ElementFinder(self.page, self.current_frame, self.scope)
        return await finder.find_by_aria_label(f"{app_name} toggle")
    
    async def enable_app_monitoring(self, app_name: str) -> bool:
        '''Enable monitoring for an app.'''
        toggle = await self.find_app_toggle(app_name)
        if not toggle:
            return False
        
        clicker = ClickableElementPage(self.page, self.current_frame, self.scope)
        return await clicker.click(toggle)
    
    async def add_website_to_allow_list(self, website_url: str) -> bool:
        '''Add website to allow list.'''
        # Find the input field
        finder = ElementFinder(self.page, self.current_frame, self.scope)
        input_field = await finder.find_by_id("web-search-never-allowed-input")
        
        if not input_field:
            return False
        
        # Type the website
        from backend.utils.page_objects import FormPage
        form = FormPage(self.page, self.current_frame, self.scope)
        return await form.type_text(input_field, website_url)


class WebsiteManagerPage(BasePage):
    '''Page object for website management UI.'''
    
    async def find_allowed_websites_list(self):
        '''Find the list of allowed websites.'''
        finder = ElementFinder(self.page, self.current_frame, self.scope)
        # Implementation specific to your UI
        pass
    
    async def remove_website(self, website_url: str) -> bool:
        '''Remove website from list.'''
        # Find website item
        # Click remove button
        pass
"""

