"""Strands-powered adversarial citation verifier.

When ``strands-agents`` is installed, this module provides an LLM-based
adversarial verifier that uses the ``http_request`` tool to independently
look up and compare citation fields.  Falls back to the deterministic
verifier on any error.

Follows the lazy-import pattern from :mod:`alice_cli.agentcore_deps` —
``strands-agents`` is imported only when :class:`StrandsVerifier` is
instantiated.
"""

from __future__ import annotations

import json
import re
from typing import TYPE_CHECKING

import structlog

if TYPE_CHECKING:
    from alice_cli.cite.models import CitationRecord

logger = structlog.get_logger(__name__)


def is_strands_available() -> bool:
    """Check if ``strands-agents`` is importable.

    Returns ``False`` on :class:`ImportError`.
    """
    try:
        import strands  # noqa: F401

        return True
    except ImportError:
        return False


class StrandsVerifier:
    """Adversarial citation verifier using a Strands Agent with ``http_request`` tool.

    The agent receives an adversarial system prompt instructing it to
    independently verify citations by fetching data from academic APIs and
    comparing fields.  Returns the same ``(verification_status, confidence_score)``
    interface as the deterministic verifier.

    Follows the lazy-import pattern from ``agentcore_deps.py`` — ``strands-agents``
    is imported only when this class is instantiated.
    """

    ADVERSARIAL_SYSTEM_PROMPT: str = (
        "You are an adversarial citation verifier. Your job is to DISPROVE that a "
        "given citation is accurate. Use the http_request tool to independently look up "
        "the cited work from academic APIs (CrossRef, arXiv, PubMed, OpenLibrary, etc.). "
        "Compare the title, authors, year, and DOI. Report whether the citation is "
        "'verified' or 'unverified' and provide a confidence score between 0.0 and 1.0. "
        'Respond with a JSON object: {"verification_status": "verified" or "unverified", '
        '"confidence_score": <float between 0.0 and 1.0>}.'
    )

    def __init__(self, model_provider: str = "bedrock") -> None:
        """Create the Strands Agent with ``http_request`` tool.

        Parameters
        ----------
        model_provider:
            LLM provider for the Strands agent (default ``"bedrock"``).

        Raises
        ------
        ImportError
            If ``strands-agents`` is not installed.
        """
        from strands import Agent
        from strands.tools.http import http_request

        self._agent = Agent(
            system_prompt=self.ADVERSARIAL_SYSTEM_PROMPT,
            tools=[http_request],
            model=model_provider,
        )
        logger.debug("StrandsVerifier initialised", model_provider=model_provider)

    def verify(self, record: CitationRecord) -> tuple[str, float]:
        """Use LLM reasoning to verify the citation.

        Returns
        -------
        tuple[str, float]
            ``(verification_status, confidence_score)`` where status is
            ``"verified"`` or ``"unverified"`` and score is in ``[0.0, 1.0]``.

        Raises
        ------
        Exception
            On LLM/network errors — the caller (:class:`RedQueenVerifier`)
            catches and falls back to deterministic verification.
        """
        prompt = (
            f"Verify this citation:\n"
            f"  Title: {record.title}\n"
            f"  Authors: {', '.join(record.authors)}\n"
            f"  Year: {record.year}\n"
            f"  DOI: {record.doi}\n"
            f"  Journal: {record.journal}\n"
            f"  Volume: {record.volume}\n"
            f"  Pages: {record.pages}\n"
            f"\nIndependently look up this work and compare the fields. "
            f"Return ONLY a JSON object with verification_status and confidence_score."
        )

        result = self._agent(prompt)
        response_text = str(result)

        return self._parse_response(response_text)

    @staticmethod
    def _parse_response(response_text: str) -> tuple[str, float]:
        """Parse the agent's JSON response into a (status, confidence) tuple.

        Falls back to ``("unverified", 0.0)`` if parsing fails, but raises
        on empty or completely unparseable responses so the caller can
        fall back to deterministic verification.
        """
        # Try to extract JSON from the response
        json_match = re.search(r"\{[^}]+\}", response_text)
        if json_match is None:
            raise ValueError(f"No JSON found in Strands response: {response_text!r}")

        data = json.loads(json_match.group())

        status = data.get("verification_status", "unverified")
        if status not in ("verified", "unverified"):
            status = "unverified"

        confidence = float(data.get("confidence_score", 0.0))
        confidence = max(0.0, min(1.0, confidence))

        return status, confidence
