"""Basic Inference Example for Sofia Engine.

Demonstrates deterministic telemetry feature extraction, statistical anomaly
detection, and evidence-based diagnostic health scoring.

Run:
    python examples/basic_inference.py
"""

from __future__ import annotations

import numpy as np

from sofia_ai.core.contracts import DataQuality, FeatureVector, SignalWindow
from sofia_ai.diagnostics.engine import (
    DiagnosticEngine,
    HealthEvent,
    HealthScore,
    compute_health_score,
)
from sofia_ai.diagnostics.rules import RuleContext
from sofia_ai.features import extract_from_array
from sofia_ai.inference.detectors import ThresholdDetector, build_manifest_for


def run_basic_inference() -> None:
    print("=== Sofia Engine: Basic Inference Example ===")

    # 1. Synthesize 1 second of vibration telemetry (fs = 1000 Hz, 25 Hz shaft rotation)
    fs = 1000.0
    t = np.arange(1000) / fs
    rng = np.random.default_rng(42)
    # 25 Hz fundamental + 50 Hz harmonic + Gaussian background noise
    raw_signal = (
        0.45 * np.sin(2 * np.pi * 25.0 * t)
        + 0.15 * np.sin(2 * np.pi * 50.0 * t)
        + 0.05 * rng.normal(size=len(t))
    )

    print(f"Input Signal: {len(raw_signal)} samples @ {fs} Hz ({len(raw_signal)/fs:.2f} s)")

    # 2. Package into a validated SignalWindow
    window = SignalWindow(
        values=raw_signal,
        sample_rate=fs,
        device_id="pump-motor-01",
        channel="vibration_de",
        unit="m/s^2",
        quality=DataQuality.GOOD,
    )

    # 3. Extract versioned feature vector (14 statistical + spectral metrics)
    features: FeatureVector = extract_from_array(
        window.values,
        window.sample_rate,
        channel=window.channel,
        quality=window.quality,
    )

    # 4. Verify feature schema version (v3.0)
    features.validate_schema("3.0")
    print(f"Extracted FeatureVector (schema {features.schema_version}): {len(features.names)} features")
    for name, val in list(zip(features.names, features.values, strict=True))[:5]:
        print(f"  - {name}: {val:.4f}")

    # 5. Anomaly detection via ThresholdDetector (monitoring vibration RMS)
    detector = ThresholdDetector(feature="rms", high=0.45)
    manifest = build_manifest_for(detector, model_id="rms_threshold_v1", version="1.0.0")
    detector.load(manifest)
    inference_result = detector.infer(features)

    print("\n--- Inference Result (Threshold Detector) ---")
    print(f"Monitored Feature: 'rms' = {inference_result.score:.4f} m/s^2 (high limit = 0.45)")
    print(f"Outcome:           {inference_result.outcome.name}")
    print(f"Confidence:        {inference_result.confidence:.2%}")

    # 6. Diagnostic Engine: Convert inference into evidence-backed health event
    diag_engine = DiagnosticEngine()
    context = RuleContext(
        device_id=window.device_id,
        channel=window.channel,
        score=inference_result.score,
        confidence=inference_result.confidence,
        unit="z-score",
    )
    event: HealthEvent | None = diag_engine.evaluate(context)

    events = [event] if event else []
    health_score: HealthScore = compute_health_score(events)

    print("\n--- Health Assessment ---")
    print(f"Health Score:      {health_score.score:.1f} / 100.0")
    print(f"Credible Interval: [{health_score.lower:.1f}, {health_score.upper:.1f}]")
    print(f"Uncertainty:       ±{health_score.uncertainty:.2%}")
    if event:
        print(f"Health Event:      {event.event_type} (Severity: {event.severity.name})")
        print(f"Recommendation:    {event.recommendation}")
    else:
        print("Status:            Nominal operating condition.")


if __name__ == "__main__":
    run_basic_inference()
