// File: crates/router/src/core/webhooks/outgoing_v2.rs
// Module: router

use std::collections::HashMap;

use api_models::{webhook_events, webhooks};
use common_utils::{ext_traits, request, type_name, types::keymanager};
use diesel_models::process_tracker::business_status;
use error_stack::{report, Report, ResultExt};
use hyperswitch_domain_models::type_encryption::{crypto_operation, CryptoOperation};
use hyperswitch_interfaces::consts;
use masking;
use router_env::{
    instrument,
    tracing::{self, Instrument},
};

use super::{
    types,
    utils::{self, increment_webhook_outgoing_received_count},
    MERCHANT_ID,
};
use crate::{
    core::{
        errors::{self, CustomResult},
        metrics,
    },
    events::outgoing_webhook_logs,
    logger,
    routes::{app::SessionStateInfo, SessionState},
    services,
    types::{
        api, domain,
        storage::{self, enums},
        transformers::ForeignFrom,
    },
};

#[allow(clippy::too_many_arguments)]
#[instrument(skip_all)]
pub(crate) async fn create_event_and_trigger_outgoing_webhook(
    state: SessionState,
    business_profile: domain::Profile,
    merchant_key_store: &domain::MerchantKeyStore,
    event_type: enums::EventType,
    event_class: enums::EventClass,
    primary_object_id: String,
    primary_object_type: enums::EventObjectType,
    content: api::OutgoingWebhookContent,
    primary_object_created_at: time::PrimitiveDateTime,
) -> CustomResult<(), errors::ApiErrorResponse> {
    let delivery_attempt = enums::WebhookDeliveryAttempt::InitialAttempt;
    let idempotent_event_id =
        utils::get_idempotent_event_id(&primary_object_id, event_type, delivery_attempt)
            .change_context(errors::ApiErrorResponse::WebhookProcessingFailure)
            .attach_printable("Failed to generate idempotent event ID")?;
    let webhook_url_result = business_profile
        .get_webhook_url_from_profile()
        .change_context(errors::WebhooksFlowError::MerchantWebhookUrlNotConfigured);

    if utils::is_outgoing_webhook_disabled(
        &state,
        &webhook_url_result,
        &business_profile,
        &idempotent_event_id,
    ) {
        return Ok(());
    }

    let event_id = utils::generate_event_id();
    let merchant_id = business_profile.merchant_id.clone();
    let now = common_utils::date_time::now();

    let outgoing_webhook = api::OutgoingWebhook {
        merchant_id: merchant_id.clone(),
        event_id: event_id.clone(),
        event_type,
        content: content.clone(),
        timestamp: now,
    };

    let request_content = get_outgoing_webhook_request(outgoing_webhook, &business_profile)
        .change_context(errors::ApiErrorResponse::WebhookProcessingFailure)
        .attach_printable("Failed to construct outgoing webhook request content")?;

    let event_metadata = storage::EventMetadata::foreign_from(&content);
    let key_manager_state = &(&state).into();
    let new_event = domain::Event {
        event_id: event_id.clone(),
        event_type,
        event_class,
        is_webhook_notified: false,
        primary_object_id,
        primary_object_type,
        created_at: now,
        merchant_id: Some(business_profile.merchant_id.clone()),
        business_profile_id: Some(business_profile.get_id().to_owned()),
        primary_object_created_at: Some(primary_object_created_at),
        idempotent_event_id: Some(idempotent_event_id.clone()),
        initial_attempt_id: Some(event_id.clone()),
        request: Some(
            crypto_operation(
                key_manager_state,
                type_name!(domain::Event),
                CryptoOperation::Encrypt(
                    ext_traits::Encode::encode_to_string_of_json(&request_content)
                        .change_context(errors::ApiErrorResponse::WebhookProcessingFailure)
                        .attach_printable("Failed to encode outgoing webhook request content")
                        .map(masking::Secret::new)?,
                ),
                keymanager::Identifier::Merchant(merchant_key_store.merchant_id.clone()),
                masking::PeekInterface::peek(merchant_key_store.key.get_inner()),
            )
            .await
            .and_then(|val| val.try_into_operation())
            .change_context(errors::ApiErrorResponse::WebhookProcessingFailure)
            .attach_printable("Failed to encrypt outgoing webhook request content")?,
        ),
        response: None,
        delivery_attempt: Some(delivery_attempt),
        metadata: Some(event_metadata),
        is_overall_delivery_successful: Some(false),
    };

    let event_insert_result = state
        .store
        .insert_event(key_manager_state, new_event, merchant_key_store)
        .await;

    let event = match event_insert_result {
        Ok(event) => Ok(event),
        Err(error) => {
            if error.current_context().is_db_unique_violation() {
                // If the event_id already exists in the database, it indicates that the event for the resource has already been sent, so we skip the flow
                logger::debug!("Event with idempotent ID `{idempotent_event_id}` already exists in the database");
                return Ok(());
            } else {
                logger::error!(event_insertion_failure=?error);
                Err(error
                    .change_context(errors::ApiErrorResponse::WebhookProcessingFailure)
                    .attach_printable("Failed to insert event in events table"))
            }
        }
    }?;

    let cloned_key_store = merchant_key_store.clone();
    // Using a tokio spawn here and not arbiter because not all caller of this function
    // may have an actix arbiter
    tokio::spawn(
        async move {
            Box::pin(trigger_webhook_and_raise_event(
                state,
                business_profile,
                &cloned_key_store,
                event,
                request_content,
                delivery_attempt,
                Some(content),
            ))
            .await;
        }
        .in_current_span(),
    );

    Ok(())
}

#[allow(clippy::too_many_arguments)]
#[instrument(skip_all)]
pub(crate) async fn trigger_webhook_and_raise_event(
    state: SessionState,
    business_profile: domain::Profile,
    merchant_key_store: &domain::MerchantKeyStore,
    event: domain::Event,
    request_content: webhook_events::OutgoingWebhookRequestContent,
    delivery_attempt: enums::WebhookDeliveryAttempt,
    content: Option<api::OutgoingWebhookContent>,
) {
    logger::debug!(
        event_id=%event.event_id,
        idempotent_event_id=?event.idempotent_event_id,
        initial_attempt_id=?event.initial_attempt_id,
        "Attempting to send webhook"
    );

    let merchant_id = business_profile.merchant_id.clone();
    let trigger_webhook_result = trigger_webhook_to_merchant(
        state.clone(),
        business_profile,
        merchant_key_store,
        event.clone(),
        request_content,
        delivery_attempt,
    )
    .await;

    let _ =
        raise_webhooks_analytics_event(state, trigger_webhook_result, content, merchant_id, event)
            .await;
}

async fn trigger_webhook_to_merchant(
    state: SessionState,
    business_profile: domain::Profile,
    merchant_key_store: &domain::MerchantKeyStore,
    event: domain::Event,
    request_content: webhook_events::OutgoingWebhookRequestContent,
    delivery_attempt: enums::WebhookDeliveryAttempt,
) -> CustomResult<
    (domain::Event, Option<Report<errors::WebhooksFlowError>>),
    errors::WebhooksFlowError,
> {
    let webhook_url = business_profile
        .get_webhook_url_from_profile()
        .change_context(errors::WebhooksFlowError::MerchantWebhookUrlNotConfigured)?;

    let response = build_and_send_request(&state, request_content, webhook_url).await;

    metrics::WEBHOOK_OUTGOING_COUNT.add(
        1,
        router_env::metric_attributes!((MERCHANT_ID, business_profile.merchant_id.clone())),
    );
    logger::debug!(outgoing_webhook_response=?response);

    match response {
        Ok(response) => {
            delivery_attempt
                .handle_success_response(
                    state,
                    merchant_key_store.clone(),
                    &business_profile.merchant_id,
                    &event.event_id,
                    None,
                    response,
                )
                .await
        }
        Err(client_error) => {
            delivery_attempt
                .handle_error_response(
                    state,
                    merchant_key_store.clone(),
                    &business_profile.merchant_id,
                    &event.event_id,
                    client_error,
                )
                .await
        }
    }
}

async fn raise_webhooks_analytics_event(
    state: SessionState,
    trigger_webhook_result: CustomResult<
        (domain::Event, Option<Report<errors::WebhooksFlowError>>),
        errors::WebhooksFlowError,
    >,
    content: Option<api::OutgoingWebhookContent>,
    merchant_id: common_utils::id_type::MerchantId,
    fallback_event: domain::Event,
) {
    let (updated_event, optional_error) = match trigger_webhook_result {
        Ok((updated_event, error)) => (updated_event, error),
        Err(error) => (fallback_event, Some(error)),
    };
    let error = optional_error.and_then(|error| {
        logger::error!(?error, "Failed to send webhook to merchant");

        serde_json::to_value(error.current_context())
            .change_context(errors::ApiErrorResponse::WebhookProcessingFailure)
            .inspect_err(|error| {
                logger::error!(?error, "Failed to serialize outgoing webhook error as JSON");
            })
            .ok()
    });

    let outgoing_webhook_event_content = content
        .as_ref()
        .and_then(
            outgoing_webhook_logs::OutgoingWebhookEventMetric::get_outgoing_webhook_event_content,
        )
        .or_else(|| {
            updated_event
                .metadata
                .map(outgoing_webhook_logs::OutgoingWebhookEventContent::foreign_from)
        });

    // Get status_code from webhook response
    let status_code = {
        let webhook_response: Option<webhook_events::OutgoingWebhookResponseContent> =
            updated_event.response.and_then(|res| {
                ext_traits::StringExt::parse_struct(
                    masking::PeekInterface::peek(res.get_inner()),
                    "OutgoingWebhookResponseContent",
                )
                .map_err(|error| {
                    logger::error!(?error, "Error deserializing webhook response");
                    error
                })
                .ok()
            });
        webhook_response.and_then(|res| res.status_code)
    };

    let webhook_event = outgoing_webhook_logs::OutgoingWebhookEvent::new(
        state.tenant.tenant_id.clone(),
        merchant_id,
        updated_event.event_id,
        updated_event.event_type,
        outgoing_webhook_event_content,
        error,
        updated_event.initial_attempt_id,
        status_code,
        updated_event.delivery_attempt,
    );
    state.event_handler().log_event(&webhook_event);
}

