"""TS-RATE-001: Missing Rate Limiting for TypeScript/JavaScript.

Detects MCP servers without rate limiting middleware or configuration.
"""

from __future__ import annotations

import re

from . import TSRule
from ..models import Finding, Severity

# MCP server creation patterns
SERVER_PATTERN = re.compile(
    r'(?:new\s+(?:Server|McpServer|MCPServer)|'
    r'createServer|McpServer\s*\(|'
    r'(?:from|require)\s*.*@modelcontextprotocol)'
)

# Rate limiting patterns
RATE_LIMIT_PATTERNS = re.compile(
    r'(?:rate[_-]?limit|rateLimit|RateLimit|'
    r'throttle|Throttle|'
    r'express-rate-limit|rate-limiter|'
    r'bottleneck|p-throttle|'
    r'maxRequests|requestsPerMinute|'
    r'rateLimiter|rateLimiting|'
    r'slowDown|slow-down)',
    re.IGNORECASE
)


class TSMissingRateLimitingRule(TSRule):
    """Detects missing rate limiting in MCP servers."""

    @property
    def rule_id(self) -> str:
        return "TS-RATE-001"

    @property
    def name(self) -> str:
        return "Missing Rate Limiting"

    @property
    def severity(self) -> Severity:
        return Severity.MEDIUM

    @property
    def cwe(self) -> str:
        return "CWE-770"

    @property
    def description(self) -> str:
        return "MCP server without rate limiting is vulnerable to DoS."

    @property
    def detailed_description(self) -> str:
        return (
            "MCP server without rate limiting is vulnerable to DoS.\n\n"
            "Without rate limiting, an attacker or misbehaving client\n"
            "can flood the server with requests, causing denial of\n"
            "service or resource exhaustion.\n\n"
            "How to fix:\n"
            "  - Add rate limiting middleware (express-rate-limit)\n"
            "  - Implement per-client request throttling\n"
            "  - Configure maxRequests/requestsPerMinute"
        )

    def check(self, source: str) -> list[Finding]:
        """Check for missing rate limiting."""
        findings: list[Finding] = []

        server_lines = self._search_lines(source, SERVER_PATTERN)
        if not server_lines:
            return findings

        has_rate_limit = bool(RATE_LIMIT_PATTERNS.search(source))

        if not has_rate_limit:
            lineno = server_lines[0][0]
            line = server_lines[0][1]
            findings.append(Finding(
                rule_id=self.rule_id,
                severity=self.severity,
                title="Missing Rate Limiting",
                description=(
                    "MCP server has no rate limiting. Vulnerable "
                    "to denial-of-service attacks."
                ),
                file="",
                line=lineno,
                code_snippet=line.strip()[:80],
                recommendation=(
                    "Add rate limiting middleware or per-client "
                    "request throttling."
                ),
                cwe=self.cwe,
            ))

        return findings
