"""AccessibilityAuditorAgent — AI-powered WCAG accessibility auditing.

Crawls pages and uses AI to identify accessibility violations, mapping
them to WCAG 2.1 criteria with concrete fix suggestions.
"""

from __future__ import annotations

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

from agno.agent import Agent
from pydantic import BaseModel, Field

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

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

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


class A11yIssue(BaseModel):
    severity: str = "warning"
    wcag_criterion: str = ""
    description: str = ""
    element: str = ""
    fix: str = ""


class A11yAuditResult(BaseModel):
    page_url: str = ""
    score: str = "unknown"
    issues: list[A11yIssue] = Field(default_factory=list)
    summary: str = ""
    passed_checks: list[str] = Field(default_factory=list)


class AccessibilityAuditorAgent:
    """Audit web pages for WCAG 2.1 accessibility compliance."""

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

    def audit_html(self, html: str, page_url: str = "") -> A11yAuditResult:
        """Audit raw HTML content for accessibility issues."""
        html_snippet = html[:6000] if len(html) > 6000 else html

        user_prompt = (
            f"## Page to audit\n"
            f"**URL:** {page_url}\n\n"
            f"```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=[self._system_prompt],
                markdown=False,
            )
            response = agent.run(user_prompt)
            content = _clean(response.content or "{}")
            data = json.loads(content)
        except Exception as exc:
            log.warning("Accessibility audit failed for %s: %s", page_url, exc)
            return A11yAuditResult(page_url=page_url, summary=f"Audit failed: {exc}")
        finally:
            agno_logger.handlers = prev_handlers
            agno_logger.propagate = prev_propagate

        issues = [
            A11yIssue(
                severity=i.get("severity", "warning"),
                wcag_criterion=i.get("wcag_criterion", ""),
                description=i.get("description", ""),
                element=i.get("element", ""),
                fix=i.get("fix", ""),
            )
            for i in data.get("issues", [])
        ]

        return A11yAuditResult(
            page_url=page_url,
            score=data.get("score", "unknown"),
            issues=issues,
            summary=data.get("summary", ""),
            passed_checks=data.get("passed_checks", []),
        )

    def audit_page(self, page, page_url: str = "") -> A11yAuditResult:
        """Audit a live Playwright page."""
        html = page.content()
        url = page_url or page.url
        return self.audit_html(html, url)

    def audit_many(
        self,
        pages_html: list[tuple[str, str]],
    ) -> list[A11yAuditResult]:
        """Audit multiple pages. Each tuple is (html, page_url)."""
        results: list[A11yAuditResult] = []
        for html, url in pages_html:
            result = self.audit_html(html, url)
            results.append(result)
            log.info("A11y audit %s: score=%s, %d issues", url, result.score, len(result.issues))
        return results


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