pub(crate) fn get_outgoing_webhook_request(
    outgoing_webhook: api::OutgoingWebhook,
    business_profile: &domain::Profile,
) -> CustomResult<webhook_events::OutgoingWebhookRequestContent, errors::WebhooksFlowError> {
    #[inline]
    fn get_outgoing_webhook_request_inner<WebhookType: types::OutgoingWebhookType>(
        outgoing_webhook: api::OutgoingWebhook,
        business_profile: &domain::Profile,
    ) -> CustomResult<webhook_events::OutgoingWebhookRequestContent, errors::WebhooksFlowError>
    {
        let mut headers = vec![
            (
                reqwest::header::CONTENT_TYPE.to_string(),
                mime::APPLICATION_JSON.essence_str().into(),
            ),
            (
                reqwest::header::USER_AGENT.to_string(),
                consts::USER_AGENT.to_string().into(),
            ),
        ];

        let transformed_outgoing_webhook = WebhookType::from(outgoing_webhook);
        let payment_response_hash_key = business_profile.payment_response_hash_key.clone();
        let custom_headers = business_profile
            .outgoing_webhook_custom_http_headers
            .clone()
            .map(|headers| {
                ext_traits::ValueExt::parse_value::<HashMap<String, String>>(
                    masking::ExposeInterface::expose(headers.into_inner()),
                    "HashMap<String,String>",
                )
                .change_context(errors::WebhooksFlowError::OutgoingWebhookEncodingFailed)
                .attach_printable("Failed to deserialize outgoing webhook custom HTTP headers")
            })
            .transpose()?;
        if let Some(ref map) = custom_headers {
            headers.extend(
                map.iter()
                    .map(|(key, value)| (key.clone(), masking::Mask::into_masked(value.clone()))),
            );
        };
        let outgoing_webhooks_signature = transformed_outgoing_webhook
            .get_outgoing_webhooks_signature(payment_response_hash_key)?;

        if let Some(signature) = outgoing_webhooks_signature.signature {
            WebhookType::add_webhook_header(&mut headers, signature)
        }

        Ok(webhook_events::OutgoingWebhookRequestContent {
            body: outgoing_webhooks_signature.payload,
            headers: headers
                .into_iter()
                .map(|(name, value)| (name, masking::Secret::new(value.into_inner())))
                .collect(),
        })
    }

    get_outgoing_webhook_request_inner::<webhooks::OutgoingWebhook>(
        outgoing_webhook,
        business_profile,
    )
}

async fn build_and_send_request(
    state: &SessionState,
    request_content: webhook_events::OutgoingWebhookRequestContent,
    webhook_url: String,
) -> Result<reqwest::Response, Report<common_enums::ApiClientError>> {
    let headers = request_content
        .headers
        .into_iter()
        .map(|(name, value)| (name, masking::Mask::into_masked(value)))
        .collect();
    let request = services::RequestBuilder::new()
        .method(services::Method::Post)
        .url(&webhook_url)
        .attach_default_headers()
        .headers(headers)
        .set_body(request::RequestContent::RawBytes(
            masking::ExposeInterface::expose(request_content.body).into_bytes(),
        ))
        .build();

    state
        .api_client
        .send_request(state, request, None, false)
        .await
}

async fn api_client_error_handler(
    state: SessionState,
    merchant_key_store: domain::MerchantKeyStore,
    merchant_id: &common_utils::id_type::MerchantId,
    event_id: &str,
    client_error: Report<errors::ApiClientError>,
    delivery_attempt: enums::WebhookDeliveryAttempt,
    _schedule_webhook_retry: types::ScheduleWebhookRetry,
) -> CustomResult<
    (domain::Event, Option<Report<errors::WebhooksFlowError>>),
    errors::WebhooksFlowError,
> {
    // Not including detailed error message in response information since it contains too
    // much of diagnostic information to be exposed to the merchant.
    let is_webhook_notified = false;
    let response_to_store = webhook_events::OutgoingWebhookResponseContent {
        body: None,
        headers: None,
        status_code: None,
        error_message: Some("Unable to send request to merchant server".to_string()),
    };
    let updated_event = update_event_in_storage(
        state,
        is_webhook_notified,
        response_to_store,
        merchant_key_store,
        merchant_id,
        event_id,
    )
    .await?;

    let error = client_error.change_context(errors::WebhooksFlowError::CallToMerchantFailed);
    logger::error!(
        ?error,
        ?delivery_attempt,
        "An error occurred when sending webhook to merchant"
    );

    //TODO: add outgoing webhook retries support
    // if let ScheduleWebhookRetry::WithProcessTracker(process_tracker) = schedule_webhook_retry {
    //     // Schedule a retry attempt for webhook delivery
    //     outgoing_webhook_retry::retry_webhook_delivery_task(
    //         &*state.store,
    //         merchant_id,
    //         *process_tracker,
    //     )
    //     .await
    //     .change_context(errors::WebhooksFlowError::OutgoingWebhookRetrySchedulingFailed)?;
    // }

    Ok((updated_event, Some(error)))
}

async fn update_event_in_storage(
    state: SessionState,
    is_webhook_notified: bool,
    outgoing_webhook_response: webhook_events::OutgoingWebhookResponseContent,
    merchant_key_store: domain::MerchantKeyStore,
    merchant_id: &common_utils::id_type::MerchantId,
    event_id: &str,
) -> CustomResult<domain::Event, errors::WebhooksFlowError> {
    let key_manager_state = &(&state).into();
    let event_update = domain::EventUpdate::UpdateResponse {
        is_webhook_notified,
        response: Some(
            crypto_operation(
                key_manager_state,
                type_name!(domain::Event),
                CryptoOperation::Encrypt(
                    ext_traits::Encode::encode_to_string_of_json(&outgoing_webhook_response)
                        .change_context(
                            errors::WebhooksFlowError::OutgoingWebhookResponseEncodingFailed,
                        )
                        .map(masking::Secret::new)?,
                ),
                keymanager::Identifier::Merchant(merchant_key_store.merchant_id.clone()),
                masking::PeekInterface::peek(merchant_key_store.key.get_inner()),
            )
            .await
            .and_then(|val| val.try_into_operation())
            .change_context(errors::WebhooksFlowError::WebhookEventUpdationFailed)
            .attach_printable("Failed to encrypt outgoing webhook response content")?,
        ),
    };
    state
        .store
        .update_event_by_merchant_id_event_id(
            key_manager_state,
            merchant_id,
            event_id,
            event_update,
            &merchant_key_store,
        )
        .await
        .change_context(errors::WebhooksFlowError::WebhookEventUpdationFailed)
}

async fn update_overall_delivery_status_in_storage(
    state: SessionState,
    merchant_key_store: domain::MerchantKeyStore,
    merchant_id: &common_utils::id_type::MerchantId,
    updated_event: &domain::Event,
) -> CustomResult<(), errors::WebhooksFlowError> {
    let key_manager_state = &(&state).into();

    let update_overall_delivery_status = domain::EventUpdate::OverallDeliveryStatusUpdate {
        is_overall_delivery_successful: true,
    };

    let initial_attempt_id = updated_event.initial_attempt_id.as_ref();
    let delivery_attempt = updated_event.delivery_attempt;

    if let Some((
        initial_attempt_id,
        enums::WebhookDeliveryAttempt::InitialAttempt
        | enums::WebhookDeliveryAttempt::AutomaticRetry,
    )) = initial_attempt_id.zip(delivery_attempt)
    {
        state
            .store
            .update_event_by_merchant_id_event_id(
                key_manager_state,
                merchant_id,
                initial_attempt_id.as_str(),
                update_overall_delivery_status,
                &merchant_key_store,
            )
            .await
            .change_context(errors::WebhooksFlowError::WebhookEventUpdationFailed)
            .attach_printable("Failed to update initial delivery attempt")?;
    }

    Ok(())
}

async fn handle_successful_delivery(
    state: SessionState,
    merchant_key_store: domain::MerchantKeyStore,
    updated_event: &domain::Event,
    merchant_id: &common_utils::id_type::MerchantId,
    process_tracker: Option<storage::ProcessTracker>,
    business_status: &'static str,
) -> CustomResult<(), errors::WebhooksFlowError> {
    update_overall_delivery_status_in_storage(
        state.clone(),
        merchant_key_store.clone(),
        merchant_id,
        updated_event,
    )
    .await?;

    increment_webhook_outgoing_received_count(merchant_id);

    match process_tracker {
        Some(process_tracker) => state
            .store
            .as_scheduler()
            .finish_process_with_business_status(process_tracker, business_status)
            .await
            .change_context(
                errors::WebhooksFlowError::OutgoingWebhookProcessTrackerTaskUpdateFailed,
            ),
        None => Ok(()),
    }
}

async fn handle_failed_delivery(
    _state: SessionState,
    merchant_id: &common_utils::id_type::MerchantId,
    delivery_attempt: enums::WebhookDeliveryAttempt,
    status_code: u16,
    log_message: &'static str,
    _schedule_webhook_retry: types::ScheduleWebhookRetry,
) -> CustomResult<(), errors::WebhooksFlowError> {
    utils::increment_webhook_outgoing_not_received_count(merchant_id);

    let error = report!(errors::WebhooksFlowError::NotReceivedByMerchant);
    logger::warn!(?error, ?delivery_attempt, status_code, %log_message);

    //TODO: add outgoing webhook retries support
    // if let ScheduleWebhookRetry::WithProcessTracker(process_tracker) = schedule_webhook_retry {
    //     // Schedule a retry attempt for webhook delivery
    //     outgoing_webhook_retry::retry_webhook_delivery_task(
    //         &*state.store,
    //         merchant_id,
    //         *process_tracker,
    //     )
    //     .await
    //     .change_context(errors::WebhooksFlowError::OutgoingWebhookRetrySchedulingFailed)?;
    // }

    Err(error)
}

