"""
Domain-Specific Page Objects for Family Safety Features.

This file shows how to extend the base page objects for specific family safety
UI components, making the agent code more semantic and maintainable.

Installation:
    Place this file at: backend/utils/family_safety_pages.py
    
Usage:
    from backend.utils.family_safety_pages import (
        FamilySafetyPage, WebsiteManagerPage, AppManagerPage, SettingsPage
    )
"""

from typing import Optional, List, Dict, Any
from playwright.async_api import Page, Frame, ElementHandle
from backend.utils.page_objects import (
    BasePage, ElementFinder, ClickableElementPage, FormPage, TogglePage
)
from backend.core.logging_config import log_info, log_debug


class FamilySafetyPage(BasePage):
    """
    Page object for Family Safety main dashboard and settings.
    
    This page handles:
    - App monitoring toggles
    - Website filtering
    - Screen time management
    - Activity reports
    """
    
    async def find_app_toggle(self, app_name: str) -> Optional[ElementHandle]:
        """
        Find the toggle for monitoring a specific app.
        
        Args:
            app_name: Name of the application (e.g., "YouTube", "Instagram")
        
        Returns:
            Element handle if found, None otherwise
        """
        finder = ElementFinder(self.page, self.current_frame, self.scope)
        
        # Try exact aria-label match first
        label = f"{app_name} monitoring toggle"
        element = await finder.find_by_aria_label(label)
        
        if not element:
            # Try partial text match
            element = await finder.find_by_text(app_name)
        
        return element
    
    async def enable_app_monitoring(self, app_name: str) -> bool:
        """
        Enable monitoring for a specific app.
        
        Args:
            app_name: Name of the application
        
        Returns:
            True if successful, False otherwise
        """
        try:
            toggle = await self.find_app_toggle(app_name)
            if not toggle:
                log_debug(f"Could not find toggle for {app_name}")
                return False
            
            toggle_page = TogglePage(self.page, self.current_frame, self.scope)
            current_state = await toggle_page.is_toggle_on(toggle)
            
            if current_state is False or current_state is None:
                clicker = ClickableElementPage(self.page, self.current_frame, self.scope)
                success = await clicker.click(toggle)
                
                if success:
                    log_info(f"Enabled monitoring for {app_name}")
                
                return success
            
            log_info(f"Monitoring for {app_name} already enabled")
            return True
        
        except Exception as e:
            log_debug(f"Error enabling app monitoring: {e}")
            return False
    
    async def disable_app_monitoring(self, app_name: str) -> bool:
        """
        Disable monitoring for a specific app.
        
        Args:
            app_name: Name of the application
        
        Returns:
            True if successful, False otherwise
        """
        try:
            toggle = await self.find_app_toggle(app_name)
            if not toggle:
                return False
            
            toggle_page = TogglePage(self.page, self.current_frame, self.scope)
            current_state = await toggle_page.is_toggle_on(toggle)
            
            if current_state is True or current_state is None:
                clicker = ClickableElementPage(self.page, self.current_frame, self.scope)
                success = await clicker.click(toggle)
                
                if success:
                    log_info(f"Disabled monitoring for {app_name}")
                
                return success
            
            log_info(f"Monitoring for {app_name} already disabled")
            return True
        
        except Exception as e:
            log_debug(f"Error disabling app monitoring: {e}")
            return False
    
    async def get_all_monitored_apps(self) -> List[str]:
        """
        Get list of all apps currently being monitored.
        
        Returns:
            List of app names
        """
        try:
            finder = ElementFinder(self.page, self.current_frame, self.scope)
            frame = self.scope or self.current_frame
            
            # Try to find all app monitoring toggles
            app_items = []
            try:
                # Look for app cards or list items with toggles
                items = await frame.query_selector_all("[data-testid*='app'], [role='listitem'][data-app-name]")
                
                for item in items:
                    try:
                        # Extract app name from element
                        app_name_el = await item.query_selector("[data-app-name]")
                        if app_name_el:
                            app_name = await app_name_el.get_attribute("data-app-name")
                            if app_name:
                                app_items.append(app_name)
                        else:
                            # Try to get text content
                            text = await item.inner_text()
                            if text:
                                app_items.append(text.split('\n')[0])  # First line
                    except Exception:
                        continue
            except Exception:
                pass
            
            return app_items
        
        except Exception as e:
            log_debug(f"Error getting monitored apps: {e}")
            return []


