// file: kb_lib/src/local_dex_corpus_search.rs

//! Local DEX corpus search service used by Demo3.

/// Local DEX corpus search service.
#[derive(Debug, Clone)]
pub struct LocalDexCorpusSearchService {
    database: std::sync::Arc<crate::Database>,
}

impl LocalDexCorpusSearchService {
    /// Creates a new local DEX corpus search service.
    pub fn new(database: std::sync::Arc<crate::Database>) -> Self {
        return Self { database };
    }

    /// Searches the local persisted pipeline for DEX corpus candidates.
    pub async fn search(
        &self,
        request: crate::LocalDexCorpusSearchRequestDto,
    ) -> Result<crate::LocalDexCorpusSearchResultDto, crate::Error> {
        let normalized_request = normalize_request(request);
        let summary_result = crate::query_local_dex_corpus_search_get_summary(
            self.database.as_ref(),
            &normalized_request,
        )
        .await;
        let summary = match summary_result {
            Ok(summary) => summary,
            Err(error) => return Err(error),
        };
        let transaction_samples_result =
            crate::query_local_dex_corpus_search_list_transaction_samples(
                self.database.as_ref(),
                &normalized_request,
            )
            .await;
        let transaction_samples = match transaction_samples_result {
            Ok(transaction_samples) => transaction_samples,
            Err(error) => return Err(error),
        };
        let pool_pair_samples_result = crate::query_local_dex_corpus_search_list_pool_pair_samples(
            self.database.as_ref(),
            &normalized_request,
        )
        .await;
        let pool_pair_samples = match pool_pair_samples_result {
            Ok(pool_pair_samples) => pool_pair_samples,
            Err(error) => return Err(error),
        };
        let decoded_event_samples_result =
            crate::query_local_dex_corpus_search_list_decoded_event_samples(
                self.database.as_ref(),
                &normalized_request,
            )
            .await;
        let decoded_event_samples = match decoded_event_samples_result {
            Ok(decoded_event_samples) => decoded_event_samples,
            Err(error) => return Err(error),
        };
        return Ok(crate::LocalDexCorpusSearchResultDto {
            request: normalized_request,
            summary,
            transaction_samples,
            pool_pair_samples,
            decoded_event_samples,
        });
    }
}

fn normalize_request(
    request: crate::LocalDexCorpusSearchRequestDto,
) -> crate::LocalDexCorpusSearchRequestDto {
    let limit = if request.limit == 0 {
        50
    } else if request.limit > 200 {
        200
    } else {
        request.limit
    };
    return crate::LocalDexCorpusSearchRequestDto {
        dex_code: normalize_optional_text(request.dex_code),
        program_id: normalize_optional_text(request.program_id),
        pair_id: request.pair_id,
        pool_address: normalize_optional_text(request.pool_address),
        token_mint: normalize_optional_text(request.token_mint),
        signature: normalize_optional_text(request.signature),
        limit,
    };
}

fn normalize_optional_text(
    value: std::option::Option<std::string::String>,
) -> std::option::Option<std::string::String> {
    let value = match value {
        Some(value) => value.trim().to_string(),
        None => return None,
    };
    if value.is_empty() {
        return None;
    }
    return Some(value);
}