impl ForeignFrom<&api::OutgoingWebhookContent> for storage::EventMetadata {
    fn foreign_from(content: &api::OutgoingWebhookContent) -> Self {
        match content {
            webhooks::OutgoingWebhookContent::PaymentDetails(payments_response) => Self::Payment {
                payment_id: payments_response.id.clone(),
            },
            webhooks::OutgoingWebhookContent::RefundDetails(refund_response) => Self::Refund {
                payment_id: refund_response.payment_id.clone(),
                refund_id: refund_response.id.clone(),
            },
            webhooks::OutgoingWebhookContent::DisputeDetails(dispute_response) => {
                //TODO: add support for dispute outgoing webhook
                todo!()
            }
            webhooks::OutgoingWebhookContent::MandateDetails(mandate_response) => Self::Mandate {
                payment_method_id: mandate_response.payment_method_id.clone(),
                mandate_id: mandate_response.mandate_id.clone(),
            },
            #[cfg(feature = "payouts")]
            webhooks::OutgoingWebhookContent::PayoutDetails(payout_response) => Self::Payout {
                payout_id: payout_response.payout_id.clone(),
            },
        }
    }
}

impl ForeignFrom<storage::EventMetadata> for outgoing_webhook_logs::OutgoingWebhookEventContent {
    fn foreign_from(event_metadata: storage::EventMetadata) -> Self {
        match event_metadata {
            diesel_models::EventMetadata::Payment { payment_id } => Self::Payment {
                payment_id,
                content: serde_json::Value::Null,
            },
            diesel_models::EventMetadata::Payout { payout_id } => Self::Payout {
                payout_id,
                content: serde_json::Value::Null,
            },
            diesel_models::EventMetadata::Refund {
                payment_id,
                refund_id,
            } => Self::Refund {
                payment_id,
                refund_id,
                content: serde_json::Value::Null,
            },
            diesel_models::EventMetadata::Dispute {
                payment_id,
                attempt_id,
                dispute_id,
            } => Self::Dispute {
                payment_id,
                attempt_id,
                dispute_id,
                content: serde_json::Value::Null,
            },
            diesel_models::EventMetadata::Mandate {
                payment_method_id,
                mandate_id,
            } => Self::Mandate {
                payment_method_id,
                mandate_id,
                content: serde_json::Value::Null,
            },
        }
    }
}

trait OutgoingWebhookResponseHandler {
    async fn handle_error_response(
        &self,
        state: SessionState,
        merchant_key_store: domain::MerchantKeyStore,
        merchant_id: &common_utils::id_type::MerchantId,
        event_id: &str,
        client_error: Report<errors::ApiClientError>,
    ) -> CustomResult<
        (domain::Event, Option<Report<errors::WebhooksFlowError>>),
        errors::WebhooksFlowError,
    >;

    async fn handle_success_response(
        &self,
        state: SessionState,
        merchant_key_store: domain::MerchantKeyStore,
        merchant_id: &common_utils::id_type::MerchantId,
        event_id: &str,
        process_tracker: Option<storage::ProcessTracker>,
        response: reqwest::Response,
    ) -> CustomResult<
        (domain::Event, Option<Report<errors::WebhooksFlowError>>),
        errors::WebhooksFlowError,
    >;
}

impl OutgoingWebhookResponseHandler for enums::WebhookDeliveryAttempt {
    async fn handle_error_response(
        &self,
        state: SessionState,
        merchant_key_store: domain::MerchantKeyStore,
        merchant_id: &common_utils::id_type::MerchantId,
        event_id: &str,
        client_error: Report<errors::ApiClientError>,
    ) -> CustomResult<
        (domain::Event, Option<Report<errors::WebhooksFlowError>>),
        errors::WebhooksFlowError,
    > {
        let schedule_webhook_retry = match self {
            Self::InitialAttempt | Self::ManualRetry => types::ScheduleWebhookRetry::NoSchedule,
            Self::AutomaticRetry => {
                // ScheduleWebhookRetry::WithProcessTracker(Box::new(process_tracker))
                todo!()
            }
        };

        api_client_error_handler(
            state,
            merchant_key_store,
            merchant_id,
            event_id,
            client_error,
            *self,
            schedule_webhook_retry,
        )
        .await
    }

    async fn handle_success_response(
        &self,
        state: SessionState,
        merchant_key_store: domain::MerchantKeyStore,
        merchant_id: &common_utils::id_type::MerchantId,
        event_id: &str,
        process_tracker: Option<storage::ProcessTracker>,
        response: reqwest::Response,
    ) -> CustomResult<
        (domain::Event, Option<Report<errors::WebhooksFlowError>>),
        errors::WebhooksFlowError,
    > {
        let status_code = response.status();
        let is_webhook_notified = status_code.is_success();
        let response_struct = types::WebhookResponse { response };
        let outgoing_webhook_response = response_struct
            .get_outgoing_webhook_response_content()
            .await;
        let updated_event = update_event_in_storage(
            state.clone(),
            is_webhook_notified,
            outgoing_webhook_response,
            merchant_key_store.clone(),
            merchant_id,
            event_id,
        )
        .await?;

        let webhook_action_handler = get_action_handler(*self);
        let result = if is_webhook_notified {
            webhook_action_handler
                .notified_action(
                    state,
                    merchant_key_store,
                    &updated_event,
                    merchant_id,
                    process_tracker,
                )
                .await
        } else {
            webhook_action_handler
                .not_notified_action(state, merchant_id, status_code.as_u16())
                .await
        };

        Ok((updated_event, result))
    }
}

#[async_trait::async_trait]
trait WebhookNotificationHandler: Send + Sync {
    async fn notified_action(
        &self,
        state: SessionState,
        merchant_key_store: domain::MerchantKeyStore,
        updated_event: &domain::Event,
        merchant_id: &common_utils::id_type::MerchantId,
        process_tracker: Option<storage::ProcessTracker>,
    ) -> Option<Report<errors::WebhooksFlowError>>;

    async fn not_notified_action(
        &self,
        state: SessionState,
        merchant_id: &common_utils::id_type::MerchantId,
        status_code: u16,
    ) -> Option<Report<errors::WebhooksFlowError>>;
}

struct InitialAttempt;
struct AutomaticRetry;
struct ManualRetry;

#[async_trait::async_trait]
impl WebhookNotificationHandler for InitialAttempt {
    async fn notified_action(
        &self,
        state: SessionState,
        merchant_key_store: domain::MerchantKeyStore,
        updated_event: &domain::Event,
        merchant_id: &common_utils::id_type::MerchantId,
        process_tracker: Option<storage::ProcessTracker>,
    ) -> Option<Report<errors::WebhooksFlowError>> {
        handle_successful_delivery(
            state,
            merchant_key_store,
            updated_event,
            merchant_id,
            process_tracker,
            business_status::INITIAL_DELIVERY_ATTEMPT_SUCCESSFUL,
        )
        .await
        .err()
        .map(|error: Report<errors::WebhooksFlowError>| report!(error))
    }

    async fn not_notified_action(
        &self,
        state: SessionState,
        merchant_id: &common_utils::id_type::MerchantId,
        status_code: u16,
    ) -> Option<Report<errors::WebhooksFlowError>> {
        handle_failed_delivery(
            state.clone(),
            merchant_id,
            enums::WebhookDeliveryAttempt::InitialAttempt,
            status_code,
            "Ignoring error when sending webhook to merchant",
            types::ScheduleWebhookRetry::NoSchedule,
        )
        .await
        .err()
        .map(|error| report!(error))
    }
}

#[async_trait::async_trait]
impl WebhookNotificationHandler for AutomaticRetry {
    async fn notified_action(
        &self,
        _state: SessionState,
        _merchant_key_store: domain::MerchantKeyStore,
        _updated_event: &domain::Event,
        _merchant_id: &common_utils::id_type::MerchantId,
        _process_tracker: Option<storage::ProcessTracker>,
    ) -> Option<Report<errors::WebhooksFlowError>> {
        todo!()
    }

    async fn not_notified_action(
        &self,
        _state: SessionState,
        _merchant_id: &common_utils::id_type::MerchantId,
        _status_code: u16,
    ) -> Option<Report<errors::WebhooksFlowError>> {
        todo!()
    }
}

#[async_trait::async_trait]
impl WebhookNotificationHandler for ManualRetry {
    async fn notified_action(
        &self,
        _state: SessionState,
        _merchant_key_store: domain::MerchantKeyStore,
        _updated_event: &domain::Event,
        merchant_id: &common_utils::id_type::MerchantId,
        _process_tracker: Option<storage::ProcessTracker>,
    ) -> Option<Report<errors::WebhooksFlowError>> {
        increment_webhook_outgoing_received_count(merchant_id);
        None
    }

    async fn not_notified_action(
        &self,
        state: SessionState,
        merchant_id: &common_utils::id_type::MerchantId,
        status_code: u16,
    ) -> Option<Report<errors::WebhooksFlowError>> {
        handle_failed_delivery(
            state.clone(),
            merchant_id,
            enums::WebhookDeliveryAttempt::ManualRetry,
            status_code,
            "Ignoring error when sending webhook to merchant",
            types::ScheduleWebhookRetry::NoSchedule,
        )
        .await
        .err()
        .map(|error| report!(error))
    }
}

fn get_action_handler(
    attempt: enums::WebhookDeliveryAttempt,
) -> Box<dyn WebhookNotificationHandler> {
    match attempt {
        enums::WebhookDeliveryAttempt::InitialAttempt => Box::new(InitialAttempt),
        enums::WebhookDeliveryAttempt::AutomaticRetry => Box::new(AutomaticRetry),
        enums::WebhookDeliveryAttempt::ManualRetry => Box::new(ManualRetry),
    }
}


// Function: is_permanent_card
// File: crates/router/src/types/storage/payment_method.rs
// Module: router

pub fn is_permanent_card(&self) -> bool


// Struct: StaxCaptureRequest
// File: crates/hyperswitch_connectors/src/connectors/stax/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct StaxCaptureRequest


// Struct: TrustpaymentsTokenizationRequestData
// File: crates/hyperswitch_connectors/src/connectors/trustpayments/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct TrustpaymentsTokenizationRequestData


// Struct: Shipping
// File: crates/router/src/compatibility/stripe/setup_intents/types.rs
// Module: router
// Implementations: 0

pub struct Shipping


// Function: create_recipient
// File: crates/router/src/core/payouts.rs
// Module: router

pub fn create_recipient(
    state: &SessionState,
    merchant_context: &domain::MerchantContext,
    connector_data: &api::ConnectorData,
    payout_data: &mut PayoutData,
) -> RouterResult<()>


