"""Derive cyber findings from a machine's networked components (hardware path).

For a hardware CE project there is no source repo to scan. Instead, each
*networked* component (PLC, HMI, gateway, drive, remote access) carries typical
ICS vulnerability CLASSES — well-established categories repeatedly flagged in
CISA ICS advisories. We emit one finding per class so they flow through the same
CRA engine.

Honesty: these are vulnerability CLASSES (with a real CWE), framed as
"product-specific check against CISA ICS advisories" — NOT fabricated CVE numbers.
The concrete CVEs per vendor/product are a later live CISA-ICS / NVD enrichment.
"""

# component_class -> typical ICS vulnerability classes (suffix, title, cwe, severity, category)
_CLASS_VULN_TEMPLATES = {
    "controller": [  # PLC / safety controller / motion controller
        ("ctrl-noauth", "Steuerungsprotokoll ohne Authentifizierung erreichbar", "CWE-306", "high", "auth"),
        ("ctrl-fw", "Firmware-/Programm-Update ohne Signaturpruefung", "CWE-494", "high", "updates"),
        ("ctrl-debug", "Offener Programmier-/Debug-Port", "CWE-1188", "medium", "config"),
    ],
    "hmi": [  # operator panel / SCADA HMI
        ("hmi-default", "Default-/Werks-Zugangsdaten", "CWE-1392", "critical", "auth"),
        ("hmi-cleartext", "Unverschluesselte Web-/Bedienoberflaeche", "CWE-319", "high", "crypto"),
    ],
    "gateway": [  # IoT / fieldbus / telemetry gateway
        ("gw-telemetry", "Unverschluesselte Telemetrie / Feldbus", "CWE-319", "high", "crypto"),
        ("gw-bruteforce", "Kein Brute-Force-/Rate-Limit-Schutz am Zugang", "CWE-307", "medium", "auth"),
    ],
    "drive": [  # VFD / servo drive
        ("drv-param", "Antriebsparameter ueber unauthentifizierten Kanal aenderbar", "CWE-306", "high", "auth"),
    ],
    "remote_access": [  # remote maintenance / VPN box
        ("ra-default", "Fernzugang mit Default-Passwort", "CWE-259", "critical", "auth"),
        ("ra-nomfa", "Keine starke Authentifizierung (MFA) fuer Fernzugang", "CWE-287", "high", "auth"),
    ],
    "sensor": [  # networked sensor
        ("sns-integrity", "Messwerte ohne Integritaetsschutz uebertragen", "CWE-345", "medium", "integrity"),
    ],
}

_SOURCE = "Komponenten-Klasse (CISA-ICS-typisch — produktspezifisch pruefen)"


def findings_from_components(components: list) -> list:
    """components: [{name, component_class, networked, vendor?, product?}]. Returns
    finding dicts (ScannerFinding-shaped) for the NETWORKED components only."""
    out = []
    for comp in components or []:
        if not comp.get("networked"):
            continue
        klass = (comp.get("component_class") or "").lower()
        name = comp.get("name") or klass or "Komponente"
        for suffix, title, cwe, severity, category in _CLASS_VULN_TEMPLATES.get(klass, []):
            out.append({
                "id": "{}-{}".format(name, suffix).replace(" ", "_"),
                "title": "{} ({})".format(title, name),
                "cwe": cwe,
                "severity": severity,
                "category": category,
                "location": name,
                "source": _SOURCE,
            })
    return out
