using Prometheus;

public sealed class ClinicalMetrics
{
    // --- Counters ---

    // Labeled by observation_code and source so clinicians can see which device types
    // and which codes dominate the ingest volume.
    public readonly Counter ObservationsIngestedTotal = Metrics.CreateCounter(
        "observations_ingested_total",
        "Total observations ingested, labeled by observation code and source.",
        labelNames: new[] { "observation_code", "source" });

    // Labeled by alert_type and severity (e.g. QSOFA_SCREEN/WARNING, SOFA_SEPSIS/CRITICAL).
    public readonly Counter ClinicalAlertsTotal = Metrics.CreateCounter(
        "clinical_alerts_total",
        "Total clinical alerts generated, labeled by type and severity.",
        labelNames: new[] { "alert_type", "severity" });

    public readonly Counter News2ScoresTotal = Metrics.CreateCounter(
        "news2_scores_total",
        "Total NEWS2 scores computed, labeled by risk level.",
        labelNames: new[] { "risk_level" });

    // Incremented by EscalationWorkerService when it processes a message from
    // alerts.escalation.queue. A rising escalations_total is the strongest operational
    // signal that critical alerts are not being acknowledged by the attending physician.
    public readonly Counter EscalationsTotal = Metrics.CreateCounter(
        "escalations_total",
        "Total alert escalations processed through the DLQ escalation path.");

    public readonly Counter TrendAlertsTotal = Metrics.CreateCounter(
        "trend_alerts_total",
        "Total RAPID_DETERIORATION alerts generated, labeled by observation code.",
        labelNames: new[] { "observation_code" });

    public readonly Counter AlertSuppressionsTotal = Metrics.CreateCounter(
        "alert_suppressions_total",
        "Total alert suppression windows set after acknowledgment.",
        labelNames: new[] { "alert_type" });

    public readonly Counter QsofaDetectionsTotal = Metrics.CreateCounter(
        "qsofa_detections_total",
        "Total QSOFA_SCREEN alerts generated by the qSOFA screening engine.");

    public readonly Counter SepsisBundleComplianceTotal = Metrics.CreateCounter(
        "sepsis_bundle_compliance_total",
        "Sepsis bundle compliance outcomes.",
        labelNames: new[] { "status" });

    public readonly Counter GcsScoresTotal = Metrics.CreateCounter(
        "gcs_scores_total",
        "GCS scores computed, labeled by classification.",
        labelNames: new[] { "classification" });

    public readonly Counter SofaScoresTotal = Metrics.CreateCounter(
        "sofa_scores_total",
        "SOFA scores computed, labeled by whether a delta alert was created.",
        labelNames: new[] { "has_delta_alert" });

    public readonly Counter FhirIngestTotal = Metrics.CreateCounter(
        "fhir_ingest_total",
        "FHIR resource ingest operations.",
        labelNames: new[] { "resource_type", "outcome" });

    public readonly Counter FhirReadTotal = Metrics.CreateCounter(
        "fhir_read_total",
        "FHIR resource read/search operations.",
        labelNames: new[] { "resource_type", "interaction", "outcome" });

    public readonly Counter AuthorizationFailuresTotal = Metrics.CreateCounter(
        "authorization_failures_total",
        "Authorization failures by permission and role.",
        labelNames: new[] { "permission", "role" });

    public readonly Counter FhirMappingErrorsTotal = Metrics.CreateCounter(
        "fhir_mapping_errors_total",
        "FHIR mapping failures.",
        labelNames: new[] { "reason" });

    public readonly Counter PhiAccessLogsTotal = Metrics.CreateCounter(
        "phi_access_logs_total",
        "PHI access log entries written.",
        labelNames: new[] { "access_type" });

    public readonly Counter ClinicalSyncBatchesTotal = Metrics.CreateCounter(
        "clinical_sync_batches_total",
        "Sync batches processed",
        labelNames: new[] { "status" });
    // --- Histograms ---