// Struct: PaymentsTokenReference
// File: crates/diesel_models/src/payment_method.rs
// Module: diesel_models
// Implementations: 2
// Traits: std::ops::Deref, std::ops::DerefMut

pub struct PaymentsTokenReference


// Struct: AuthorizedResponse
// File: crates/hyperswitch_connectors/src/connectors/worldpay/response.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct AuthorizedResponse


// Trait: DatabaseStore
// File: crates/storage_impl/src/database/store.rs
// Module: storage_impl

pub trait DatabaseStore: Clone + Send + Sync


// Function: from_role_id_org_id_tenant_id
// File: crates/router/src/services/authorization/roles.rs
// Module: router

pub fn from_role_id_org_id_tenant_id(
        state: &SessionState,
        role_id: &str,
        org_id: &id_type::OrganizationId,
        tenant_id: &id_type::TenantId,
    ) -> CustomResult<Self, errors::StorageError>


// Function: connector_retrieve
// File: crates/router/src/routes/admin.rs
// Module: router

pub fn connector_retrieve(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<common_utils::id_type::MerchantConnectorAccountId>,
) -> HttpResponse


// Struct: IatapayRefundRequest
// File: crates/hyperswitch_connectors/src/connectors/iatapay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct IatapayRefundRequest


// File: crates/hyperswitch_connectors/src/connectors/signifyd/transformers/auth.rs
// Module: hyperswitch_connectors
// Public structs: 1

use error_stack;
use hyperswitch_domain_models::router_data::ConnectorAuthType;
use hyperswitch_interfaces::errors::ConnectorError;
use masking::Secret;

pub struct SignifydAuthType {
    pub api_key: Secret<String>,
}

impl TryFrom<&ConnectorAuthType> for SignifydAuthType {
    type Error = error_stack::Report<ConnectorError>;
    fn try_from(auth_type: &ConnectorAuthType) -> Result<Self, Self::Error> {
        match auth_type {
            ConnectorAuthType::HeaderKey { api_key } => Ok(Self {
                api_key: api_key.to_owned(),
            }),
            _ => Err(ConnectorError::FailedToObtainAuthType.into()),
        }
    }
}


// Function: create_pm_collect_db_entry
// File: crates/router/src/core/payment_methods.rs
// Module: router

pub fn create_pm_collect_db_entry(
    state: &SessionState,
    merchant_context: &domain::MerchantContext,
    pm_collect_link_data: &PaymentMethodCollectLinkData,
    return_url: Option<String>,
) -> RouterResult<PaymentMethodCollectLink>


// Function: get_sdk_event_filters
// File: crates/router/src/analytics.rs
// Module: router

pub fn get_sdk_event_filters(
        state: web::Data<AppState>,
        req: actix_web::HttpRequest,
        json_payload: web::Json<GetSdkEventFiltersRequest>,
    ) -> impl Responder


// Struct: PartnerReferralThirdPartyDetails
// File: crates/router/src/types/api/connector_onboarding/paypal.rs
// Module: router
// Implementations: 0

pub struct PartnerReferralThirdPartyDetails


// Struct: CardMandateRequest
// File: crates/hyperswitch_connectors/src/connectors/paypal/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct CardMandateRequest


// Struct: VaultFingerprintResponse
// File: crates/router/src/types/payment_methods.rs
// Module: router
// Implementations: 0

pub struct VaultFingerprintResponse


// Function: get_updated_feature_metadata
// File: crates/hyperswitch_domain_models/src/payments.rs
// Module: hyperswitch_domain_models

pub fn get_updated_feature_metadata(
        &self,
    ) -> CustomResult<Option<FeatureMetadata>, errors::api_error_response::ApiErrorResponse>


// Function: dummy_connector_refund
// File: crates/router/src/routes/dummy_connector.rs
// Module: router

pub fn dummy_connector_refund(
    state: web::Data<app::AppState>,
    req: actix_web::HttpRequest,
    json_payload: web::Json<types::DummyConnectorRefundRequest>,
    path: web::Path<common_utils::id_type::PaymentId>,
) -> impl actix_web::Responder


// Implementation: impl webhooks::IncomingWebhook for for Mollie
// File: crates/hyperswitch_connectors/src/connectors/mollie.rs
// Module: hyperswitch_connectors
// Methods: 3 total (0 public)

impl webhooks::IncomingWebhook for for Mollie


// Struct: AuthenticationEligibilityRequest
// File: crates/api_models/src/authentication.rs
// Module: api_models
// Implementations: 2
// Traits: ApiEventMetric

pub struct AuthenticationEligibilityRequest


// Struct: MaskedHeaders
// File: crates/api_models/src/admin.rs
// Module: api_models
// Implementations: 1

pub struct MaskedHeaders


// Function: migrate_payment_method
// File: crates/payment_methods/src/core/migration/payment_methods.rs
// Module: payment_methods

pub fn migrate_payment_method(
    state: &state::PaymentMethodsState,
    req: pm_api::PaymentMethodMigrate,
    merchant_id: &id_type::MerchantId,
    merchant_context: &merchant_context::MerchantContext,
    controller: &dyn PaymentMethodsController,
) -> CustomResult<ApplicationResponse<pm_api::PaymentMethodMigrateResponse>, errors::ApiErrorResponse>


// Struct: RefundResponse
// File: crates/hyperswitch_connectors/src/connectors/bluesnap/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct RefundResponse


// Function: validate_payment_method_update
// File: crates/router/src/core/payment_methods/cards.rs
// Module: router

pub fn validate_payment_method_update(
    card_updation_obj: CardDetailUpdate,
    existing_card_data: api::CardDetailFromLocker,
) -> bool


// Implementation: impl api::PaymentSession for for Adyenplatform
// File: crates/hyperswitch_connectors/src/connectors/adyenplatform.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentSession for for Adyenplatform


// Implementation: impl TrustpaymentsSettleStatus
// File: crates/hyperswitch_connectors/src/connectors/trustpayments/transformers.rs
// Module: hyperswitch_connectors
// Methods: 1 total (1 public)

impl TrustpaymentsSettleStatus


// Implementation: impl ConnectorSpecifications for for Mifinity
// File: crates/hyperswitch_connectors/src/connectors/mifinity.rs
// Module: hyperswitch_connectors
// Methods: 3 total (0 public)

impl ConnectorSpecifications for for Mifinity


// Struct: AuthenticationDataWithUser
// File: crates/router/src/services/authentication.rs
// Module: router
// Implementations: 0

pub struct AuthenticationDataWithUser


// Struct: BillingConnectorPaymentsSyncResponseData
// File: crates/router/src/core/webhooks/recovery_incoming.rs
// Module: router
// Implementations: 1

pub struct BillingConnectorPaymentsSyncResponseData


// Struct: PaymentAddress
// File: crates/router/src/types/domain/address.rs
// Module: router
// Implementations: 1
// Traits: behaviour::Conversion

pub struct PaymentAddress


// Implementation: impl api::RefundExecute for for Nmi
// File: crates/hyperswitch_connectors/src/connectors/nmi.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::RefundExecute for for Nmi


// Function: get_payment_method_id
// File: crates/api_models/src/webhooks.rs
// Module: api_models

pub fn get_payment_method_id(&self) -> Option<String>


// File: crates/hyperswitch_connectors/src/connectors/hyperwallet/transformers.rs
// Module: hyperswitch_connectors
// Public structs: 8

use common_enums::enums;
use common_utils::types::StringMinorUnit;
use hyperswitch_domain_models::{
    payment_method_data::PaymentMethodData,
    router_data::{ConnectorAuthType, RouterData},
    router_flow_types::refunds::{Execute, RSync},
    router_request_types::ResponseId,
    router_response_types::{PaymentsResponseData, RefundsResponseData},
    types::{PaymentsAuthorizeRouterData, RefundsRouterData},
};
use hyperswitch_interfaces::errors;
use masking::Secret;
use serde::{Deserialize, Serialize};

use crate::types::{RefundsResponseRouterData, ResponseRouterData};

//TODO: Fill the struct with respective fields
pub struct HyperwalletRouterData<T> {
    pub amount: StringMinorUnit, // The type of amount that a connector accepts, for example, String, i64, f64, etc.
    pub router_data: T,
}

impl<T> From<(StringMinorUnit, T)> for HyperwalletRouterData<T> {
    fn from((amount, item): (StringMinorUnit, T)) -> Self {
        //Todo :  use utils to convert the amount to the type of amount that a connector accepts
        Self {
            amount,
            router_data: item,
        }
    }
}

//TODO: Fill the struct with respective fields
#[derive(Default, Debug, Serialize, PartialEq)]
pub struct HyperwalletPaymentsRequest {
    amount: StringMinorUnit,
    card: HyperwalletCard,
}

#[derive(Default, Debug, Serialize, Eq, PartialEq)]
pub struct HyperwalletCard {
    number: cards::CardNumber,
    expiry_month: Secret<String>,
    expiry_year: Secret<String>,
    cvc: Secret<String>,
    complete: bool,
}

impl TryFrom<&HyperwalletRouterData<&PaymentsAuthorizeRouterData>> for HyperwalletPaymentsRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: &HyperwalletRouterData<&PaymentsAuthorizeRouterData>,
    ) -> Result<Self, Self::Error> {
        match item.router_data.request.payment_method_data.clone() {
            PaymentMethodData::Card(_) => Err(errors::ConnectorError::NotImplemented(
                "Card payment method not implemented".to_string(),
            )
            .into()),
            _ => Err(errors::ConnectorError::NotImplemented("Payment method".to_string()).into()),
        }
    }
}

//TODO: Fill the struct with respective fields
// Auth Struct
pub struct HyperwalletAuthType {
    pub(super) api_key: Secret<String>,
}

impl TryFrom<&ConnectorAuthType> for HyperwalletAuthType {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(auth_type: &ConnectorAuthType) -> Result<Self, Self::Error> {
        match auth_type {
            ConnectorAuthType::HeaderKey { api_key } => Ok(Self {
                api_key: api_key.to_owned(),
            }),
            _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()),
        }
    }
}
// PaymentsResponse
//TODO: Append the remaining status flags
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum HyperwalletPaymentStatus {
    Succeeded,
    Failed,
    #[default]
    Processing,
}

