// file: kb_lib/src/local_pipeline_diagnostics.rs

//! Local pipeline diagnostics service.

/// Local pipeline diagnostics service.
#[derive(Debug, Clone)]
pub struct LocalPipelineDiagnosticsService {
    database: std::sync::Arc<crate::Database>,
}

impl LocalPipelineDiagnosticsService {
    /// Creates a new local pipeline diagnostics service.
    pub fn new(database: std::sync::Arc<crate::Database>) -> Self {
        return Self { database };
    }

    /// Builds a local pipeline diagnostics summary from already persisted data.
    pub async fn diagnose(&self) -> Result<crate::LocalPipelineDiagnosticSummaryDto, crate::Error> {
        let sample_limit = 25_i64;
        let counters_result =
            crate::query_local_pipeline_diagnostic_get_counters(self.database.as_ref()).await;
        let counters = match counters_result {
            Ok(counters) => counters,
            Err(error) => return Err(error),
        };
        let dex_summaries_result =
            crate::query_local_pipeline_diagnostic_list_summaries(self.database.as_ref()).await;
        let dex_summaries = match dex_summaries_result {
            Ok(dex_summaries) => dex_summaries,
            Err(error) => return Err(error),
        };
        let pair_summaries_result =
            crate::query_local_pair_diagnostic_list_summaries(self.database.as_ref()).await;
        let pair_summaries = match pair_summaries_result {
            Ok(pair_summaries) => pair_summaries,
            Err(error) => return Err(error),
        };
        let pair_actionability_summaries_result =
            crate::query_local_pair_actionability_diagnostic_list_summaries(self.database.as_ref())
                .await;
        let pair_actionability_summaries = match pair_actionability_summaries_result {
            Ok(summaries) => summaries,
            Err(error) => return Err(error),
        };
        let pair_trading_readiness_summaries_result =
            crate::query_local_pair_trading_readiness_diagnostic_list_summaries(
                self.database.as_ref(),
            )
            .await;
        let pair_trading_readiness_summaries = match pair_trading_readiness_summaries_result {
            Ok(summaries) => summaries,
            Err(error) => return Err(error),
        };
        let decoded_event_summaries_result =
            crate::query_local_decoded_event_diagnostic_list_summaries(self.database.as_ref())
                .await;
        let decoded_event_summaries = match decoded_event_summaries_result {
            Ok(decoded_event_summaries) => decoded_event_summaries,
            Err(error) => return Err(error),
        };
        let event_classification_summaries_result =
            crate::query_local_event_classification_diagnostic_list_summaries(
                self.database.as_ref(),
            )
            .await;
        let event_classification_summaries = match event_classification_summaries_result {
            Ok(summaries) => summaries,
            Err(error) => return Err(error),
        };
        let missing_trade_event_reason_summaries_result =
            crate::query_local_missing_trade_event_reason_list_summaries(self.database.as_ref())
                .await;
        let missing_trade_event_reason_summaries = match missing_trade_event_reason_summaries_result
        {
            Ok(summaries) => summaries,
            Err(error) => return Err(error),
        };
        let non_actionable_pair_summaries_result =
            crate::query_local_non_actionable_pair_diagnostic_list_summaries(
                self.database.as_ref(),
                sample_limit,
            )
            .await;
        let non_actionable_pair_summaries = match non_actionable_pair_summaries_result {
            Ok(summaries) => summaries,
            Err(error) => return Err(error),
        };
        let missing_trade_event_samples_result =
            crate::query_local_missing_trade_event_diagnostic_list_samples(
                self.database.as_ref(),
                sample_limit,
            )
            .await;
        let missing_trade_event_samples = match missing_trade_event_samples_result {
            Ok(samples) => samples,
            Err(error) => return Err(error),
        };
        let duplicate_decoded_event_trade_samples_result =
            crate::query_local_duplicate_decoded_event_trade_diagnostic_list_samples(
                self.database.as_ref(),
                sample_limit,
            )
            .await;
        let duplicate_decoded_event_trade_samples =
            match duplicate_decoded_event_trade_samples_result {
                Ok(samples) => samples,
                Err(error) => return Err(error),
            };
        let multi_trade_signature_pair_samples_result =
            crate::query_local_multi_trade_signature_pair_diagnostic_list_samples(
                self.database.as_ref(),
                sample_limit,
            )
            .await;
        let multi_trade_signature_pair_samples = match multi_trade_signature_pair_samples_result {
            Ok(samples) => samples,
            Err(error) => return Err(error),
        };
        let pair_without_trade_samples_result =
            crate::query_local_pair_without_trade_diagnostic_list_samples(
                self.database.as_ref(),
                sample_limit,
            )
            .await;
        let pair_without_trade_samples = match pair_without_trade_samples_result {
            Ok(samples) => samples,
            Err(error) => return Err(error),
        };
        let pair_without_candle_samples_result =
            crate::query_local_pair_without_candle_diagnostic_list_samples(
                self.database.as_ref(),
                sample_limit,
            )
            .await;
        let pair_without_candle_samples = match pair_without_candle_samples_result {
            Ok(samples) => samples,
            Err(error) => return Err(error),
        };
        let blocking_issue_count = counters.actionable_missing_trade_event_count
            + counters.invalid_trade_event_count
            + counters.duplicate_decoded_event_trade_count
            + counters.duplicate_candle_bucket_count;
        let diagnostics_clean = blocking_issue_count == 0;
        return Ok(crate::LocalPipelineDiagnosticSummaryDto {
            transaction_count: counters.transaction_count,
            ok_transaction_count: counters.ok_transaction_count,
            failed_transaction_count: counters.failed_transaction_count,
            decoded_event_count: counters.decoded_event_count,
            decoded_trade_candidate_count: counters.decoded_trade_candidate_count,
            decoded_candle_candidate_count: counters.decoded_candle_candidate_count,
            decoded_non_trade_useful_event_count: counters.decoded_non_trade_useful_event_count,
            decoded_non_actionable_trade_event_count: counters
                .decoded_non_actionable_trade_event_count,
            decoded_unknown_event_count: counters.decoded_unknown_event_count,
            diagnostics_clean,
            blocking_issue_count,
            missing_trade_event_count: counters.missing_trade_event_count,
            decoded_trade_candidate_without_trade_event_count: counters
                .decoded_trade_candidate_without_trade_event_count,
            decoded_trade_candidate_without_trade_event_on_ok_transaction_count: counters
                .decoded_trade_candidate_without_trade_event_on_ok_transaction_count,
            decoded_trade_candidate_without_trade_event_on_failed_transaction_count: counters
                .decoded_trade_candidate_without_trade_event_on_failed_transaction_count,
            actionable_missing_trade_event_count: counters.actionable_missing_trade_event_count,
            ignored_failed_transaction_trade_candidate_count: counters
                .ignored_failed_transaction_trade_candidate_count,
            decoded_trade_candidate_without_amount_payload_count: counters
                .decoded_trade_candidate_without_amount_payload_count,
            trade_event_count: counters.trade_event_count,
            invalid_trade_event_count: counters.invalid_trade_event_count,
            pair_candle_count: counters.pair_candle_count,
            duplicate_decoded_event_trade_count: counters.duplicate_decoded_event_trade_count,
            multi_trade_signature_pair_count: counters.multi_trade_signature_pair_count,
            duplicate_candle_bucket_count: counters.duplicate_candle_bucket_count,
            token_count: counters.token_count,
            token_metadata_missing_count: counters.token_metadata_missing_count,
            pool_count: counters.pool_count,
            pair_count: counters.pair_count,
            pair_gap_counter_semantics: "blocking_actionable_pairs_only".to_string(),
            literal_pair_without_trade_count: counters.literal_pair_without_trade_count,
            literal_pair_without_candle_count: counters.literal_pair_without_candle_count,
            trade_materialized_pair_count: counters.trade_materialized_pair_count,
            candle_materialized_pair_count: counters.candle_materialized_pair_count,
            actionable_pair_count: counters.actionable_pair_count,
            candle_bucket_timeframe_count: counters.candle_bucket_timeframe_count,
            candles_are_bucketed: counters.candle_bucket_timeframe_count > 0,
            blocking_pair_without_trade_count: counters.blocking_pair_without_trade_count,
            blocking_pair_without_candle_count: counters.blocking_pair_without_candle_count,
            pair_without_trade_count: counters.pair_without_trade_count,
            pair_without_candle_count: counters.pair_without_candle_count,
            dex_summaries,
            pair_summaries,
            pair_actionability_summaries,
            pair_trading_readiness_summaries,
            decoded_event_summaries,
            event_classification_summaries,
            missing_trade_event_reason_summaries,
            non_actionable_pair_count: counters.non_actionable_pair_count,
            non_actionable_pair_summaries,
            missing_trade_event_samples,
            duplicate_decoded_event_trade_samples,
            multi_trade_signature_pair_samples,
            pair_without_trade_samples,
            pair_without_candle_samples,
        });
    }
}
