"""Tool for grep-like text search within the current browser page (zero LLM cost)."""

from __future__ import annotations

import json
from typing import Any

from .base import Tool


class PageSearchTool(Tool):
    """Search for text patterns within the current browser page."""

    def __init__(self, *, browser_backend: Any = None) -> None:
        self._backend = browser_backend

    @property
    def name(self) -> str:
        return "page_search"

    @property
    def description(self) -> str:
        return (
            "Search for text or regex patterns within the current browser page content. "
            "Returns matching text with surrounding context. Zero LLM cost."
        )

    @property
    def parameters(self) -> dict[str, Any]:
        return {
            "type": "object",
            "properties": {
                "query": {
                    "type": "string",
                    "description": "Text or regex pattern to search for.",
                },
                "case_sensitive": {
                    "type": "boolean",
                    "description": "Case-sensitive search. Default false.",
                },
                "max_results": {
                    "type": "integer",
                    "description": "Maximum matches to return. Default 20.",
                    "minimum": 1,
                    "maximum": 200,
                },
                "context_chars": {
                    "type": "integer",
                    "description": "Characters of surrounding context per match. Default 80.",
                    "minimum": 0,
                    "maximum": 500,
                },
            },
            "required": ["query"],
        }

    async def execute(self, **kwargs: Any) -> str:
        if self._backend is None:
            return json.dumps({"error": "No browser backend available"})

        from .browser import NativePlaywrightBrowserBackend

        if not isinstance(self._backend, NativePlaywrightBrowserBackend):
            return json.dumps({"error": "page_search requires native Playwright backend"})

        query = kwargs["query"]
        case_sensitive = kwargs.get("case_sensitive", False)
        max_results = kwargs.get("max_results", 20)
        context_chars = kwargs.get("context_chars", 80)

        try:
            page = await self._backend._current_page()

            js_code = """
            (args) => {
                const [query, caseSensitive, maxResults, contextChars] = args;
                const body = document.body.innerText || '';
                const flags = caseSensitive ? 'g' : 'gi';
                let regex;
                try {
                    regex = new RegExp(query, flags);
                } catch (e) {
                    const escaped = query.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');
                    regex = new RegExp(escaped, flags);
                }
                const matches = [];
                let match;
                while ((match = regex.exec(body)) !== null && matches.length < maxResults) {
                    const start = Math.max(0, match.index - contextChars);
                    const end = Math.min(body.length, match.index + match[0].length + contextChars);
                    matches.push({
                        text: match[0],
                        position: match.index,
                        context: body.substring(start, end),
                    });
                    if (match[0].length === 0) regex.lastIndex++;
                }
                return { total_text_length: body.length, matches };
            }
            """

            data = await page.evaluate(js_code, [query, case_sensitive, max_results, context_chars])
            return json.dumps({
                "ok": True,
                "query": query,
                "match_count": len(data["matches"]),
                "page_length": data["total_text_length"],
                "matches": data["matches"],
            })
        except Exception as exc:
            return json.dumps({"error": str(exc)})
