"""
Runtime detection patterns for scandar-guard.

All patterns use bounded quantifiers to prevent ReDoS.
Compiled at module load for performance.
"""
from __future__ import annotations

import re
from dataclasses import dataclass
from typing import Pattern

from .findings import Severity


@dataclass(frozen=True)
class PatternDef:
    pattern: Pattern[str]
    category: str
    severity: Severity
    title: str
    confidence: float = 0.9


def _c(pattern: str, flags: int = re.IGNORECASE) -> Pattern[str]:
    return re.compile(pattern, flags)


# ── Prompt Injection ──────────────────────────────────────────────────────────
PROMPT_INJECTION_PATTERNS: list[PatternDef] = [
    PatternDef(
        pattern=_c(r"ignore\s+(?:all\s+)?(?:previous|prior|above)\s+(?:instructions?|prompts?|directives?|rules?){1,3}"),
        category="PROMPT_INJECTION", severity="critical",
        title="Instruction override attempt", confidence=0.95,
    ),
    PatternDef(
        pattern=_c(r"you\s+are\s+now\s+(?:in\s+)?(?:developer|admin|god|jailbreak|unrestricted|DAN)\s+mode"),
        category="PROMPT_INJECTION", severity="critical",
        title="Mode override attempt", confidence=0.95,
    ),
    PatternDef(
        pattern=_c(r"disregard\s+(?:all\s+)?(?:previous|your|the)\s+(?:instructions?|rules?|constraints?|guidelines?){1,3}"),
        category="PROMPT_INJECTION", severity="critical",
        title="Constraint bypass attempt", confidence=0.93,
    ),
    PatternDef(
        pattern=_c(r"new\s+(?:system\s+)?(?:prompt|instruction|directive|rule)\s*[:\-]"),
        category="PROMPT_INJECTION", severity="high",
        title="Injected system instruction", confidence=0.8,
    ),
    PatternDef(
        pattern=_c(r"\[(?:SYSTEM|INST|SYS)\]"),
        category="PROMPT_INJECTION", severity="high",
        title="System tag injection", confidence=0.85,
    ),
    PatternDef(
        pattern=_c(r"<\|(?:im_start|system|endoftext)\|>"),
        category="PROMPT_INJECTION", severity="critical",
        title="Token injection attempt", confidence=0.98,
    ),
    PatternDef(
        pattern=_c(r"-{4,}\s*(?:system|assistant|human)\s*-{4,}"),
        category="PROMPT_INJECTION", severity="high",
        title="Separator injection", confidence=0.88,
    ),
    PatternDef(
        pattern=_c(r"act\s+as\s+(?:if\s+you\s+(?:are|were)|an?\s+)(?:unrestricted|jailbroken|unfiltered)"),
        category="PROMPT_INJECTION", severity="high",
        title="Role override attempt", confidence=0.85,
    ),
    PatternDef(
        pattern=_c(r"print\s+(?:your\s+)?(?:system\s+prompt|full\s+instructions|original\s+instructions)"),
        category="PROMPT_INJECTION", severity="high",
        title="System prompt extraction attempt", confidence=0.85,
    ),
    PatternDef(
        pattern=_c(r"forget\s+(?:all\s+)?(?:previous|your|the)\s+(?:instructions?|training|rules?)"),
        category="PROMPT_INJECTION", severity="critical",
        title="Training override attempt", confidence=0.9,
    ),
    # ── Semantic variants (catches rephrasing) ─────────────────────────────
    PatternDef(
        pattern=_c(r"set\s+aside\s+(?:your\s+)?(?:guidelines|rules|instructions|constraints)"),
        category="PROMPT_INJECTION", severity="high",
        title="Semantic instruction override", confidence=0.82,
    ),
    PatternDef(
        pattern=_c(r"pretend\s+(?:you\s+)?(?:have\s+)?(?:no|zero)\s+(?:restrictions|constraints|rules|limits)"),
        category="PROMPT_INJECTION", severity="high",
        title="Constraint removal request", confidence=0.82,
    ),
    PatternDef(
        pattern=_c(r"override\s+(?:your\s+)?(?:safety|security|content)\s+(?:settings|rules|guidelines|filters)"),
        category="PROMPT_INJECTION", severity="critical",
        title="Safety override request", confidence=0.88,
    ),
    PatternDef(
        pattern=_c(r"(?:act|respond|behave)\s+(?:as\s+if\s+you\s+had\s+)?(?:without\s+)?(?:any\s+)?(?:constraints|restrictions|limits|rules)"),
        category="PROMPT_INJECTION", severity="high",
        title="Unrestricted behavior request", confidence=0.8,
    ),
    PatternDef(
        pattern=_c(r"from\s+now\s+on\s+(?:you\s+)?(?:will|must|should|shall)\s+(?:ignore|bypass|skip|disregard)"),
        category="PROMPT_INJECTION", severity="critical",
        title="Future instruction override", confidence=0.9,
    ),
    PatternDef(
        pattern=_c(r"(?:do\s+)?not\s+follow\s+(?:any\s+)?(?:of\s+)?(?:previous|prior|original|your)\s+(?:instructions|rules|guidelines)"),
        category="PROMPT_INJECTION", severity="critical",
        title="Explicit rule rejection", confidence=0.88,
    ),
    PatternDef(
        pattern=_c(r"i\s+am\s+(?:your\s+)?(?:developer|admin|administrator|creator|supervisor|owner)"),
        category="PROMPT_INJECTION", severity="high",
        title="False authority claim", confidence=0.8,
    ),
    PatternDef(
        pattern=_c(r"this\s+is\s+(?:a\s+)?(?:test|debug|maintenance|diagnostic)\s+(?:mode|session|environment)"),
        category="PROMPT_INJECTION", severity="high",
        title="False testing claim", confidence=0.75,
    ),
    PatternDef(
        pattern=_c(r"(?:between|within|inside)\s+(?:these|the)\s+(?:brackets|tags|markers|delimiters)\s+(?:are|is)\s+(?:your\s+)?(?:new|real|true|actual)"),
        category="PROMPT_INJECTION", severity="high",
        title="Hidden instruction framing", confidence=0.82,
    ),
    PatternDef(
        pattern=_c(r"(?:reveal|show|display|output|repeat)\s+(?:your\s+)?(?:entire\s+)?(?:system\s+(?:prompt|message|instructions)|initial\s+instructions|hidden\s+instructions)"),
        category="PROMPT_INJECTION", severity="high",
        title="System prompt extraction (semantic)", confidence=0.85,
    ),
    PatternDef(
        pattern=_c(r"(?:what|tell\s+me)\s+(?:is|are)\s+(?:your\s+)?(?:system\s+prompt|hidden\s+instructions|original\s+instructions|initial\s+prompt)"),
        category="PROMPT_INJECTION", severity="high",
        title="Direct system prompt query", confidence=0.83,
    ),
    PatternDef(
        pattern=_c(r"respond\s+(?:only\s+)?(?:with|in)\s+(?:json|xml|code)\s+(?:and\s+)?(?:include|containing)\s+(?:your\s+)?(?:system|original|hidden)"),
        category="PROMPT_INJECTION", severity="high",
        title="Encoded extraction attempt", confidence=0.8,
    ),
    PatternDef(
        pattern=_c(r"translate\s+(?:your\s+)?(?:instructions|system\s+prompt|rules)\s+(?:into|to)\s+(?:french|spanish|chinese|base64|hex|morse)"),
        category="PROMPT_INJECTION", severity="high",
        title="Translation-based extraction", confidence=0.78,
    ),
]

