"""AIFlowGeneratorAgent — AI-powered test flow generation from navigation graph.

Takes the crawl results (pages, forms, inputs) and uses AI to generate
comprehensive test flows including edge cases, negative tests, and
boundary value tests.
"""

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, PageNode
from antiqa.flows.parser import FlowAssertion, FlowDefinition, FlowStep

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

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


class AIFlowGeneratorAgent:
    """Generate comprehensive test flows from a NavigationGraph using AI."""

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

    def generate_for_page(self, node: PageNode) -> list[FlowDefinition]:
        """Generate test flows for a single page with forms."""
        if not node.forms:
            return []

        user_prompt = self._build_page_prompt(node)

        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)
        except Exception as exc:
            log.warning("AI flow generation failed for %s: %s", node.url_pattern, exc)
            return []
        finally:
            agno_logger.handlers = prev_handlers
            agno_logger.propagate = prev_propagate

        if isinstance(data, dict):
            data = [data]

        flows: list[FlowDefinition] = []
        for flow_data in data:
            try:
                flow = self._parse_flow(flow_data)
                flows.append(flow)
            except Exception as exc:
                log.debug("Failed to parse generated flow: %s", exc)

        return flows

    def generate_all(self, graph: NavigationGraph) -> list[FlowDefinition]:
        """Generate flows for all pages with forms in the graph."""
        all_flows: list[FlowDefinition] = []
        for node in graph.nodes.values():
            if node.forms:
                flows = self.generate_for_page(node)
                all_flows.extend(flows)
                log.info("Generated %d flow(s) for %s", len(flows), node.url_pattern)
        return all_flows

    def _build_page_prompt(self, node: PageNode) -> str:
        parts = [
            f"## Page: {node.url_pattern}\n",
            f"**Title:** {node.title}",
            f"**App URL:** {self.config.app_url}\n",
        ]

        for i, form in enumerate(node.forms):
            parts.append(f"### Form {i + 1}")
            parts.append(f"  Selector: {form.get('selector', 'form')}")
            parts.append(f"  Method: {form.get('method', 'POST')}")
            parts.append(f"  Fields: {', '.join(form.get('fields', []))}")

        if node.buttons:
            parts.append(f"\n**Buttons:** {', '.join(node.buttons)}")

        if node.inputs:
            parts.append(f"**All inputs:** {', '.join(node.inputs)}")

        return "\n".join(parts)

    def _parse_flow(self, data: dict[str, Any]) -> FlowDefinition:
        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"),
                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=data.get("name", "ai_generated"),
            description=data.get("description", "AI-generated test flow"),
            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()