    // Measures the full ingest transaction: Redis cache lookup + alert evaluation +
    // outbox write + COMMIT. The 99th percentile matters for patient safety —
    // a slow ingest path delays the critical alert creation.
    public readonly Histogram ObservationIngestDuration = Metrics.CreateHistogram(
        "observation_ingest_duration_seconds",
        "Ingest transaction duration from request receipt to COMMIT.",
        new HistogramConfiguration
        {
            Buckets = new[] { 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0 }
        });

    public readonly Histogram News2ScoringDuration = Metrics.CreateHistogram(
        "news2_scoring_duration_seconds",
        "Time to compute a NEWS2 score from Redis state.",
        new HistogramConfiguration
        {
            Buckets = new[] { 0.001, 0.005, 0.01, 0.025, 0.05, 0.1 }
        });   
        
    public readonly Histogram TrendAnalysisDuration = Metrics.CreateHistogram(
        "trend_analysis_duration_seconds",
        "Time to evaluate trend for one observation.",
        new HistogramConfiguration
        {
            Buckets = new[] { 0.001, 0.005, 0.01, 0.025, 0.05, 0.1 }
        });

    public readonly Histogram SofaScoringDuration = Metrics.CreateHistogram(
        "sofa_scoring_duration_seconds",
        "SOFA scoring computation time",
        new HistogramConfiguration
        {
            Buckets = new[] { 0.001, 0.005, 0.01, 0.025, 0.05, 0.1 }
        });

    public readonly Histogram ClinicalSyncBatchDuration = Metrics.CreateHistogram(
        "clinical_sync_batch_duration_seconds",
        "Batch processing duration",
        new HistogramConfiguration
        {
            Buckets = new[] { 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0 }
        });

        // --- Gauges (set by background collectors, not incremented inline) ---

        // The most clinically significant panel. A non-zero value means a patient's
        // critical alert has gone unacknowledged for more than 5 minutes.
        // In a real deployment this panel drives an on-call pager alert at the nurse station.
        public readonly Gauge AlertsUnacknowledgedGauge = Metrics.CreateGauge(
            "alerts_unacknowledged_gauge",
            "Count of open CRITICAL alerts older than 5 minutes with no acknowledgment.");

        // Per consumer group so the dashboard can show whether es-indexer, sepsis-engine,
        // or data-lake-writer is falling behind the observation stream.
        public readonly Gauge KafkaConsumerLag = Metrics.CreateGauge(
            "kafka_consumer_lag",
            "Approximate consumer group lag in messages, labeled by consumer group.",
            labelNames: new[] { "consumer_group" });

        // An outbox that is growing means the relay is not keeping up or Kafka is unavailable.
        // In a patient safety system, a growing outbox delays alert delivery to all consumers.
        public readonly Gauge OutboxPendingEvents = Metrics.CreateGauge(
            "outbox_pending_events",
            "Count of outbox events not yet relayed to Kafka.");

        public readonly Gauge WardGatewaysOffline = Metrics.CreateGauge(
            "ward_gateways_offline_gauge",
            "Ward gateways with status OFFLINE or DEGRADED",
            labelNames: new[] { "site_code" });

        public readonly Gauge WardGatewayBufferDepth = Metrics.CreateGauge(
            "ward_gateway_buffer_depth",
            "Reported unsynced event count per gateway",
            labelNames: new[] { "gateway_code", "department" });

        public readonly Gauge AlertAcknowledgementRate = Metrics.CreateGauge(
            "vigilcare_alert_acknowledgement_rate",
            "Alert acknowledgement rate by type.",
            labelNames: new[] { "alert_type" });

        public readonly Gauge AlertFalsePositiveRate = Metrics.CreateGauge(
            "vigilcare_alert_false_positive_rate",
            "Clinician-reported false positive rate by type.",
            labelNames: new[] { "alert_type" });

        public readonly Gauge AlertUsefulRate = Metrics.CreateGauge(
            "vigilcare_alert_useful_rate",
            "Clinician-reported useful rate by type.",
            labelNames: new[] { "alert_type" });

        public readonly Gauge AlertAvgAckSeconds = Metrics.CreateGauge(
            "vigilcare_alert_avg_ack_seconds",
            "Average seconds from trigger to acknowledgement by type.",
            labelNames: new[] { "alert_type" });
    }