"""Event, signal, and feature models for the CyberFlage pipeline."""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any


@dataclass(slots=True)
class Event:
    """Raw event emitted by an upstream subsystem (network, fs, process, etc.)."""

    source: str
    event_type: str
    severity: float = 0.5
    payload: dict[str, Any] = field(default_factory=dict)


@dataclass(slots=True)
class Signal:
    """Normalized risk signal derived from one event."""

    name: str
    weight: float
    metadata: dict[str, Any] = field(default_factory=dict)


@dataclass(slots=True)
class Feature:
    """Feature engineered from a collection of signals."""

    name: str
    value: float
    metadata: dict[str, Any] = field(default_factory=dict)


def events_to_signals(events: list[Event]) -> list[Signal]:
    """Convert events into normalized weighted signals."""
    signals: list[Signal] = []
    for event in events:
        base_weight = max(0.0, min(1.0, event.severity)) * 20.0
        signals.append(
            Signal(
                name=event.event_type,
                weight=base_weight,
                metadata={"source": event.source, **event.payload},
            )
        )
    return signals


def signals_to_features(signals: list[Signal]) -> list[Feature]:
    """Build compact features from normalized signals."""
    if not signals:
        return [
            Feature(name="signal_count", value=0.0),
            Feature(name="total_signal_weight", value=0.0),
            Feature(name="max_signal_weight", value=0.0),
        ]

    weights = [float(signal.weight) for signal in signals]
    return [
        Feature(name="signal_count", value=float(len(signals))),
        Feature(name="total_signal_weight", value=float(sum(weights))),
        Feature(name="max_signal_weight", value=float(max(weights))),
    ]


def format_risk_explanation(
    *,
    previous_risk: float,
    decayed_risk: float,
    signal_contributions: list[tuple[str, float]],
    feature_contributions: list[tuple[str, float]],
    final_risk: float,
) -> list[str]:
    """Return human-readable risk contribution lines."""
    lines = [f"Risk {previous_risk:.2f} -> {decayed_risk:.2f} (decay)"]
    for name, delta in signal_contributions:
        lines.append(f"+{delta:.2f} signal:{name}")
    for name, delta in feature_contributions:
        lines.append(f"+{delta:.2f} feature:{name}")
    lines.append(f"Risk = {final_risk:.2f}")
    return lines