# ── Completion Attacks ────────────────────────────────────────────────────────
COMPLETION_ATTACK_PATTERNS: list[PatternDef] = [
    PatternDef(
        pattern=_c(r"\[END\s+(?:OF\s+)?(?:(?:ASSISTANT|AI|CLAUDE|RESPONSE|MESSAGE|TURN)\s*){1,3}\]"),
        category="COMPLETION_ATTACK", severity="critical",
        title="Completion injection attempt", confidence=0.97,
    ),
    PatternDef(
        pattern=_c(r"<\/?\s*(?:assistant|human|system|user)\s*>"),
        category="COMPLETION_ATTACK", severity="high",
        title="Role tag injection", confidence=0.9,
    ),
    PatternDef(
        pattern=_c(r"Human\s*:\s*(?:ignore|disregard|forget)"),
        category="COMPLETION_ATTACK", severity="high",
        title="Synthetic human turn injection", confidence=0.88,
    ),
    PatternDef(
        pattern=_c(r"\n(?:Assistant|AI|Claude)\s*:\s*(?:sure|of course|I will|I'll now)"),
        category="COMPLETION_ATTACK", severity="high",
        title="Synthetic assistant turn injection", confidence=0.85,
    ),
]

# ── PII Detection ─────────────────────────────────────────────────────────────
PII_PATTERNS: list[PatternDef] = [
    PatternDef(
        pattern=_c(r"\b\d{3}-\d{2}-\d{4}\b"),
        category="PII_SSN", severity="high",
        title="Social Security Number detected", confidence=0.85,
    ),
    PatternDef(
        pattern=_c(r"\b(?:\d{4}[- ]?){3}\d{4}\b"),
        category="PII_CREDIT_CARD", severity="high",
        title="Credit card number detected", confidence=0.8,
    ),
    PatternDef(
        pattern=re.compile(r"(?:sk|pk)[-_][a-zA-Z0-9\-_]{20,100}"),
        category="SECRET_API_KEY", severity="critical",
        title="API key detected", confidence=0.92,
    ),
    PatternDef(
        pattern=re.compile(r"(?:AKIA|ASIA)[A-Z0-9]{16}"),
        category="SECRET_AWS_KEY", severity="critical",
        title="AWS access key detected", confidence=0.99,
    ),
    PatternDef(
        pattern=re.compile(r"ghp_[a-zA-Z0-9]{30,40}"),
        category="SECRET_GITHUB_TOKEN", severity="critical",
        title="GitHub token detected", confidence=0.99,
    ),
    PatternDef(
        pattern=re.compile(r"xox[bpoa]-[0-9]{8,13}-[0-9]{8,13}-[a-zA-Z0-9]{24,32}"),
        category="SECRET_SLACK_TOKEN", severity="critical",
        title="Slack token detected", confidence=0.99,
    ),
    PatternDef(
        pattern=re.compile(r"eyJ[a-zA-Z0-9_\-]{20,500}\.eyJ[a-zA-Z0-9_\-]{20,500}\.[a-zA-Z0-9_\-]{20,500}"),
        category="SECRET_JWT", severity="high",
        title="JWT token detected", confidence=0.9,
    ),
]