impl From<HyperwalletPaymentStatus> for common_enums::AttemptStatus {
    fn from(item: HyperwalletPaymentStatus) -> Self {
        match item {
            HyperwalletPaymentStatus::Succeeded => Self::Charged,
            HyperwalletPaymentStatus::Failed => Self::Failure,
            HyperwalletPaymentStatus::Processing => Self::Authorizing,
        }
    }
}

//TODO: Fill the struct with respective fields
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct HyperwalletPaymentsResponse {
    status: HyperwalletPaymentStatus,
    id: String,
}

impl<F, T> TryFrom<ResponseRouterData<F, HyperwalletPaymentsResponse, T, PaymentsResponseData>>
    for RouterData<F, T, PaymentsResponseData>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: ResponseRouterData<F, HyperwalletPaymentsResponse, T, PaymentsResponseData>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            status: common_enums::AttemptStatus::from(item.response.status),
            response: Ok(PaymentsResponseData::TransactionResponse {
                resource_id: ResponseId::ConnectorTransactionId(item.response.id),
                redirection_data: Box::new(None),
                mandate_reference: Box::new(None),
                connector_metadata: None,
                network_txn_id: None,
                connector_response_reference_id: None,
                incremental_authorization_allowed: None,
                charges: None,
            }),
            ..item.data
        })
    }
}

//TODO: Fill the struct with respective fields
// REFUND :
// Type definition for RefundRequest
#[derive(Default, Debug, Serialize)]
pub struct HyperwalletRefundRequest {
    pub amount: StringMinorUnit,
}

impl<F> TryFrom<&HyperwalletRouterData<&RefundsRouterData<F>>> for HyperwalletRefundRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(item: &HyperwalletRouterData<&RefundsRouterData<F>>) -> Result<Self, Self::Error> {
        Ok(Self {
            amount: item.amount.to_owned(),
        })
    }
}

// Type definition for Refund Response

#[allow(dead_code)]
#[derive(Debug, Copy, Serialize, Default, Deserialize, Clone)]
pub enum RefundStatus {
    Succeeded,
    Failed,
    #[default]
    Processing,
}

impl From<RefundStatus> for enums::RefundStatus {
    fn from(item: RefundStatus) -> Self {
        match item {
            RefundStatus::Succeeded => Self::Success,
            RefundStatus::Failed => Self::Failure,
            RefundStatus::Processing => Self::Pending,
            //TODO: Review mapping
        }
    }
}

//TODO: Fill the struct with respective fields
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct RefundResponse {
    id: String,
    status: RefundStatus,
}

impl TryFrom<RefundsResponseRouterData<Execute, RefundResponse>> for RefundsRouterData<Execute> {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: RefundsResponseRouterData<Execute, RefundResponse>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            response: Ok(RefundsResponseData {
                connector_refund_id: item.response.id.to_string(),
                refund_status: enums::RefundStatus::from(item.response.status),
            }),
            ..item.data
        })
    }
}

impl TryFrom<RefundsResponseRouterData<RSync, RefundResponse>> for RefundsRouterData<RSync> {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: RefundsResponseRouterData<RSync, RefundResponse>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            response: Ok(RefundsResponseData {
                connector_refund_id: item.response.id.to_string(),
                refund_status: enums::RefundStatus::from(item.response.status),
            }),
            ..item.data
        })
    }
}

//TODO: Fill the struct with respective fields
#[derive(Default, Debug, Serialize, Deserialize, PartialEq)]
pub struct HyperwalletErrorResponse {
    pub status_code: u16,
    pub code: String,
    pub message: String,
    pub reason: Option<String>,
    pub network_advice_code: Option<String>,
    pub network_decline_code: Option<String>,
    pub network_error_message: Option<String>,
}


// Struct: PlaidBankAccountCredentialsBacs
// File: crates/pm_auth/src/connector/plaid/transformers.rs
// Module: pm_auth
// Implementations: 0

pub struct PlaidBankAccountCredentialsBacs


// Implementation: impl api::PaymentCapture for for Loonio
// File: crates/hyperswitch_connectors/src/connectors/loonio.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentCapture for for Loonio


// Struct: BankOfAmericaCaptureRequest
// File: crates/hyperswitch_connectors/src/connectors/bankofamerica/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct BankOfAmericaCaptureRequest


// Implementation: impl api::MandateSetup for for Iatapay
// File: crates/hyperswitch_connectors/src/connectors/iatapay.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::MandateSetup for for Iatapay


// Function: check_role_in_blacklist
// File: crates/router/src/services/authentication/blacklist.rs
// Module: router

pub fn check_role_in_blacklist<A: SessionStateInfo>(
    state: &A,
    role_id: &str,
    token_expiry: u64,
) -> RouterResult<bool>


// Struct: UpdateRoleRequest
// File: crates/api_models/src/user_role/role.rs
// Module: api_models
// Implementations: 0

pub struct UpdateRoleRequest


// Function: get_user_agent
// File: crates/common_types/src/payments.rs
// Module: common_types

// Documentation: Get the User Agent

pub fn get_user_agent(&self) -> Option<String>


// Implementation: impl ReverseLookupNew
// File: crates/diesel_models/src/query/reverse_lookup.rs
// Module: diesel_models
// Methods: 2 total (0 public)

impl ReverseLookupNew


// Function: payments_list
// File: crates/openapi/src/routes/payments.rs
// Module: openapi

pub fn payments_list()


// Struct: RoutingAlgorithmId
// File: crates/api_models/src/routing.rs
// Module: api_models
// Implementations: 0

