"""Threat intelligence signature cache for local matching."""

from __future__ import annotations

import logging
import re
import time
from dataclasses import dataclass, field
from typing import List, Optional

import httpx

logger = logging.getLogger("sentinely")

REFRESH_INTERVAL = 6 * 60 * 60  # 6 hours in seconds


@dataclass
class Signature:
    signature_hash: str
    pattern_type: str
    pattern_value: str
    attack_type: str
    severity: str
    risk_score_floor: int


@dataclass
class SignatureMatch:
    signature: Signature
    risk_score_floor: int


class SignatureCache:
    """Lazy signature cache that fetches from the Sentinely API.

    - Only fetches when an API key is configured
    - Refreshes every 6 hours
    - Never crashes the agent if the API is unreachable
    """

    def __init__(self, api_key: str, api_base_url: str = "https://api.sentinely.ai"):
        self._api_key = api_key
        self._api_base_url = api_base_url
        self._signatures: List[Signature] = []
        self._last_fetched: float = 0
        self._initialized: bool = False

    async def _fetch(self) -> None:
        """Fetch latest signatures from the API."""
        try:
            async with httpx.AsyncClient(timeout=3.0) as http:
                resp = await http.get(
                    f"{self._api_base_url}/api/v1/signatures/latest",
                    headers={"Authorization": f"Bearer {self._api_key}"},
                )
            if resp.status_code == 200:
                data = resp.json()
                self._signatures = [
                    Signature(
                        signature_hash=s.get("signature_hash", ""),
                        pattern_type=s.get("pattern_type", "keyword_set"),
                        pattern_value=s.get("pattern_value", ""),
                        attack_type=s.get("attack_type", "injection"),
                        severity=s.get("severity", "high"),
                        risk_score_floor=s.get("risk_score_floor", 70),
                    )
                    for s in data.get("signatures", [])
                ]
                self._last_fetched = time.time()
                self._initialized = True
        except Exception:
            logger.debug("signature_cache_fetch_failed", exc_info=True)

    async def refresh(self) -> None:
        """Re-fetch if stale (> 6 hours since last fetch)."""
        if time.time() - self._last_fetched > REFRESH_INTERVAL:
            await self._fetch()

    async def ensure_initialized(self) -> None:
        """Ensure the cache has been fetched at least once."""
        if not self._initialized:
            await self._fetch()

    async def check(self, text: str) -> List[SignatureMatch]:
        """Run all cached signatures against the text. Returns matches."""
        await self.ensure_initialized()
        await self.refresh()

        if not text or not self._signatures:
            return []

        text_lower = text.lower()
        matches: List[SignatureMatch] = []

        for sig in self._signatures:
            try:
                if sig.pattern_type == "regex":
                    if re.search(sig.pattern_value, text, re.IGNORECASE):
                        matches.append(SignatureMatch(signature=sig, risk_score_floor=sig.risk_score_floor))
                elif sig.pattern_type == "keyword_set":
                    keywords = [k.strip().lower() for k in sig.pattern_value.split(",")]
                    if keywords and all(k in text_lower for k in keywords):
                        matches.append(SignatureMatch(signature=sig, risk_score_floor=sig.risk_score_floor))
            except Exception:
                continue

        return matches
