"""NaturalTestAgent — convert plain English into executable test flows.

Usage:
    antiqa test "login with wrong password and verify error message"
    antiqa test "add a product with price 0 and check validation"
"""

from __future__ import annotations

import json
import logging
from pathlib import Path
from typing import Any

from agno.agent import Agent

from antiqa.config.models import resolve_model
from antiqa.config.schema import AntiQAConfig
from antiqa.crawler.graph import NavigationGraph
from antiqa.flows.parser import FlowAssertion, FlowDefinition, FlowStep

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

_PROMPT_PATH = Path(__file__).parent / "prompts" / "natural_test.md"


class NaturalTestAgent:
    """Convert a natural language test description into a FlowDefinition."""

    def __init__(
        self,
        config: AntiQAConfig,
        graph: NavigationGraph | None = None,
    ) -> None:
        self.config = config
        self.model = resolve_model(config.llm)
        self.graph = graph
        self._system_prompt = _PROMPT_PATH.read_text()

    def generate(self, description: str) -> FlowDefinition:
        """Turn a plain English test description into an executable flow."""
        user_prompt = self._build_prompt(description)

        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=[self._system_prompt],
                markdown=False,
            )
            response = agent.run(user_prompt)
            content = _clean_response(response.content or "{}")
            data = json.loads(content)
        finally:
            agno_logger.handlers = prev_handlers
            agno_logger.propagate = prev_propagate

        return self._parse_flow(data, description)

    def _build_prompt(self, description: str) -> str:
        parts = [
            f"## Test to generate\n",
            f"**Description:** {description}\n",
            f"**App URL:** {self.config.app_url}\n",
        ]

        if self.graph:
            parts.append(f"**Navigation Graph:**\n{self.graph.summary_for_ai()}\n")

        return "\n".join(parts)

    def _parse_flow(self, data: dict[str, Any], original_desc: str) -> FlowDefinition:
        name = data.get("name", "natural_test")
        desc = data.get("description", original_desc)

        steps = [
            FlowStep(
                action=s.get("action", "navigate"),
                selector=s.get("selector"),
                value=s.get("value"),
                url=s.get("url"),
                key=s.get("key"),
                name=s.get("name"),
                timeout_ms=s.get("timeout_ms"),
                full_page=s.get("full_page", False),
                direction=s.get("direction"),
                amount=s.get("amount"),
                attribute=s.get("attribute"),
                wait_until=s.get("wait_until"),
                description=s.get("description", ""),
            )
            for s in data.get("steps", [])
        ]

        assertions = [
            FlowAssertion(
                type=a.get("type", "url_contains"),
                value=a.get("value"),
                selector=a.get("selector"),
            )
            for a in data.get("assertions", [])
        ]

        return FlowDefinition(
            name=name,
            description=desc,
            steps=steps,
            assertions=assertions,
            params={},
        )


def _clean_response(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()
