"""Automatic vulnerability detection functionality."""

import logging
import re
from typing import Any

from wish_models.finding import Finding
from wish_models.host import Host, Service

logger = logging.getLogger(__name__)


class VulnerabilityDetector:
    """Automatic vulnerability detection class."""

    def __init__(self) -> None:
        self.vulnerability_patterns = {
            "samba_usermap_script": {
                "pattern": r"Samba\s+3\.0\.20",
                "service_names": ["netbios-ssn", "microsoft-ds"],
                "ports": [139, 445],
                "cve": "CVE-2007-2447",
                "title": "Samba 3.0.20 - Remote Command Execution",
                "description": (
                    "Samba versions 3.0.20 through 3.0.25rc3 contain a vulnerability "
                    "that allows remote code execution through the usermap script functionality."
                ),
                "severity": "critical",
                "category": "vulnerability",
            },
            "vsftpd_backdoor": {
                "pattern": r"vsftpd\s+2\.3\.4",
                "service_names": ["ftp"],
                "ports": [21],
                "cve": "CVE-2011-2523",
                "title": "vsftpd 2.3.4 - Backdoor Command Execution",
                "description": "vsftpd version 2.3.4 contains a backdoor which opens a shell on port 6200/tcp.",
                "severity": "critical",
                "category": "vulnerability",
            },
            "apache_mod_ssl": {
                "pattern": r"Apache.*mod_ssl/2\.8\.[0-7]",
                "service_names": ["https", "ssl/http"],
                "ports": [443],
                "cve": "CVE-2002-0082",
                "title": "Apache mod_ssl < 2.8.8 - Remote Buffer Overflow",
                "description": "Apache mod_ssl versions prior to 2.8.8 contain a buffer overflow vulnerability.",
                "severity": "high",
                "category": "vulnerability",
            },
        }

    def detect_vulnerabilities(self, host: Host) -> list[Finding]:
        """Detect vulnerabilities for host."""
        findings = []

        for service in host.services:
            service_findings = self._detect_service_vulnerabilities(service, host)
            findings.extend(service_findings)

        return findings

    def _detect_service_vulnerabilities(self, service: Service, host: Host) -> list[Finding]:
        """Detect vulnerabilities for service."""
        findings = []

        # Build service information
        service_info = self._build_service_info(service)

        # Check each vulnerability pattern
        for _vuln_id, vuln_data in self.vulnerability_patterns.items():
            if self._matches_vulnerability(service, service_info, vuln_data):
                finding = self._create_finding(vuln_data, service, host)
                findings.append(finding)
                logger.info(f"Detected vulnerability: {vuln_data['cve']} on {host.ip_address}:{service.port}")

        return findings

    def _build_service_info(self, service: Service) -> str:
        """Build service information as string."""
        info_parts = []

        if service.product:
            info_parts.append(service.product)
        if service.version:
            info_parts.append(service.version)
        if service.extrainfo:
            info_parts.append(service.extrainfo)
        if service.banner:
            info_parts.append(service.banner)

        return " ".join(info_parts)

    def _matches_vulnerability(self, service: Service, service_info: str, vuln_data: dict[str, Any]) -> bool:
        """Check if vulnerability pattern matches."""
        # Port check
        if service.port not in vuln_data["ports"]:
            return False

        # Service name check
        if service.service_name and service.service_name not in vuln_data["service_names"]:
            return False

        # Pattern matching
        if not re.search(vuln_data["pattern"], service_info, re.IGNORECASE):
            return False

        return True

    def _create_finding(self, vuln_data: dict[str, Any], service: Service, host: Host) -> Finding:
        """Create vulnerability finding."""
        evidence = f"Service: {service.service_name or 'unknown'} on {host.ip_address}:{service.port}"
        if service.product:
            evidence += f"\nProduct: {service.product}"
        if service.version:
            evidence += f"\nVersion: {service.version}"
        if service.banner:
            evidence += f"\nBanner: {service.banner}"

        return Finding(
            title=vuln_data["title"],
            description=vuln_data["description"],
            category=vuln_data["category"],
            severity=vuln_data["severity"],
            target_type="service",
            discovered_by="vulnerability_detector",
            evidence=evidence,
            cve_ids=[vuln_data["cve"]],
            host_id=host.id,
            service_id=service.id,
            url=None,
            status="new",
            recommendation=f"Apply security patches for {vuln_data['cve']}",
        )

    def get_exploit_suggestions(self, cve_id: str) -> list[str]:
        """Get exploit suggestions for CVE."""
        exploit_suggestions = {
            "CVE-2007-2447": [
                "Use Metasploit module: exploit/multi/samba/usermap_script",
                "Manual exploitation: Send malicious username containing command injection",
                "Test with: smbclient //target/tmp -U '/=`id`'",
            ],
            "CVE-2011-2523": [
                "Connect to FTP and send USER with smile face trigger",
                "Check if backdoor opens on port 6200/tcp",
                "Use Metasploit module: exploit/unix/ftp/vsftpd_234_backdoor",
            ],
            "CVE-2002-0082": [
                "Use OpenSSL exploit for Apache mod_ssl",
                "Test with custom exploit targeting the buffer overflow",
                "Use Metasploit module: exploit/unix/http/apache_mod_ssl_off_by_one",
            ],
        }

        return exploit_suggestions.get(cve_id, ["No specific exploit suggestions available"])