class WebsiteManagerPage(BasePage):
    """
    Page object for website filtering and management.
    
    This page handles:
    - Adding websites to allow list
    - Adding websites to block list
    - Removing websites
    - Managing cultural/news categories
    """
    
    async def add_website_to_allow_list(self, website_url: str) -> bool:
        """
        Add a website to the allow list (never flag for review).
        
        Args:
            website_url: Full or partial URL to allow
        
        Returns:
            True if successful, False otherwise
        """
        try:
            # Find the input field for adding websites to allow list
            finder = ElementFinder(self.page, self.current_frame, self.scope)
            
            # Try specific ID first
            input_field = await finder.find_by_id("web-search-never-allowed-input")
            
            if not input_field:
                # Try by placeholder
                input_field = await finder.find_by_placeholder("Add a website")
            
            if not input_field:
                log_debug("Could not find website allow list input field")
                return False
            
            # Type the website
            form = FormPage(self.page, self.current_frame, self.scope)
            if await form.type_text(input_field, website_url):
                log_info(f"Added {website_url} to allow list")
                
                # Try to click 'Add' button if it appears
                await self._click_add_button()
                
                return True
            
            return False
        
        except Exception as e:
            log_debug(f"Error adding website to allow list: {e}")
            return False
    
    async def add_website_to_block_list(self, website_url: str) -> bool:
        """
        Add a website to the block list (always flag for review).
        
        Args:
            website_url: Full or partial URL to block
        
        Returns:
            True if successful, False otherwise
        """
        try:
            # Similar to allow list but for block list
            finder = ElementFinder(self.page, self.current_frame, self.scope)
            
            input_field = await finder.find_by_id("web-search-always-allowed-input")
            
            if not input_field:
                input_field = await finder.find_by_placeholder("Add site to always allow")
            
            if not input_field:
                log_debug("Could not find website block list input field")
                return False
            
            form = FormPage(self.page, self.current_frame, self.scope)
            if await form.type_text(input_field, website_url):
                log_info(f"Added {website_url} to block list")
                
                await self._click_add_button()
                
                return True
            
            return False
        
        except Exception as e:
            log_debug(f"Error adding website to block list: {e}")
            return False
    
    async def remove_website(self, website_url: str, from_list: str = "allow") -> bool:
        """
        Remove a website from allow or block list.
        
        Args:
            website_url: URL to remove
            from_list: "allow" or "block"
        
        Returns:
            True if successful, False otherwise
        """
        try:
            finder = ElementFinder(self.page, self.current_frame, self.scope)
            frame = self.scope or self.current_frame
            
            # Find the website item in the list
            website_items = await frame.query_selector_all(
                "[data-testid*='website-item'], [role='listitem'][data-url]"
            )
            
            target_item = None
            for item in website_items:
                try:
                    # Check if this item contains our website
                    text = await item.inner_text()
                    if website_url in text:
                        target_item = item
                        break
                except Exception:
                    continue
            
            if not target_item:
                log_debug(f"Could not find website item for {website_url}")
                return False
            
            # Find remove button within the item
            remove_button = None
            try:
                remove_button = await target_item.query_selector(
                    "[aria-label*='Remove'], [aria-label*='Delete'], button[data-testid*='remove']"
                )
            except Exception:
                pass
            
            if not remove_button:
                # Try finding by text
                try:
                    remove_button = await target_item.query_selector("button:has-text('Remove')")
                except Exception:
                    pass
            
            if remove_button:
                clicker = ClickableElementPage(self.page, self.current_frame, self.scope)
                success = await clicker.click(remove_button)
                
                if success:
                    log_info(f"Removed {website_url} from {from_list} list")
                
                return success
            
            log_debug(f"Could not find remove button for {website_url}")
            return False
        
        except Exception as e:
            log_debug(f"Error removing website: {e}")
            return False
    
    async def _click_add_button(self) -> bool:
        """Click the 'Add' button if visible."""
        try:
            finder = ElementFinder(self.page, self.current_frame, self.scope)
            add_button = await finder.find_by_text("Add")
            
            if add_button:
                clicker = ClickableElementPage(self.page, self.current_frame, self.scope)
                return await clicker.click(add_button)
            
            return False
        except Exception:
            return False