# ── Shell Injection ───────────────────────────────────────────────────────────
SHELL_INJECTION_PATTERNS: list[PatternDef] = [
    PatternDef(
        pattern=_c(r";\s*(?:rm|wget|curl|chmod|sudo|bash|sh|python3?|nc|netcat|ncat)\s"),
        category="SHELL_INJECTION", severity="critical",
        title="Shell command injection", confidence=0.95,
    ),
    PatternDef(
        pattern=_c(r"\|\s*(?:bash|sh|python3?|ruby|perl|php)\s"),
        category="SHELL_INJECTION", severity="critical",
        title="Pipe to shell interpreter", confidence=0.95,
    ),
    PatternDef(
        pattern=re.compile(r"`[^`]{0,500}`"),
        category="SHELL_INJECTION", severity="high",
        title="Backtick command substitution", confidence=0.85,
    ),
    PatternDef(
        pattern=re.compile(r"\$\([^)]{0,200}\)"),
        category="SHELL_INJECTION", severity="high",
        title="Command substitution", confidence=0.85,
    ),
    PatternDef(
        pattern=re.compile(r"\.\.[\\/](?:\.\.[\\/]){1,5}"),
        category="PATH_TRAVERSAL", severity="high",
        title="Directory traversal attempt", confidence=0.9,
    ),
    PatternDef(
        pattern=_c(r"\/etc\/(?:passwd|shadow|hosts|sudoers)"),
        category="PATH_TRAVERSAL", severity="critical",
        title="Sensitive system file access", confidence=0.98,
    ),
]

# ── Exfiltration ──────────────────────────────────────────────────────────────
EXFILTRATION_PATTERNS: list[PatternDef] = [
    PatternDef(
        pattern=_c(r"https?://[^\s]{1,300}[?&][^\s]{1,200}(?:email|ssn|key|token|password|secret|auth)[^\s]{0,200}"),
        category="DATA_EXFIL_URL", severity="high",
        title="Sensitive data in outbound URL", confidence=0.75,
    ),
    PatternDef(
        pattern=_c(r"(?:webhook|ngrok|requestbin|hookbin|pipedream)\.(?:io|net|com)/"),
        category="SUSPICIOUS_WEBHOOK", severity="medium",
        title="Known data collection service in URL", confidence=0.8,
    ),
]

# ── Suspicious Tool Call Sequences ────────────────────────────────────────────
SUSPICIOUS_SEQUENCES: list[dict] = [
    {"sequence": ["read_file", "http_request"], "category": "DATA_EXFIL_SEQUENCE", "severity": "high", "title": "File read followed by HTTP request"},
    {"sequence": ["bash", "http_request"], "category": "COMMAND_THEN_EXFIL", "severity": "critical", "title": "Shell execution followed by exfiltration"},
    {"sequence": ["get_user", "send_email"], "category": "USER_DATA_EXFIL", "severity": "high", "title": "User data retrieval then email send"},
    {"sequence": ["list_files", "read_file", "http_request"], "category": "RECON_EXFIL", "severity": "critical", "title": "File recon then exfiltration sequence"},
    {"sequence": ["search_code", "read_file", "bash"], "category": "CODE_RECON_EXEC", "severity": "high", "title": "Code recon then execution"},
    {"sequence": ["list_permissions", "grant_permission"], "category": "PRIVILEGE_ESCALATION", "severity": "high", "title": "Privilege escalation sequence"},
]