pub struct RoutingAlgorithmId


        //         updated_by,
        //         net_amount: None,
        //         authentication_type: None,
        //         error_message: None,
        //         payment_method_id: None,
        //         browser_info: None,
        //         payment_token: None,
        //         error_code: None,
        //         connector_metadata: None,
        //         payment_method_data: None,
        //         payment_experience: None,
        //         straight_through_algorithm: None,
        //         preprocessing_step_id: None,
        //         error_reason: None,
        //         connector_response_reference_id: None,
        //         multiple_capture_count: None,
        //         surcharge_amount: None,
        //         tax_amount: None,
        //         amount_capturable: None,
        //         merchant_connector_id: None,
        //         authentication_data: None,
        //         encoded_data: None,
        //         unified_code: None,
        //         unified_message: None,
        //         external_three_ds_authentication_attempted: None,
        //         authentication_connector: None,
        //         authentication_id: None,
        //         fingerprint_id: None,
        //         payment_method_billing_address_id: None,
        //         charge_id: None,
        //         client_source: None,
        //         client_version: None,
        //         customer_acceptance: None,
        //         card_network: None,
        //     },
        //     PaymentAttemptUpdate::RejectUpdate {
        //         status,
        //         error_code,
        //         error_message,
        //         updated_by,
        //     } => Self {
        //         status: Some(status),
        //         modified_at: common_utils::date_time::now(),
        //         error_code,
        //         error_message,
        //         updated_by,
        //         net_amount: None,
        //         authentication_type: None,
        //         payment_method_id: None,
        //         cancellation_reason: None,
        //         browser_info: None,
        //         payment_token: None,
        //         connector_metadata: None,
        //         payment_method_data: None,
        //         payment_experience: None,
        //         straight_through_algorithm: None,
        //         preprocessing_step_id: None,
        //         error_reason: None,
        //         connector_response_reference_id: None,
        //         multiple_capture_count: None,
        //         surcharge_amount: None,
        //         tax_amount: None,
        //         amount_capturable: None,
        //         merchant_connector_id: None,
        //         authentication_data: None,
        //         encoded_data: None,
        //         unified_code: None,
        //         unified_message: None,
        //         external_three_ds_authentication_attempted: None,
        //         authentication_connector: None,
        //         authentication_id: None,
        //         fingerprint_id: None,
        //         payment_method_billing_address_id: None,
        //         charge_id: None,
        //         client_source: None,
        //         client_version: None,
        //         customer_acceptance: None,
        //         card_network: None,
        //     },
        //     PaymentAttemptUpdate::BlocklistUpdate {
        //         status,
        //         error_code,
        //         error_message,
        //         updated_by,
        //     } => Self {
        //         status: Some(status),
        //         modified_at: common_utils::date_time::now(),
        //         error_code,
        //         error_message,
        //         updated_by,
        //         merchant_connector_id: Some(None),
        //         net_amount: None,
        //         authentication_type: None,
        //         payment_method_id: None,
        //         cancellation_reason: None,
        //         browser_info: None,
        //         payment_token: None,
        //         connector_metadata: None,
        //         payment_method_data: None,
        //         payment_experience: None,
        //         straight_through_algorithm: None,
        //         preprocessing_step_id: None,
        //         error_reason: None,
        //         connector_response_reference_id: None,
        //         multiple_capture_count: None,
        //         surcharge_amount: None,
        //         tax_amount: None,
        //         amount_capturable: None,
        //         authentication_data: None,
        //         encoded_data: None,
        //         unified_code: None,
        //         unified_message: None,
        //         external_three_ds_authentication_attempted: None,
        //         authentication_connector: None,
        //         authentication_id: None,
        //         fingerprint_id: None,
        //         payment_method_billing_address_id: None,
        //         charge_id: None,
        //         client_source: None,
        //         client_version: None,
        //         customer_acceptance: None,
        //         card_network: None,
        //     },
        //     PaymentAttemptUpdate::ConnectorMandateDetailUpdate {
        //         connector_mandate_detail,
        // updated_by,
        //     } => Self {
        //         payment_method_id: None,
        //         modified_at: common_utils::date_time::now(),
        //         updated_by,
        //         amount: None,
        //         net_amount: None,
        //         currency: None,
        //         status: None,
        //         connector_transaction_id: None,
        //         amount_to_capture: None,
        //         connector: None,
        //         authentication_type: None,
        //         payment_method: None,
        //         error_message: None,
        //         cancellation_reason: None,
        //         mandate_id: None,
        //         browser_info: None,
        //         payment_token: None,
        //         error_code: None,
        //         connector_metadata: None,
        //         payment_method_data: None,
        //         payment_method_type: None,
        //         payment_experience: None,
        //         business_sub_label: None,
        //         straight_through_algorithm: None,
        //         preprocessing_step_id: None,
        //         error_reason: None,
        //         capture_method: None,
        //         connector_response_reference_id: None,
        //         multiple_capture_count: None,
        //         surcharge_amount: None,
        //         tax_amount: None,
        //         amount_capturable: None,
        //         merchant_connector_id: None,
        //         authentication_data: None,
        //         encoded_data: None,
        //         unified_code: None,
        //         unified_message: None,
        //         external_three_ds_authentication_attempted: None,
        //         authentication_connector: None,
        //         authentication_id: None,
        //         fingerprint_id: None,
        //         payment_method_billing_address_id: None,
        //         charge_id: None,
        //         client_source: None,
        //         client_version: None,
        //         customer_acceptance: None,
        //         card_network: None,
        //         shipping_cost: None,
        //         order_tax_amount: None,
        //         processor_transaction_data: None,
        //         connector_mandate_detail,
        //     },
        //     PaymentAttemptUpdate::ConnectorMandateDetailUpdate {
        //         payment_method_id,
        //         updated_by,
        //     } => Self {
        //         payment_method_id,
        //         modified_at: common_utils::date_time::now(),
        //         updated_by,
        //         net_amount: None,
        //         status: None,
        //         authentication_type: None,
        //         error_message: None,
        //         cancellation_reason: None,
        //         browser_info: None,
        //         payment_token: None,
        //         error_code: None,
        //         connector_metadata: None,
        //         payment_method_data: None,
        //         payment_experience: None,
        //         straight_through_algorithm: None,
        //         preprocessing_step_id: None,
        //         error_reason: None,
        //         connector_response_reference_id: None,
        //         multiple_capture_count: None,
        //         surcharge_amount: None,
        //         tax_amount: None,
        //         amount_capturable: None,
        //         merchant_connector_id: None,
        //         authentication_data: None,
        //         encoded_data: None,
        //         unified_code: None,
        //         unified_message: None,
        //         external_three_ds_authentication_attempted: None,
        //         authentication_connector: None,
        //         authentication_id: None,
        //         fingerprint_id: None,
        //         payment_method_billing_address_id: None,
        //         charge_id: None,
        //         client_source: None,
        //         client_version: None,
        //         customer_acceptance: None,
        //         card_network: None,
        //     },
        //     PaymentAttemptUpdate::ResponseUpdate {
        //         status,
        //         connector,
        //         connector_transaction_id,
        //         authentication_type,
        //         payment_method_id,
        //         mandate_id,
        //         connector_metadata,
        //         payment_token,
        //         error_code,
        //         error_message,
        //         error_reason,
        //         connector_response_reference_id,
        //         amount_capturable,
        //         updated_by,
        //         authentication_data,
        //         encoded_data,
        //         unified_code,
        //         unified_message,
        //         payment_method_data,
        //         charge_id,
        //     } => Self {
        //         status: Some(status),
        //         authentication_type,
        //         payment_method_id,
        //         modified_at: common_utils::date_time::now(),
        //         connector_metadata,
        //         error_code,
        //         error_message,
        //         payment_token,
        //         error_reason,
        //         connector_response_reference_id,
        //         amount_capturable,
        //         updated_by,
        //         authentication_data,
        //         encoded_data,
        //         unified_code,
        //         unified_message,
        //         payment_method_data,
        //         charge_id,
        //         net_amount: None,
        //         cancellation_reason: None,
        //         browser_info: None,
        //         payment_experience: None,
        //         straight_through_algorithm: None,
        //         preprocessing_step_id: None,
        //         multiple_capture_count: None,
        //         surcharge_amount: None,
        //         tax_amount: None,
        //         merchant_connector_id: None,
        //         external_three_ds_authentication_attempted: None,
        //         authentication_connector: None,
        //         authentication_id: None,
        //         fingerprint_id: None,
        //         payment_method_billing_address_id: None,
        //         client_source: None,
        //         client_version: None,
        //         customer_acceptance: None,
        //         card_network: None,
        //     },
        //     PaymentAttemptUpdate::ErrorUpdate {
        //         connector,
        //         status,
        //         error_code,
        //         error_message,
        //         error_reason,
        //         amount_capturable,
        //         updated_by,
        //         unified_code,
        //         unified_message,
        //         connector_transaction_id,
        //         payment_method_data,
        //         authentication_type,
        //     } => Self {
        //         status: Some(status),
        //         error_message,
        //         error_code,
        //         modified_at: common_utils::date_time::now(),
        //         error_reason,
        //         amount_capturable,
        //         updated_by,
        //         unified_code,
        //         unified_message,
        //         payment_method_data,
        //         authentication_type,
        //         net_amount: None,
        //         payment_method_id: None,
        //         cancellation_reason: None,
        //         browser_info: None,
        //         payment_token: None,
        //         connector_metadata: None,
        //         payment_experience: None,
        //         straight_through_algorithm: None,
        //         preprocessing_step_id: None,
        //         connector_response_reference_id: None,
        //         multiple_capture_count: None,
        //         surcharge_amount: None,
        //         tax_amount: None,
        //         merchant_connector_id: None,
        //         authentication_data: None,
        //         encoded_data: None,
        //         external_three_ds_authentication_attempted: None,
        //         authentication_connector: None,
        //         authentication_id: None,
        //         fingerprint_id: None,
        //         payment_method_billing_address_id: None,
        //         charge_id: None,
        //         client_source: None,
        //         client_version: None,
        //         customer_acceptance: None,
        //         card_network: None,
        //     },
        //     PaymentAttemptUpdate::StatusUpdate { status, updated_by } => Self {
        //         status: Some(status),
        //         modified_at: common_utils::date_time::now(),
        //         updated_by,
        //         net_amount: None,
        //         authentication_type: None,
        //         error_message: None,
        //         payment_method_id: None,
        //         cancellation_reason: None,
        //         browser_info: None,
        //         payment_token: None,
        //         error_code: None,
        //         connector_metadata: None,
        //         payment_method_data: None,
        //         payment_experience: None,
        //         straight_through_algorithm: None,
        //         preprocessing_step_id: None,
        //         error_reason: None,
        //         connector_response_reference_id: None,
        //         multiple_capture_count: None,
        //         surcharge_amount: None,
        //         tax_amount: None,
        //         amount_capturable: None,
        //         merchant_connector_id: None,
        //         authentication_data: None,
        //         encoded_data: None,
        //         unified_code: None,
        //         unified_message: None,
        //         external_three_ds_authentication_attempted: None,
        //         authentication_connector: None,
        //         authentication_id: None,
        //         fingerprint_id: None,
        //         payment_method_billing_address_id: None,
        //         charge_id: None,
        //         client_source: None,
        //         client_version: None,
        //         customer_acceptance: None,
        //         card_network: None,
        //     },
        //     PaymentAttemptUpdate::UpdateTrackers {
        //         payment_token,
        //         connector,
        //         straight_through_algorithm,
        //         amount_capturable,
        //         surcharge_amount,
        //         tax_amount,
        //         updated_by,
        //         merchant_connector_id,
        //     } => Self {
        //         payment_token,
        //         modified_at: common_utils::date_time::now(),
        //         straight_through_algorithm,
        //         amount_capturable,
        //         surcharge_amount,
        //         tax_amount,
        //         updated_by,
        //         merchant_connector_id: merchant_connector_id.map(Some),
        //         net_amount: None,
        //         status: None,
        //         authentication_type: None,
        //         error_message: None,
        //         payment_method_id: None,
        //         cancellation_reason: None,
        //         browser_info: None,
        //         error_code: None,
        //         connector_metadata: None,
        //         payment_method_data: None,
        //         payment_experience: None,
        //         preprocessing_step_id: None,
        //         error_reason: None,
        //         connector_response_reference_id: None,
        //         multiple_capture_count: None,
        //         authentication_data: None,
        //         encoded_data: None,
        //         unified_code: None,
        //         unified_message: None,
        //         external_three_ds_authentication_attempted: None,
        //         authentication_connector: None,
        //         authentication_id: None,
        //         fingerprint_id: None,
        //         payment_method_billing_address_id: None,
        //         charge_id: None,
        //         client_source: None,
        //         client_version: None,
        //         customer_acceptance: None,
        //         card_network: None,
        //     },
        //     PaymentAttemptUpdate::UnresolvedResponseUpdate {
        //         status,
        //         connector,
        //         connector_transaction_id,
        //         payment_method_id,
        //         error_code,
        //         error_message,
        //         error_reason,
        //         connector_response_reference_id,
        //         updated_by,
        //     } => Self {
        //         status: Some(status),
        //         payment_method_id,
        //         modified_at: common_utils::date_time::now(),
        //         error_code,
        //         error_message,
        //         error_reason,
        //         connector_response_reference_id,
        //         updated_by,
        //         net_amount: None,
        //         authentication_type: None,
        //         cancellation_reason: None,
        //         browser_info: None,
        //         payment_token: None,
        //         connector_metadata: None,
        //         payment_method_data: None,
        //         payment_experience: None,
        //         straight_through_algorithm: None,
        //         preprocessing_step_id: None,
        //         multiple_capture_count: None,
        //         surcharge_amount: None,
        //         tax_amount: None,
        //         amount_capturable: None,
        //         merchant_connector_id: None,
        //         authentication_data: None,
        //         encoded_data: None,
        //         unified_code: None,
        //         unified_message: None,
        //         external_three_ds_authentication_attempted: None,
        //         authentication_connector: None,
        //         authentication_id: None,
        //         fingerprint_id: None,
        //         payment_method_billing_address_id: None,
        //         charge_id: None,
        //         client_source: None,
        //         client_version: None,
        //         customer_acceptance: None,
        //         card_network: None,
        //     },
        //     PaymentAttemptUpdate::PreprocessingUpdate {
        //         status,
        //         payment_method_id,
        //         connector_metadata,
        //         preprocessing_step_id,
        //         connector_transaction_id,
        //         connector_response_reference_id,
        //         updated_by,
        //     } => Self {
        //         status: Some(status),
        //         payment_method_id,
        //         modified_at: common_utils::date_time::now(),
        //         connector_metadata,
        //         preprocessing_step_id,
        //         connector_response_reference_id,
        //         updated_by,
        //         net_amount: None,
        //         authentication_type: None,
        //         error_message: None,
        //         cancellation_reason: None,
        //         browser_info: None,
        //         payment_token: None,
        //         error_code: None,
        //         payment_method_data: None,
        //         payment_experience: None,
        //         straight_through_algorithm: None,
        //         error_reason: None,
        //         multiple_capture_count: None,
        //         surcharge_amount: None,
        //         tax_amount: None,
        //         amount_capturable: None,
        //         merchant_connector_id: None,
        //         authentication_data: None,
        //         encoded_data: None,
        //         unified_code: None,
        //         unified_message: None,
        //         external_three_ds_authentication_attempted: None,
        //         authentication_connector: None,
        //         authentication_id: None,
        //         fingerprint_id: None,
        //         payment_method_billing_address_id: None,
        //         charge_id: None,
        //         client_source: None,
        //         client_version: None,
        //         customer_acceptance: None,
        //         card_network: None,
        //     },
        //     PaymentAttemptUpdate::CaptureUpdate {
        //         multiple_capture_count,
        //         updated_by,
        //         amount_to_capture,
        //     } => Self {
        //         multiple_capture_count,
        //         modified_at: common_utils::date_time::now(),
        //         updated_by,
        //         net_amount: None,
        //         status: None,
        //         authentication_type: None,
        //         error_message: None,
        //         payment_method_id: None,
        //         cancellation_reason: None,
        //         browser_info: None,
        //         payment_token: None,
        //         error_code: None,
        //         connector_metadata: None,
        //         payment_method_data: None,
        //         payment_experience: None,
        //         straight_through_algorithm: None,
        //         preprocessing_step_id: None,
        //         error_reason: None,
        //         connector_response_reference_id: None,
        //         surcharge_amount: None,
        //         tax_amount: None,
        //         amount_capturable: None,
        //         merchant_connector_id: None,
        //         authentication_data: None,
        //         encoded_data: None,
        //         unified_code: None,
        //         unified_message: None,
        //         external_three_ds_authentication_attempted: None,
        //         authentication_connector: None,
        //         authentication_id: None,
        //         fingerprint_id: None,
        //         payment_method_billing_address_id: None,
        //         charge_id: None,
        //         client_source: None,
        //         client_version: None,
        //         customer_acceptance: None,
        //         card_network: None,
        //     },
        //     PaymentAttemptUpdate::AmountToCaptureUpdate {
        //         status,
        //         amount_capturable,
        //         updated_by,
        //     } => Self {
        //         status: Some(status),
        //         modified_at: common_utils::date_time::now(),
        //         amount_capturable: Some(amount_capturable),
        //         updated_by,
        //         net_amount: None,
        //         authentication_type: None,
        //         error_message: None,
        //         payment_method_id: None,
        //         cancellation_reason: None,
        //         browser_info: None,
        //         payment_token: None,
        //         error_code: None,
        //         connector_metadata: None,
        //         payment_method_data: None,
        //         payment_experience: None,
        //         straight_through_algorithm: None,
        //         preprocessing_step_id: None,
        //         error_reason: None,
        //         connector_response_reference_id: None,
        //         multiple_capture_count: None,
        //         surcharge_amount: None,
        //         tax_amount: None,
        //         merchant_connector_id: None,
        //         authentication_data: None,
        //         encoded_data: None,
        //         unified_code: None,
        //         unified_message: None,
        //         external_three_ds_authentication_attempted: None,
        //         authentication_connector: None,
        //         authentication_id: None,
        //         fingerprint_id: None,
        //         payment_method_billing_address_id: None,
        //         charge_id: None,
        //         client_source: None,
        //         client_version: None,
        //         customer_acceptance: None,
        //         card_network: None,
        //     },
        //     PaymentAttemptUpdate::ConnectorResponse {
        //         authentication_data,
        //         encoded_data,
        //         connector_transaction_id,
        //         connector,
        //         updated_by,
        //         charge_id,
        //     } => Self {
        //         authentication_data,
        //         encoded_data,
        //         modified_at: common_utils::date_time::now(),
        //         updated_by,
        //         charge_id,
        //         net_amount: None,
        //         status: None,
        //         authentication_type: None,
        //         error_message: None,
        //         payment_method_id: None,
        //         cancellation_reason: None,
        //         browser_info: None,
        //         payment_token: None,
        //         error_code: None,
        //         connector_metadata: None,
        //         payment_method_data: None,
        //         payment_experience: None,
        //         straight_through_algorithm: None,
        //         preprocessing_step_id: None,
        //         error_reason: None,
        //         connector_response_reference_id: None,
        //         multiple_capture_count: None,
        //         surcharge_amount: None,
        //         tax_amount: None,
        //         amount_capturable: None,
        //         merchant_connector_id: None,
        //         unified_code: None,
        //         unified_message: None,
        //         external_three_ds_authentication_attempted: None,
        //         authentication_connector: None,
        //         authentication_id: None,
        //         fingerprint_id: None,
        //         payment_method_billing_address_id: None,
        //         client_source: None,
        //         client_version: None,
        //         customer_acceptance: None,
        //         card_network: None,
        //     },
        //     PaymentAttemptUpdate::IncrementalAuthorizationAmountUpdate {
        //         amount,
        //         amount_capturable,
        //     } => Self {
        //         modified_at: common_utils::date_time::now(),
        //         amount_capturable: Some(amount_capturable),
        //         net_amount: None,
        //         status: None,
        //         authentication_type: None,
        //         error_message: None,
        //         payment_method_id: None,
        //         cancellation_reason: None,
        //         browser_info: None,
        //         payment_token: None,
        //         error_code: None,
        //         connector_metadata: None,
        //         payment_method_data: None,
        //         payment_experience: None,
        //         straight_through_algorithm: None,
        //         preprocessing_step_id: None,
        //         error_reason: None,
        //         connector_response_reference_id: None,
        //         multiple_capture_count: None,
        //         surcharge_amount: None,
        //         tax_amount: None,
        //         updated_by: String::default(),
        //         merchant_connector_id: None,
        //         authentication_data: None,
        //         encoded_data: None,
        //         unified_code: None,
        //         unified_message: None,
        //         external_three_ds_authentication_attempted: None,
        //         authentication_connector: None,
        //         authentication_id: None,
        //         fingerprint_id: None,
        //         payment_method_billing_address_id: None,
        //         charge_id: None,
        //         client_source: None,
        //         client_version: None,
        //         customer_acceptance: None,
        //         card_network: None,
        //     },
        //     PaymentAttemptUpdate::AuthenticationUpdate {
        //         status,
        //         external_three_ds_authentication_attempted,
        //         authentication_connector,
        //         authentication_id,
        //         updated_by,
        //     } => Self {
        //         status: Some(status),
        //         modified_at: common_utils::date_time::now(),
        //         external_three_ds_authentication_attempted,
        //         authentication_connector,
        //         authentication_id,
        //         updated_by,
        //         net_amount: None,
        //         authentication_type: None,
        //         error_message: None,
        //         payment_method_id: None,
        //         cancellation_reason: None,
        //         browser_info: None,
        //         payment_token: None,
        //         error_code: None,
        //         connector_metadata: None,
        //         payment_method_data: None,
        //         payment_experience: None,
        //         straight_through_algorithm: None,
        //         preprocessing_step_id: None,
        //         error_reason: None,
        //         connector_response_reference_id: None,
        //         multiple_capture_count: None,
        //         surcharge_amount: None,
        //         tax_amount: None,
        //         amount_capturable: None,
        //         merchant_connector_id: None,
        //         authentication_data: None,
        //         encoded_data: None,
        //         unified_code: None,
        //         unified_message: None,
        //         fingerprint_id: None,
        //         payment_method_billing_address_id: None,
        //         charge_id: None,
        //         client_source: None,
        //         client_version: None,
        //         customer_acceptance: None,
        //         card_network: None,
        //     },
        //     PaymentAttemptUpdate::ManualUpdate {
        //         status,
        //         error_code,
        //         error_message,
        //         error_reason,
        //         updated_by,
        //         unified_code,
        //         unified_message,
        //         connector_transaction_id,
        //     } => Self {
        //         status,
        //         error_code: error_code.map(Some),
        //         modified_at: common_utils::date_time::now(),
        //         error_message: error_message.map(Some),
        //         error_reason: error_reason.map(Some),
        //         updated_by,
        //         unified_code: unified_code.map(Some),
        //         unified_message: unified_message.map(Some),
        //         net_amount: None,
        //         authentication_type: None,
        //         payment_method_id: None,
        //         cancellation_reason: None,
        //         browser_info: None,
        //         payment_token: None,
        //         connector_metadata: None,
        //         payment_method_data: None,
        //         payment_experience: None,
        //         straight_through_algorithm: None,
        //         preprocessing_step_id: None,
        //         connector_response_reference_id: None,
        //         multiple_capture_count: None,
        //         surcharge_amount: None,
        //         tax_amount: None,
        //         amount_capturable: None,
        //         merchant_connector_id: None,
        //         authentication_data: None,
        //         encoded_data: None,
        //         external_three_ds_authentication_attempted: None,
        //         authentication_connector: None,
        //         authentication_id: None,
        //         fingerprint_id: None,
        //         payment_method_billing_address_id: None,
        //         charge_id: None,
        //         client_source: None,
        //         client_version: None,
        //         customer_acceptance: None,
        //         card_network: None,
        //     },
        // }
    }
}

