"""
MCP Server for Web Browser Automation
Exposes Julia Browser tools via Model Context Protocol
"""

import os
from contextlib import redirect_stdout, redirect_stderr
from typing import Dict, Any
from fastmcp import FastMCP
from julia_browser import AgentSDK


class BrowserSession:
    """Singleton browser session manager"""
    
    _instance = None
    _browser = None
    _current_url = None
    
    @classmethod
    def get_browser(cls):
        """Get or create browser instance"""
        if cls._browser is None:
            with open(os.devnull, 'w') as devnull:
                with redirect_stdout(devnull), redirect_stderr(devnull):
                    cls._browser = AgentSDK()
        return cls._browser
    
    @classmethod
    def get_current_url(cls):
        """Get current URL"""
        return cls._current_url
    
    @classmethod
    def set_current_url(cls, url: str):
        """Set current URL"""
        cls._current_url = url


def create_server() -> FastMCP:
    """Create and configure the MCP server with browser tools"""
    
    mcp = FastMCP("webbrowser-mcp")
    
    @mcp.tool()
    def open_website(url: str) -> Dict[str, Any]:
        """
        Open a website and return its title and basic information.
        
        Args:
            url: The URL to open (e.g., "https://example.com")
        
        Returns:
            dict: Page title, URL, and success status
        """
        try:
            browser = BrowserSession.get_browser()
            result = browser.open_website(url)
            BrowserSession.set_current_url(url)
            return {
                "success": True,
                "url": url,
                "title": result.get('title', 'No title'),
                "message": f"Successfully opened: {result.get('title', url)}"
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "message": f"Failed to open website: {str(e)}"
            }
    
    @mcp.tool()
    def list_elements() -> Dict[str, Any]:
        """
        List all interactive elements on the current page.
        
        Returns:
            dict: Information about clickable elements, inputs, and buttons
        """
        try:
            browser = BrowserSession.get_browser()
            elements = browser.list_elements()
            return {
                "success": True,
                "total_clickable": elements.get('total_clickable', 0),
                "elements": elements,
                "message": f"Found {elements.get('total_clickable', 0)} interactive elements"
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "message": f"Failed to list elements: {str(e)}"
            }
    
    @mcp.tool()
    def get_page_info() -> Dict[str, Any]:
        """
        Get current page title, URL, and full content.
        
        Returns:
            dict: Page information including title, URL, and content
        """
        try:
            browser = BrowserSession.get_browser()
            page_info = browser.get_page_info()
            return {
                "success": True,
                "url": page_info.get('url', BrowserSession.get_current_url()),
                "title": page_info.get('title', 'No title'),
                "content": page_info.get('content', ''),
                "message": f"Page info retrieved for: {page_info.get('title', 'Unknown')}"
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "message": f"Failed to get page info: {str(e)}"
            }
    
    @mcp.tool()
    def search_page(term: str) -> Dict[str, Any]:
        """
        Search for text within the current page.
        
        Args:
            term: The search term to find on the page
        
        Returns:
            dict: Search results
        """
        try:
            browser = BrowserSession.get_browser()
            results = browser.search_page(term)
            return {
                "success": True,
                "term": term,
                "results": results,
                "message": f"Found search results for: {term}"
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "message": f"Failed to search page: {str(e)}"
            }
    
    @mcp.tool()
    def click_element(element_id: int) -> Dict[str, Any]:
        """
        Click a button or link on the page.
        
        Args:
            element_id: The ID of the element to click
        
        Returns:
            dict: Confirmation of the action
        """
        try:
            browser = BrowserSession.get_browser()
            browser.click_element(element_id)
            return {
                "success": True,
                "message": f"Clicked element {element_id}"
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "message": f"Failed to click element: {str(e)}"
            }
    
    @mcp.tool()
    def type_text(element_id: int, text: str) -> Dict[str, Any]:
        """
        Type text into an input field.
        
        Args:
            element_id: The ID of the input element
            text: The text to type into the field
        
        Returns:
            dict: Confirmation of the action
        """
        try:
            browser = BrowserSession.get_browser()
            browser.type_text(element_id, text)
            return {
                "success": True,
                "message": f"Typed '{text}' into element {element_id}"
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "message": f"Failed to type text: {str(e)}"
            }
    
    @mcp.tool()
    def submit_form() -> Dict[str, Any]:
        """
        Submit the current form on the page.
        
        Returns:
            dict: Result page title and success status
        """
        try:
            browser = BrowserSession.get_browser()
            result = browser.submit_form()
            return {
                "success": True,
                "title": result.get('title', 'No title'),
                "message": f"Form submitted successfully: {result.get('title', 'Unknown page')}"
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "message": f"Failed to submit form: {str(e)}"
            }
    
    @mcp.tool()
    def follow_link(link_url: str) -> Dict[str, Any]:
        """
        Navigate to a link by its URL.
        
        Args:
            link_url: The URL of the link to follow
        
        Returns:
            dict: Confirmation of the navigation
        """
        try:
            browser = BrowserSession.get_browser()
            result = browser.follow_link(link_url)
            return {
                "success": True,
                "message": f"Followed link to {link_url}",
                "title": result.get('title', 'No title')
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "message": f"Failed to follow link: {str(e)}"
            }
    
    @mcp.tool()
    def scroll_down(chunks: int = 1) -> Dict[str, Any]:
        """
        Scroll down to see more content.
        
        Args:
            chunks: Number of chunks to scroll (default: 1)
        
        Returns:
            dict: Confirmation and scroll information
        """
        try:
            browser = BrowserSession.get_browser()
            result = browser.scroll_down(chunks)
            return {
                "success": True,
                "chunks": chunks,
                "message": f"Scrolled down {chunks} chunk(s)",
                "scroll_info": result
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "message": f"Failed to scroll down: {str(e)}"
            }
    
    @mcp.tool()
    def scroll_up(chunks: int = 1) -> Dict[str, Any]:
        """
        Scroll up to see previous content.
        
        Args:
            chunks: Number of chunks to scroll (default: 1)
        
        Returns:
            dict: Confirmation and scroll information
        """
        try:
            browser = BrowserSession.get_browser()
            result = browser.scroll_up(chunks)
            return {
                "success": True,
                "chunks": chunks,
                "message": f"Scrolled up {chunks} chunk(s)",
                "scroll_info": result
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "message": f"Failed to scroll up: {str(e)}"
            }
    
    @mcp.tool()
    def scroll_to_top() -> Dict[str, Any]:
        """
        Jump to the top of the page.
        
        Returns:
            dict: Confirmation of the action
        """
        try:
            browser = BrowserSession.get_browser()
            result = browser.scroll_to_top()
            return {
                "success": True,
                "message": "Scrolled to top of page",
                "scroll_info": result
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "message": f"Failed to scroll to top: {str(e)}"
            }
    
    @mcp.tool()
    def scroll_to_bottom() -> Dict[str, Any]:
        """
        Jump to the bottom of the page.
        
        Returns:
            dict: Confirmation of the action
        """
        try:
            browser = BrowserSession.get_browser()
            result = browser.scroll_to_bottom()
            return {
                "success": True,
                "message": "Scrolled to bottom of page",
                "scroll_info": result
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "message": f"Failed to scroll to bottom: {str(e)}"
            }
    
    @mcp.tool()
    def get_scroll_info() -> Dict[str, Any]:
        """
        Get current scroll position and progress.
        
        Returns:
            dict: Scroll position and page information
        """
        try:
            browser = BrowserSession.get_browser()
            scroll_info = browser.get_scroll_info()
            return {
                "success": True,
                "scroll_info": scroll_info,
                "message": "Retrieved scroll information"
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e),
                "message": f"Failed to get scroll info: {str(e)}"
            }
    
    return mcp


def main():
    """Main entry point for running the MCP server"""
    server = create_server()
    server.run()


if __name__ == "__main__":
    main()
