"""TS-AUTH-001: Missing Authentication for TypeScript/JavaScript.

Detects MCP servers without authentication checks in server setup.
"""

from __future__ import annotations

import re

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

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

# Authentication patterns
AUTH_PATTERNS = re.compile(
    r'(?:authenticate|authorization|auth[_-]?token|'
    r'verify[_-]?token|jwt\.verify|passport\.|'
    r'bearer|api[_-]?key|isAuthenticated|'
    r'requireAuth|checkAuth|authMiddleware|'
    r'auth\s*\(|\.auth\s*\(|'
    r'Authorization|x-api-key|'
    r'authenticate\s*[:=]|'
    r'session\.|cookie\.|'
    r'oauth|openid|oidc)',
    re.IGNORECASE
)


class TSMissingAuthRule(TSRule):
    """Detects MCP servers without authentication."""

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

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

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

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

    @property
    def description(self) -> str:
        return "MCP server created without authentication checks."

    @property
    def detailed_description(self) -> str:
        return (
            "MCP server created without authentication checks.\n\n"
            "MCP servers expose tool capabilities to LLM clients.\n"
            "Without authentication, any client can connect and invoke\n"
            "tools, potentially accessing sensitive resources.\n\n"
            "Examples of vulnerable code:\n"
            "  const server = new Server({ name: 'myserver' });\n"
            "  // No auth middleware or token verification\n\n"
            "How to fix:\n"
            "  - Add authentication middleware\n"
            "  - Verify Bearer tokens or API keys\n"
            "  - Use the MCP SDK's auth capabilities\n"
            "  - Implement OAuth2/OIDC for production"
        )

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

        # Only check files that create MCP servers
        server_lines = self._search_lines(source, SERVER_CREATION)
        if not server_lines:
            return findings

        # Check if auth patterns exist anywhere in the source
        has_auth = bool(AUTH_PATTERNS.search(source))

        if not has_auth:
            lineno = server_lines[0][0]
            line = server_lines[0][1]
            findings.append(Finding(
                rule_id=self.rule_id,
                severity=self.severity,
                title="Missing Authentication",
                description=(
                    "MCP server setup without authentication. "
                    "Any client can connect and invoke tools."
                ),
                file="",
                line=lineno,
                code_snippet=line.strip()[:80],
                recommendation=(
                    "Add authentication middleware or token "
                    "verification before processing requests."
                ),
                cwe=self.cwe,
            ))

        return findings