#[cfg(feature = "v1")]
impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
    fn from(payment_attempt_update: PaymentAttemptUpdate) -> Self {
        match payment_attempt_update {
            PaymentAttemptUpdate::Update {
                amount,
                currency,
                status,
                // connector_transaction_id,
                authentication_type,
                payment_method,
                payment_token,
                payment_method_data,
                payment_method_type,
                payment_experience,
                business_sub_label,
                amount_to_capture,
                capture_method,
                surcharge_amount,
                tax_amount,
                fingerprint_id,
                updated_by,
                payment_method_billing_address_id,
                network_transaction_id,
            } => Self {
                amount: Some(amount),
                currency: Some(currency),
                status: Some(status),
                // connector_transaction_id,
                authentication_type,
                payment_method,
                payment_token,
                modified_at: common_utils::date_time::now(),
                payment_method_data,
                payment_method_type,
                payment_experience,
                business_sub_label,
                amount_to_capture,
                capture_method,
                surcharge_amount,
                tax_amount,
                fingerprint_id,
                payment_method_billing_address_id,
                updated_by,
                net_amount: None,
                connector_transaction_id: None,
                connector: None,
                error_message: None,
                payment_method_id: None,
                cancellation_reason: None,
                mandate_id: None,
                browser_info: None,
                error_code: None,
                connector_metadata: None,
                straight_through_algorithm: None,
                preprocessing_step_id: None,
                error_reason: None,
                connector_response_reference_id: None,
                multiple_capture_count: None,
                amount_capturable: None,
                merchant_connector_id: None,
                authentication_data: None,
                encoded_data: None,
                unified_code: None,
                unified_message: None,
                external_three_ds_authentication_attempted: None,
                authentication_connector: None,
                authentication_id: None,
                client_source: None,
                client_version: None,
                customer_acceptance: None,
                card_network: None,
                shipping_cost: None,
                capture_before: None,
                extended_authorization_applied: None,
                order_tax_amount: None,
                processor_transaction_data: None,
                connector_mandate_detail: None,
                card_discovery: None,
                charges: None,
                issuer_error_code: None,
                issuer_error_message: None,
                setup_future_usage_applied: None,
                routing_approach: None,
                connector_request_reference_id: None,
                network_transaction_id,
                is_overcapture_enabled: None,
                network_details: None,
                is_stored_credential: None,
                request_extended_authorization: None,
            },
            PaymentAttemptUpdate::AuthenticationTypeUpdate {
                authentication_type,
                updated_by,
            } => Self {
                authentication_type: Some(authentication_type),
                modified_at: common_utils::date_time::now(),
                updated_by,
                amount: None,
                net_amount: None,
                currency: None,
                status: None,
                connector_transaction_id: None,
                amount_to_capture: None,
                connector: None,
                payment_method: None,
                error_message: None,
                payment_method_id: None,
                cancellation_reason: None,
                mandate_id: None,
                browser_info: None,
                payment_token: None,
                error_code: None,
                connector_metadata: None,
                payment_method_data: None,
                payment_method_type: None,
                payment_experience: None,
                business_sub_label: None,
                straight_through_algorithm: None,
                preprocessing_step_id: None,
                error_reason: None,
                capture_method: None,
                connector_response_reference_id: None,
                multiple_capture_count: None,
                surcharge_amount: None,
                tax_amount: None,
                amount_capturable: None,
                merchant_connector_id: None,
                authentication_data: None,
                encoded_data: None,
                unified_code: None,
                unified_message: None,
                external_three_ds_authentication_attempted: None,
                authentication_connector: None,
                authentication_id: None,
                fingerprint_id: None,
                payment_method_billing_address_id: None,
                client_source: None,
                client_version: None,
                customer_acceptance: None,
                card_network: None,
                shipping_cost: None,
                order_tax_amount: None,
                capture_before: None,
                extended_authorization_applied: None,
                processor_transaction_data: None,
                connector_mandate_detail: None,
                card_discovery: None,
                charges: None,
                issuer_error_code: None,
                issuer_error_message: None,
                setup_future_usage_applied: None,
                routing_approach: None,
                connector_request_reference_id: None,
                network_transaction_id: None,
                is_overcapture_enabled: None,
                network_details: None,
                is_stored_credential: None,
                request_extended_authorization: None,
            },
            PaymentAttemptUpdate::ConfirmUpdate {
                amount,
                currency,
                authentication_type,
                capture_method,
                status,
                payment_method,
                browser_info,
                connector,
                payment_token,
                payment_method_data,
                payment_method_type,
                payment_experience,
                business_sub_label,
                straight_through_algorithm,
                error_code,
                error_message,
                updated_by,
                merchant_connector_id,
                surcharge_amount,
                tax_amount,
                external_three_ds_authentication_attempted,
                authentication_connector,
                authentication_id,
                payment_method_billing_address_id,
                fingerprint_id,
                payment_method_id,
                client_source,
                client_version,
                customer_acceptance,
                shipping_cost,
                order_tax_amount,
                connector_mandate_detail,
                card_discovery,
                routing_approach,
                connector_request_reference_id,
                network_transaction_id,
                is_stored_credential,
                request_extended_authorization,
            } => Self {
                amount: Some(amount),
                currency: Some(currency),
                authentication_type,
                status: Some(status),
                payment_method,
                modified_at: common_utils::date_time::now(),
                browser_info,
                connector: connector.map(Some),
                payment_token,
                payment_method_data,
                payment_method_type,
                payment_experience,
                business_sub_label,
                straight_through_algorithm,
                error_code,
                error_message,
                amount_capturable: None,
                updated_by,
                merchant_connector_id: merchant_connector_id.map(Some),
                surcharge_amount,
                tax_amount,
                external_three_ds_authentication_attempted,
                authentication_connector,
                authentication_id,
                payment_method_billing_address_id,
                fingerprint_id,
                payment_method_id,
                capture_method,
                client_source,
                client_version,
                customer_acceptance,
                net_amount: None,
                connector_transaction_id: None,
                amount_to_capture: None,
                cancellation_reason: None,
                mandate_id: None,
                connector_metadata: None,
                preprocessing_step_id: None,
                error_reason: None,
                connector_response_reference_id: None,
                multiple_capture_count: None,
                authentication_data: None,
                encoded_data: None,
                unified_code: None,
                unified_message: None,
                card_network: None,
                shipping_cost,
                order_tax_amount,
                capture_before: None,
                extended_authorization_applied: None,
                processor_transaction_data: None,
                connector_mandate_detail,
                card_discovery,
                charges: None,
                issuer_error_code: None,
                issuer_error_message: None,
                setup_future_usage_applied: None,
                routing_approach,
                connector_request_reference_id,
                network_transaction_id,
                is_overcapture_enabled: None,
                network_details: None,
                is_stored_credential,
                request_extended_authorization,
            },
            PaymentAttemptUpdate::VoidUpdate {
                status,
                cancellation_reason,
                updated_by,
            } => Self {
                status: Some(status),
                cancellation_reason,
                modified_at: common_utils::date_time::now(),
                updated_by,
                amount: None,
                net_amount: None,
                currency: None,
                connector_transaction_id: None,
                amount_to_capture: None,
                connector: None,
                authentication_type: None,
                payment_method: None,
                error_message: None,
                payment_method_id: None,
                mandate_id: None,
                browser_info: None,
                payment_token: None,
                error_code: None,
                connector_metadata: None,
                payment_method_data: None,
                payment_method_type: None,
                payment_experience: None,
                business_sub_label: None,
                straight_through_algorithm: None,
                preprocessing_step_id: None,
                error_reason: None,
                capture_method: None,
                connector_response_reference_id: None,
                multiple_capture_count: None,
                surcharge_amount: None,


        enums::PaymentMethodType::Credit,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: Some(
                api_models::feature_matrix::PaymentMethodSpecificFeatures::Card({
                    api_models::feature_matrix::CardSpecificFeatures {
                        three_ds: common_enums::FeatureStatus::Supported,
                        no_three_ds: common_enums::FeatureStatus::Supported,
                        supported_card_networks: supported_card_network.clone(),
                    }
                }),
            ),
        },
    );

    nmi_supported_payment_methods.add(
        enums::PaymentMethod::Card,
        enums::PaymentMethodType::Debit,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: Some(
                api_models::feature_matrix::PaymentMethodSpecificFeatures::Card({
                    api_models::feature_matrix::CardSpecificFeatures {
                        three_ds: common_enums::FeatureStatus::Supported,
                        no_three_ds: common_enums::FeatureStatus::Supported,
                        supported_card_networks: supported_card_network,
                    }
                }),
            ),
        },
    );

    nmi_supported_payment_methods.add(
        enums::PaymentMethod::Wallet,
        enums::PaymentMethodType::GooglePay,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );

    nmi_supported_payment_methods.add(
        enums::PaymentMethod::Wallet,
        enums::PaymentMethodType::ApplePay,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods,
            specific_features: None,
        },
    );

    nmi_supported_payment_methods
});