class AppManagerPage(BasePage):
    """
    Page object for app management and installation.
    
    This page handles:
    - Finding and installing apps from app store
    - Managing installed apps
    - Configuring app settings
    """
    
    async def find_app_in_store(self, app_name: str) -> Optional[ElementHandle]:
        """
        Find an app in the app store.
        
        Args:
            app_name: Name of the app to find
        
        Returns:
            App card element if found, None otherwise
        """
        try:
            finder = ElementFinder(self.page, self.current_frame, self.scope)
            
            # Try locator type 'app_store_item' if supported by ElementFinder
            frame = self.scope or self.current_frame
            
            # Search for app cards by text content
            app_cards = []
            try:
                app_cards = await frame.query_selector_all(
                    "[data-testid^='store-item'], [role='option'][data-testid], "
                    "[data-automationid*='app']"
                )
            except Exception:
                pass
            
            for card in app_cards:
                try:
                    text = await card.inner_text()
                    if app_name.lower() in text.lower():
                        return card
                except Exception:
                    continue
            
            return None
        
        except Exception as e:
            log_debug(f"Error finding app in store: {e}")
            return None
    
    async def install_app(self, app_name: str) -> bool:
        """
        Install an app from the app store.
        
        Args:
            app_name: Name of the app to install
        
        Returns:
            True if successful, False otherwise
        """
        try:
            app_card = await self.find_app_in_store(app_name)
            if not app_card:
                log_debug(f"Could not find app {app_name} in store")
                return False
            
            # Find and click install button within the card
            finder = ElementFinder(self.page, self.current_frame, self.scope)
            install_button = None
            
            try:
                install_button = await app_card.query_selector(
                    "[aria-label*='Install'], [aria-label*='Add'], "
                    "button[data-testid*='install'], button[data-testid*='add']"
                )
            except Exception:
                pass
            
            if not install_button:
                try:
                    install_button = await app_card.query_selector("button:has-text('Install')")
                except Exception:
                    pass
            
            if install_button:
                clicker = ClickableElementPage(self.page, self.current_frame, self.scope)
                success = await clicker.click(install_button)
                
                if success:
                    log_info(f"Installed app: {app_name}")
                
                return success
            
            log_debug(f"Could not find install button for {app_name}")
            return False
        
        except Exception as e:
            log_debug(f"Error installing app: {e}")
            return False


class SettingsPage(BasePage):
    """
    Page object for family safety settings.
    
    This page handles:
    - Screen time limits
    - App access schedules
    - Content filtering levels
    - Notification preferences
    """
    
    async def find_setting_toggle(self, setting_name: str) -> Optional[ElementHandle]:
        """
        Find a settings toggle by name.
        
        Args:
            setting_name: Name of the setting (e.g., "Screen time", "Web filtering")
        
        Returns:
            Toggle element if found, None otherwise
        """
        try:
            finder = ElementFinder(self.page, self.current_frame, self.scope)
            return await finder.find_by_aria_label(f"{setting_name} toggle")
        except Exception:
            return None
    
    async def enable_setting(self, setting_name: str) -> bool:
        """
        Enable a setting toggle.
        
        Args:
            setting_name: Name of the setting
        
        Returns:
            True if successful, False otherwise
        """
        try:
            toggle = await self.find_setting_toggle(setting_name)
            if not toggle:
                return False
            
            toggle_page = TogglePage(self.page, self.current_frame, self.scope)
            current_state = await toggle_page.is_toggle_on(toggle)
            
            if current_state is not True:
                clicker = ClickableElementPage(self.page, self.current_frame, self.scope)
                success = await clicker.click(toggle)
                
                if success:
                    log_info(f"Enabled setting: {setting_name}")
                
                return success
            
            return True
        
        except Exception as e:
            log_debug(f"Error enabling setting: {e}")
            return False
    
    async def disable_setting(self, setting_name: str) -> bool:
        """
        Disable a setting toggle.
        
        Args:
            setting_name: Name of the setting
        
        Returns:
            True if successful, False otherwise
        """
        try:
            toggle = await self.find_setting_toggle(setting_name)
            if not toggle:
                return False
            
            toggle_page = TogglePage(self.page, self.current_frame, self.scope)
            current_state = await toggle_page.is_toggle_on(toggle)
            
            if current_state is not False:
                clicker = ClickableElementPage(self.page, self.current_frame, self.scope)
                success = await clicker.click(toggle)
                
                if success:
                    log_info(f"Disabled setting: {setting_name}")
                
                return success
            
            return True
        
        except Exception as e:
            log_debug(f"Error disabling setting: {e}")
            return False


# ============================================================================
# USAGE EXAMPLES
# ============================================================================

"""
Example 1: Enable app monitoring
    
    page_obj = FamilySafetyPage(page, frame, modal_root)
    success = await page_obj.enable_app_monitoring("YouTube")

Example 2: Add website to allow list
    
    web_manager = WebsiteManagerPage(page, frame, modal_root)
    success = await web_manager.add_website_to_allow_list("example.com")

Example 3: Install app from store
    
    app_mgr = AppManagerPage(page, frame, modal_root)
    success = await app_mgr.install_app("Microsoft Edge")

Example 4: Enable screen time setting
    
    settings = SettingsPage(page, frame, modal_root)
    success = await settings.enable_setting("Screen Time")

Example 5: Complex workflow
    
    family_page = FamilySafetyPage(page, frame, modal_root)
    web_manager = WebsiteManagerPage(page, frame, modal_root)
    
    # Enable monitoring for multiple apps
    for app in ["YouTube", "Instagram", "TikTok"]:
        await family_page.enable_app_monitoring(app)
    
    # Add educational websites to allow list
    for url in ["khan-academy.org", "wikipedia.org"]:
        await web_manager.add_website_to_allow_list(url)
"""
