"""SelectorHealerAgent — AI-powered selector repair when elements aren't found.

When a CSS selector fails, this agent receives the broken selector, the page's
HTML context, and a description of the target element, then suggests a working
alternative selector.
"""

from __future__ import annotations

import json
import logging
from typing import Any

from agno.agent import Agent

from antiqa.config.models import resolve_model
from antiqa.config.schema import AntiQAConfig

log = logging.getLogger("antiqa.agents")

HEAL_SYSTEM_PROMPT = """\
You are a Playwright selector expert. A CSS selector failed to find an element on a web page.

Given:
- The broken selector
- A description of what the element should be
- A snippet of the page's HTML

Suggest 3 alternative selectors, ordered by reliability.

Rules:
1. Prefer selectors using: id > name > role/aria > text content > CSS class > tag structure
2. Each selector must be valid for Playwright's `page.click()` / `page.fill()` etc.
3. Consider that class names and IDs may have changed — use text content or structural selectors.

Return ONLY valid JSON:
```json
{
  "suggestions": [
    {"selector": "button:has-text('Login')", "confidence": 0.95, "strategy": "text-based"},
    {"selector": "[role='button'][name='login']", "confidence": 0.8, "strategy": "aria"},
    {"selector": "form >> button:first-of-type", "confidence": 0.6, "strategy": "structural"}
  ]
}
```
"""


class SelectorHealerAgent:
    """Suggest alternative selectors when the original one breaks."""

    def __init__(self, config: AntiQAConfig) -> None:
        self.config = config
        self.model = resolve_model(config.llm)

    def heal(
        self,
        broken_selector: str,
        description: str,
        page_html: str,
    ) -> list[dict[str, Any]]:
        """Return a list of alternative selector suggestions.

        Each suggestion is a dict with 'selector', 'confidence', 'strategy'.
        """
        html_snippet = page_html[:3000] if len(page_html) > 3000 else page_html

        user_prompt = (
            f"## Broken selector\n`{broken_selector}`\n\n"
            f"## Element description\n{description}\n\n"
            f"## Page HTML (snippet)\n```html\n{html_snippet}\n```"
        )

        from agno.utils.log import logger as agno_logger
        prev_handlers = agno_logger.handlers[:]
        prev_propagate = agno_logger.propagate
        agno_logger.handlers = [logging.NullHandler()]
        agno_logger.propagate = False
        try:
            agent = Agent(
                model=self.model,
                instructions=[HEAL_SYSTEM_PROMPT],
                markdown=False,
            )
            response = agent.run(user_prompt)
            content = _clean(response.content or "{}")
            data = json.loads(content)
            return data.get("suggestions", [])
        except Exception as exc:
            log.debug("Selector healing failed: %s", exc)
            return []
        finally:
            agno_logger.handlers = prev_handlers
            agno_logger.propagate = prev_propagate


def _clean(content: str) -> str:
    content = content.strip()
    if content.startswith("```"):
        first_newline = content.index("\n") if "\n" in content else 3
        content = content[first_newline + 1:]
    if content.endswith("```"):
        content = content[:-3]
    return content.strip()