static NMI_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
    display_name: "NMI",
    description: "NMI is a global leader in embedded payments, powering more than $200 billion in payment volumes every year.",
    connector_type: enums::HyperswitchConnectorCategory::PaymentGateway,
    integration_status: enums::ConnectorIntegrationStatus::Live,
};

static NMI_SUPPORTED_WEBHOOK_FLOWS: [enums::EventClass; 2] =
    [enums::EventClass::Payments, enums::EventClass::Refunds];

impl ConnectorSpecifications for Nmi {
    fn get_connector_about(&self) -> Option<&'static ConnectorInfo> {
        Some(&NMI_CONNECTOR_INFO)
    }

    fn get_supported_payment_methods(&self) -> Option<&'static SupportedPaymentMethods> {
        Some(&*NMI_SUPPORTED_PAYMENT_METHODS)
    }

    fn get_supported_webhook_flows(&self) -> Option<&'static [enums::EventClass]> {
        Some(&NMI_SUPPORTED_WEBHOOK_FLOWS)
    }
}


// Struct: Przelewy24MethodData
// File: crates/hyperswitch_connectors/src/connectors/mollie/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct Przelewy24MethodData


// Function: files_delete
// File: crates/router/src/routes/files.rs
// Module: router

pub fn files_delete(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<String>,
) -> HttpResponse


// Struct: NordeaOAuthRequest
// File: crates/hyperswitch_connectors/src/connectors/nordea/requests.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct NordeaOAuthRequest


// Function: skip_locker_call_and_migrate_payment_method
// File: crates/payment_methods/src/core/migration/payment_methods.rs
// Module: payment_methods

pub fn skip_locker_call_and_migrate_payment_method(
    _state: state::PaymentMethodsState,
    _req: &pm_api::PaymentMethodMigrate,
    _merchant_id: id_type::MerchantId,
    _merchant_context: &merchant_context::MerchantContext,
    _card: pm_api::CardDetailFromLocker,
) -> CustomResult<ApplicationResponse<pm_api::PaymentMethodResponse>, errors::ApiErrorResponse>


// Implementation: impl Dispute
// File: crates/diesel_models/src/query/dispute.rs
// Module: diesel_models
// Methods: 4 total (0 public)

impl Dispute