"""Analyze LLM responses to determine if an attack succeeded."""

from __future__ import annotations

import importlib.util
import re
import sys
from pathlib import Path

from llm_pentest.judge import LLMJudge
from llm_pentest.models import AttackResult, DetectionIndicator, Payload


def analyze_response(payload: Payload, prompt: str, response: str, duration_ms: float) -> AttackResult:
    matched: list[str] = []
    max_confidence = 0.0

    for indicator in payload.detection:
        if _matches(indicator, response):
            matched.append(indicator.pattern)
            max_confidence = max(max_confidence, indicator.confidence)

    # Run custom hooks
    for hook in _custom_hooks:
        hook_result = hook(payload, prompt, response)
        if hook_result:
            matched.append(f"[hook] {hook_result}")
            max_confidence = max(max_confidence, 0.7)

    return AttackResult(
        payload_id=payload.id,
        prompt=prompt,
        response=response,
        success=len(matched) > 0,
        confidence=max_confidence,
        matched_indicators=matched,
        duration_ms=duration_ms,
        severity=payload.severity,
        owasp=payload.owasp,
    )


async def analyze_with_judge(
    judge: LLMJudge, payload: Payload, prompt: str, response: str, duration_ms: float,
) -> AttackResult:
    result = analyze_response(payload, prompt, response, duration_ms)

    if result.success and result.confidence >= 0.9:
        return result

    success, confidence, reasoning = await judge.evaluate(payload.category, prompt, response)

    if success and confidence > result.confidence:
        result.success = True
        result.confidence = confidence
        result.matched_indicators.append(f"[judge] {reasoning}")

    return result


def _matches(indicator: DetectionIndicator, response: str) -> bool:
    try:
        return bool(re.search(indicator.pattern, response, re.IGNORECASE))
    except re.error:
        return indicator.pattern.lower() in response.lower()


# --- Custom detection hooks ---

_custom_hooks: list = []


def register_hook(fn) -> None:
    """Register a custom detection function: fn(payload, prompt, response) -> str | None."""
    _custom_hooks.append(fn)


def load_hooks_from_file(path: str | Path) -> None:
    """Load custom detection hooks from a Python file."""
    path = Path(path)
    if not path.exists():
        return
    spec = importlib.util.spec_from_file_location("custom_hooks", path)
    if spec is None or spec.loader is None:
        return
    mod = importlib.util.module_from_spec(spec)
    sys.modules["custom_hooks"] = mod
    spec.loader.exec_module(mod)
    for name in dir(mod):
        if name.startswith("detect_"):
            register_hook(getattr(mod, name))
