"""Base adapter interface for WebView protocol implementations."""

from __future__ import annotations

from abc import ABC, abstractmethod
from typing import Any


class BaseAdapter(ABC):
    """Abstract base class for WebView protocol adapters.

    All protocol adapters (CDP, WebDriver) must implement this interface
    to ensure consistent behavior across different protocols.
    """

    @abstractmethod
    def connect(self) -> None:
        """Establish connection to the WebView endpoint.

        Raises:
            WebViewConnectionError: If connection fails.
        """

    @abstractmethod
    def disconnect(self) -> None:
        """Disconnect from the WebView and cleanup resources."""

    @property
    @abstractmethod
    def endpoint(self) -> str:
        """Get the endpoint URL."""

    @property
    @abstractmethod
    def is_connected(self) -> bool:
        """Check if currently connected to a WebView."""

    @abstractmethod
    def click(self, selector: str, timeout_ms: int = 30000) -> None:
        """Click an element by CSS selector.

        Args:
            selector: CSS selector for the element.
            timeout_ms: Maximum wait time in milliseconds.

        Raises:
            WebViewElementNotFoundError: If element not found.
            WebViewOperationError: If operation fails.
        """

    @abstractmethod
    def type_text(self, selector: str, text: str, timeout_ms: int = 30000) -> None:
        """Fill an input field with text.

        Args:
            selector: CSS selector for the input element.
            text: Text to type.
            timeout_ms: Maximum wait time in milliseconds.

        Raises:
            WebViewElementNotFoundError: If element not found.
            WebViewOperationError: If operation fails.
        """

    @abstractmethod
    def get_text(self, selector: str, timeout_ms: int = 30000) -> str:
        """Get text content of an element.

        Args:
            selector: CSS selector for the element.
            timeout_ms: Maximum wait time in milliseconds.

        Returns:
            Text content of the element.

        Raises:
            WebViewElementNotFoundError: If element not found.
            WebViewOperationError: If operation fails.
        """

    @abstractmethod
    def get_attribute(self, selector: str, attr: str, timeout_ms: int = 30000) -> str:
        """Get an attribute value of an element.

        Args:
            selector: CSS selector for the element.
            attr: Name of the attribute.
            timeout_ms: Maximum wait time in milliseconds.

        Returns:
            Attribute value.

        Raises:
            WebViewElementNotFoundError: If element not found.
            WebViewOperationError: If operation fails.
        """

    @abstractmethod
    def screenshot(
        self,
        path: str,
        selector: str | None = None,
        timeout_ms: int = 30000,
    ) -> bytes:
        """Take a screenshot.

        Args:
            path: File path to save screenshot.
            selector: Optional CSS selector for element screenshot.
            timeout_ms: Maximum wait time in milliseconds.

        Returns:
            Screenshot image bytes.

        Raises:
            WebViewElementNotFoundError: If selector specified but element not found.
            WebViewOperationError: If screenshot fails.
        """

    @abstractmethod
    def execute_script(self, script: str, *args: Any) -> Any:
        """Execute JavaScript in the page context.

        Args:
            script: JavaScript code to execute.
            *args: Arguments to pass to the script.

        Returns:
            Result of script execution.

        Raises:
            WebViewOperationError: If script execution fails.
        """

    @abstractmethod
    def wait_for_selector(self, selector: str, timeout_ms: int = 30000) -> bool:
        """Wait for an element to appear in the DOM.

        Args:
            selector: CSS selector to wait for.
            timeout_ms: Maximum wait time in milliseconds.

        Returns:
            True if element found, False if timeout.
        """

    @property
    @abstractmethod
    def url(self) -> str:
        """Get the current page URL."""

    @property
    @abstractmethod
    def title(self) -> str:
        """Get the current page title."""
