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

impl api::MandateSetup for for Phonepe


// Struct: DestinationChargeRefund
// File: crates/hyperswitch_domain_models/src/router_request_types.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct DestinationChargeRefund


// Struct: FiuuPaymentRedirectResponse
// File: crates/hyperswitch_connectors/src/connectors/fiuu/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct FiuuPaymentRedirectResponse


// Struct: GlobepayPaymentsResponse
// File: crates/hyperswitch_connectors/src/connectors/globepay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct GlobepayPaymentsResponse


// Struct: Links
// File: crates/hyperswitch_connectors/src/connectors/checkout/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct Links


// File: crates/router/src/routes/user.rs
// Module: router
// Public functions: 50

pub mod theme;

use actix_web::{web, HttpRequest, HttpResponse};
#[cfg(feature = "dummy_connector")]
use api_models::user::sample_data::SampleDataRequest;
use api_models::{
    errors::types::ApiErrorResponse,
    user::{self as user_api},
};
use common_enums::TokenPurpose;
use common_utils::errors::ReportSwitchExt;
use router_env::Flow;

use super::AppState;
use crate::{
    core::{api_locking, user as user_core},
    services::{
        api,
        authentication::{self as auth},
        authorization::permissions::Permission,
    },
    utils::user::dashboard_metadata::{parse_string_to_enums, set_ip_address_if_required},
};

pub async fn get_user_details(state: web::Data<AppState>, req: HttpRequest) -> HttpResponse {
    let flow = Flow::GetUserDetails;
    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        (),
        |state, user, _, _| user_core::get_user_details(state, user),
        &auth::DashboardNoPermissionAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "email")]
pub async fn user_signup_with_merchant_id(
    state: web::Data<AppState>,
    http_req: HttpRequest,
    json_payload: web::Json<user_api::SignUpWithMerchantIdRequest>,
    query: web::Query<user_api::AuthIdAndThemeIdQueryParam>,
) -> HttpResponse {
    let flow = Flow::UserSignUpWithMerchantId;
    let req_payload = json_payload.into_inner();
    let query_params = query.into_inner();
    Box::pin(api::server_wrap(
        flow.clone(),
        state,
        &http_req,
        req_payload.clone(),
        |state, _, req_body, _| {
            user_core::signup_with_merchant_id(
                state,
                req_body,
                query_params.auth_id.clone(),
                query_params.theme_id.clone(),
            )
        },
        &auth::AdminApiAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn user_signup(
    state: web::Data<AppState>,
    http_req: HttpRequest,
    json_payload: web::Json<user_api::SignUpRequest>,
) -> HttpResponse {
    let flow = Flow::UserSignUp;
    let req_payload = json_payload.into_inner();
    Box::pin(api::server_wrap(
        flow.clone(),
        state,
        &http_req,
        req_payload.clone(),
        |state, _: (), req_body, _| async move {
            user_core::signup_token_only_flow(state, req_body).await
        },
        &auth::NoAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn user_signin(
    state: web::Data<AppState>,
    http_req: HttpRequest,
    json_payload: web::Json<user_api::SignInRequest>,
) -> HttpResponse {
    let flow = Flow::UserSignIn;
    let req_payload = json_payload.into_inner();
    Box::pin(api::server_wrap(
        flow.clone(),
        state,
        &http_req,
        req_payload.clone(),
        |state, _: (), req_body, _| async move {
            user_core::signin_token_only_flow(state, req_body).await
        },
        &auth::NoAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "email")]
pub async fn user_connect_account(
    state: web::Data<AppState>,
    http_req: HttpRequest,
    json_payload: web::Json<user_api::ConnectAccountRequest>,
    query: web::Query<user_api::AuthIdAndThemeIdQueryParam>,
) -> HttpResponse {
    let flow = Flow::UserConnectAccount;
    let req_payload = json_payload.into_inner();
    let query_params = query.into_inner();
    Box::pin(api::server_wrap(
        flow.clone(),
        state,
        &http_req,
        req_payload.clone(),
        |state, _: (), req_body, _| {
            user_core::connect_account(
                state,
                req_body,
                query_params.auth_id.clone(),
                query_params.theme_id.clone(),
            )
        },
        &auth::NoAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn signout(state: web::Data<AppState>, http_req: HttpRequest) -> HttpResponse {
    let flow = Flow::Signout;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &http_req,
        (),
        |state, user, _, _| user_core::signout(state, user),
        &auth::AnyPurposeOrLoginTokenAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn change_password(
    state: web::Data<AppState>,
    http_req: HttpRequest,
    json_payload: web::Json<user_api::ChangePasswordRequest>,
) -> HttpResponse {
    let flow = Flow::ChangePassword;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &http_req,
        json_payload.into_inner(),
        |state, user, req, _| user_core::change_password(state, req, user),
        &auth::DashboardNoPermissionAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn set_dashboard_metadata(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<user_api::dashboard_metadata::SetMetaDataRequest>,
) -> HttpResponse {
    let flow = Flow::SetDashboardMetadata;
    let mut payload = json_payload.into_inner();

    if let Err(e) = ReportSwitchExt::<(), ApiErrorResponse>::switch(set_ip_address_if_required(
        &mut payload,
        req.headers(),
    )) {
        return api::log_and_return_error_response(e);
    }

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        payload,
        user_core::dashboard_metadata::set_metadata,
        &auth::JWTAuth {
            permission: Permission::ProfileAccountWrite,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn get_multiple_dashboard_metadata(
    state: web::Data<AppState>,
    req: HttpRequest,
    query: web::Query<user_api::dashboard_metadata::GetMultipleMetaDataRequest>,
) -> HttpResponse {
    let flow = Flow::GetMultipleDashboardMetadata;
    let payload = match ReportSwitchExt::<_, ApiErrorResponse>::switch(parse_string_to_enums(
        query.into_inner().keys,
    )) {
        Ok(payload) => payload,
        Err(e) => {
            return api::log_and_return_error_response(e);
        }
    };
    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        payload,
        user_core::dashboard_metadata::get_multiple_metadata,
        &auth::DashboardNoPermissionAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn internal_user_signup(
    state: web::Data<AppState>,
    http_req: HttpRequest,
    json_payload: web::Json<user_api::CreateInternalUserRequest>,
) -> HttpResponse {
    let flow = Flow::InternalUserSignup;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &http_req,
        json_payload.into_inner(),
        |state, _, req, _| user_core::create_internal_user(state, req),
        &auth::AdminApiAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn create_tenant_user(
    state: web::Data<AppState>,
    http_req: HttpRequest,
    json_payload: web::Json<user_api::CreateTenantUserRequest>,
) -> HttpResponse {
    let flow = Flow::TenantUserCreate;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &http_req,
        json_payload.into_inner(),
        |state, _, req, _| user_core::create_tenant_user(state, req),
        &auth::AdminApiAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "v1")]
pub async fn create_platform(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<user_api::PlatformAccountCreateRequest>,
) -> HttpResponse {
    let flow = Flow::CreatePlatformAccount;
    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        json_payload.into_inner(),
        |state, user: auth::UserFromToken, json_payload, _| {
            user_core::create_platform_account(state, user, json_payload)
        },
        &auth::JWTAuth {
            permission: Permission::OrganizationAccountWrite,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "v1")]
pub async fn user_org_create(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<user_api::UserOrgMerchantCreateRequest>,
) -> HttpResponse {
    let flow = Flow::UserOrgMerchantCreate;
    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        json_payload.into_inner(),
        |state, _auth: auth::UserFromToken, json_payload, _| {
            user_core::create_org_merchant_for_user(state, json_payload)
        },
        &auth::JWTAuth {
            permission: Permission::TenantAccountWrite,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn user_merchant_account_create(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<user_api::UserMerchantCreate>,
) -> HttpResponse {
    let flow = Flow::UserMerchantAccountCreate;
    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        json_payload.into_inner(),
        |state, auth: auth::UserFromToken, json_payload, _| {
            user_core::create_merchant_account(state, auth, json_payload)
        },
        &auth::JWTAuth {
            permission: Permission::OrganizationAccountWrite,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(all(feature = "dummy_connector", feature = "v1"))]
pub async fn generate_sample_data(
    state: web::Data<AppState>,
    http_req: HttpRequest,
    payload: web::Json<SampleDataRequest>,
) -> impl actix_web::Responder {
    use crate::core::user::sample_data;

    let flow = Flow::GenerateSampleData;
    Box::pin(api::server_wrap(
        flow,
        state,
        &http_req,
        payload.into_inner(),
        sample_data::generate_sample_data_for_user,
        &auth::JWTAuth {
            permission: Permission::MerchantPaymentWrite,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(all(feature = "dummy_connector", feature = "v1"))]
pub async fn delete_sample_data(
    state: web::Data<AppState>,
    http_req: HttpRequest,
    payload: web::Json<SampleDataRequest>,
) -> impl actix_web::Responder {
    use crate::core::user::sample_data;

    let flow = Flow::DeleteSampleData;
    Box::pin(api::server_wrap(
        flow,
        state,
        &http_req,
        payload.into_inner(),
        sample_data::delete_sample_data_for_user,
        &auth::JWTAuth {
            permission: Permission::MerchantAccountWrite,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn list_user_roles_details(
    state: web::Data<AppState>,
    req: HttpRequest,
    payload: web::Json<user_api::GetUserRoleDetailsRequest>,
) -> HttpResponse {
    let flow = Flow::GetUserRoleDetails;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        payload.into_inner(),
        user_core::list_user_roles_details,
        &auth::JWTAuth {
            permission: Permission::ProfileUserRead,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn rotate_password(
    state: web::Data<AppState>,
    req: HttpRequest,
    payload: web::Json<user_api::RotatePasswordRequest>,
) -> HttpResponse {
    let flow = Flow::RotatePassword;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        payload.into_inner(),
        user_core::rotate_password,
        &auth::SinglePurposeJWTAuth(TokenPurpose::ForceSetPassword),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "email")]
pub async fn forgot_password(
    state: web::Data<AppState>,
    req: HttpRequest,
    payload: web::Json<user_api::ForgotPasswordRequest>,
    query: web::Query<user_api::AuthIdAndThemeIdQueryParam>,
) -> HttpResponse {
    let flow = Flow::ForgotPassword;
    let query_params = query.into_inner();
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        payload.into_inner(),
        |state, _: (), payload, _| {
            user_core::forgot_password(
                state,
                payload,
                query_params.auth_id.clone(),
                query_params.theme_id.clone(),
            )
        },
        &auth::NoAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "email")]
pub async fn reset_password(
    state: web::Data<AppState>,
    req: HttpRequest,
    payload: web::Json<user_api::ResetPasswordRequest>,
) -> HttpResponse {
    let flow = Flow::ResetPassword;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        payload.into_inner(),
        |state, user, payload, _| user_core::reset_password_token_only_flow(state, user, payload),
        &auth::SinglePurposeJWTAuth(TokenPurpose::ResetPassword),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn invite_multiple_user(
    state: web::Data<AppState>,
    req: HttpRequest,
    payload: web::Json<Vec<user_api::InviteUserRequest>>,
    auth_id_query_param: web::Query<user_api::AuthIdAndThemeIdQueryParam>,
) -> HttpResponse {
    let flow = Flow::InviteMultipleUser;
    let auth_id = auth_id_query_param.into_inner().auth_id;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        payload.into_inner(),
        |state, user, payload, req_state| {
            user_core::invite_multiple_user(state, user, payload, req_state, auth_id.clone())
        },
        &auth::JWTAuth {
            permission: Permission::ProfileUserWrite,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "email")]
pub async fn resend_invite(
    state: web::Data<AppState>,
    req: HttpRequest,
    payload: web::Json<user_api::ReInviteUserRequest>,
    query: web::Query<user_api::AuthIdAndThemeIdQueryParam>,
) -> HttpResponse {
    let flow = Flow::ReInviteUser;
    let auth_id = query.into_inner().auth_id;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        payload.into_inner(),
        |state, user, req_payload, _| {
            user_core::resend_invite(state, user, req_payload, auth_id.clone())
        },
        &auth::JWTAuth {
            permission: Permission::ProfileUserWrite,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "email")]
pub async fn accept_invite_from_email(
    state: web::Data<AppState>,
    req: HttpRequest,
    payload: web::Json<user_api::AcceptInviteFromEmailRequest>,
) -> HttpResponse {
    let flow = Flow::AcceptInviteFromEmail;
    Box::pin(api::server_wrap(
        flow.clone(),
        state,
        &req,
        payload.into_inner(),
        |state, user, req_payload, _| {
            user_core::accept_invite_from_email_token_only_flow(state, user, req_payload)
        },
        &auth::SinglePurposeJWTAuth(TokenPurpose::AcceptInvitationFromEmail),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "email")]
pub async fn verify_email(
    state: web::Data<AppState>,
    http_req: HttpRequest,
    json_payload: web::Json<user_api::VerifyEmailRequest>,
) -> HttpResponse {
    let flow = Flow::VerifyEmail;
    Box::pin(api::server_wrap(
        flow.clone(),
        state,
        &http_req,
        json_payload.into_inner(),
        |state, user, req_payload, _| {
            user_core::verify_email_token_only_flow(state, user, req_payload)
        },
        &auth::SinglePurposeJWTAuth(TokenPurpose::VerifyEmail),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "email")]
pub async fn verify_email_request(
    state: web::Data<AppState>,
    http_req: HttpRequest,
    json_payload: web::Json<user_api::SendVerifyEmailRequest>,
    query: web::Query<user_api::AuthIdAndThemeIdQueryParam>,
) -> HttpResponse {
    let flow = Flow::VerifyEmailRequest;
    let query_params = query.into_inner();
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &http_req,
        json_payload.into_inner(),
        |state, _: (), req_body, _| {
            user_core::send_verification_mail(
                state,
                req_body,
                query_params.auth_id.clone(),
                query_params.theme_id.clone(),
            )
        },
        &auth::NoAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn update_user_account_details(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<user_api::UpdateUserAccountDetailsRequest>,
) -> HttpResponse {
    let flow = Flow::UpdateUserAccountDetails;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        json_payload.into_inner(),
        user_core::update_user_details,
        &auth::DashboardNoPermissionAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "email")]
pub async fn user_from_email(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<user_api::UserFromEmailRequest>,
) -> HttpResponse {
    let flow = Flow::UserFromEmail;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        json_payload.into_inner(),
        |state, _: (), req_body, _| user_core::user_from_email(state, req_body),
        &auth::NoAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn totp_begin(state: web::Data<AppState>, req: HttpRequest) -> HttpResponse {
    let flow = Flow::TotpBegin;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        (),
        |state, user, _, _| user_core::begin_totp(state, user),
        &auth::SinglePurposeJWTAuth(TokenPurpose::TOTP),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn totp_reset(state: web::Data<AppState>, req: HttpRequest) -> HttpResponse {
    let flow = Flow::TotpReset;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        (),
        |state, user, _, _| user_core::reset_totp(state, user),
        &auth::DashboardNoPermissionAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn totp_verify(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<user_api::VerifyTotpRequest>,
) -> HttpResponse {
    let flow = Flow::TotpVerify;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        json_payload.into_inner(),
        |state, user, req_body, _| user_core::verify_totp(state, user, req_body),
        &auth::SinglePurposeOrLoginTokenAuth(TokenPurpose::TOTP),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn verify_recovery_code(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<user_api::VerifyRecoveryCodeRequest>,
) -> HttpResponse {
    let flow = Flow::RecoveryCodeVerify;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        json_payload.into_inner(),
        |state, user, req_body, _| user_core::verify_recovery_code(state, user, req_body),
        &auth::SinglePurposeOrLoginTokenAuth(TokenPurpose::TOTP),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn totp_update(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<user_api::VerifyTotpRequest>,
) -> HttpResponse {
    let flow = Flow::TotpUpdate;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        json_payload.into_inner(),
        |state, user, req_body, _| user_core::update_totp(state, user, req_body),
        &auth::SinglePurposeOrLoginTokenAuth(TokenPurpose::TOTP),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn generate_recovery_codes(state: web::Data<AppState>, req: HttpRequest) -> HttpResponse {
    let flow = Flow::RecoveryCodesGenerate;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        (),
        |state, user, _, _| user_core::generate_recovery_codes(state, user),
        &auth::SinglePurposeOrLoginTokenAuth(TokenPurpose::TOTP),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn terminate_two_factor_auth(
    state: web::Data<AppState>,
    req: HttpRequest,
    query: web::Query<user_api::SkipTwoFactorAuthQueryParam>,
) -> HttpResponse {
    let flow = Flow::TerminateTwoFactorAuth;
    let skip_two_factor_auth = query.into_inner().skip_two_factor_auth.unwrap_or(false);

    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        (),
        |state, user, _, _| user_core::terminate_two_factor_auth(state, user, skip_two_factor_auth),
        &auth::SinglePurposeJWTAuth(TokenPurpose::TOTP),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn check_two_factor_auth_status(
    state: web::Data<AppState>,
    req: HttpRequest,
) -> HttpResponse {
    let flow = Flow::TwoFactorAuthStatus;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        (),
        |state, user, _, _| user_core::check_two_factor_auth_status(state, user),
        &auth::DashboardNoPermissionAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn check_two_factor_auth_status_with_attempts(
    state: web::Data<AppState>,
    req: HttpRequest,
) -> HttpResponse {
    let flow = Flow::TwoFactorAuthStatus;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        (),
        |state, user, _, _| user_core::check_two_factor_auth_status_with_attempts(state, user),
        &auth::SinglePurposeOrLoginTokenAuth(TokenPurpose::TOTP),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "v1")]
pub async fn get_sso_auth_url(
    state: web::Data<AppState>,
    req: HttpRequest,
    query: web::Query<user_api::GetSsoAuthUrlRequest>,
) -> HttpResponse {
    let flow = Flow::GetSsoAuthUrl;
    let payload = query.into_inner();
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        payload,
        |state, _: (), req, _| user_core::get_sso_auth_url(state, req),
        &auth::NoAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn sso_sign(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<user_api::SsoSignInRequest>,
) -> HttpResponse {
    let flow = Flow::SignInWithSso;
    let payload = json_payload.into_inner();
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        payload,
        |state, user: Option<auth::UserFromSinglePurposeToken>, payload, _| {
            user_core::sso_sign(state, payload, user)
        },
        auth::auth_type(
            &auth::NoAuth,
            &auth::SinglePurposeJWTAuth(TokenPurpose::SSO),
            req.headers(),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn create_user_authentication_method(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<user_api::CreateUserAuthenticationMethodRequest>,
) -> HttpResponse {
    let flow = Flow::CreateUserAuthenticationMethod;

    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        json_payload.into_inner(),
        |state, _, req_body, _| user_core::create_user_authentication_method(state, req_body),
        &auth::AdminApiAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn update_user_authentication_method(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<user_api::UpdateUserAuthenticationMethodRequest>,
) -> HttpResponse {
    let flow = Flow::UpdateUserAuthenticationMethod;

    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        json_payload.into_inner(),
        |state, _, req_body, _| user_core::update_user_authentication_method(state, req_body),
        &auth::AdminApiAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn list_user_authentication_methods(
    state: web::Data<AppState>,
    req: HttpRequest,
    query: web::Query<user_api::GetUserAuthenticationMethodsRequest>,
) -> HttpResponse {
    let flow = Flow::ListUserAuthenticationMethods;

    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        query.into_inner(),
        |state, _: (), req, _| user_core::list_user_authentication_methods(state, req),
        &auth::NoAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn terminate_auth_select(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<user_api::AuthSelectRequest>,
) -> HttpResponse {
    let flow = Flow::AuthSelect;

    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        json_payload.into_inner(),
        |state, user, req, _| user_core::terminate_auth_select(state, user, req),
        &auth::SinglePurposeJWTAuth(TokenPurpose::AuthSelect),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn transfer_user_key(
    state: web::Data<AppState>,
    req: HttpRequest,
    payload: web::Json<user_api::UserKeyTransferRequest>,
) -> HttpResponse {
    let flow = Flow::UserTransferKey;

    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        payload.into_inner(),
        |state, _, req, _| user_core::transfer_user_key_store_keymanager(state, req),
        &auth::AdminApiAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn list_orgs_for_user(state: web::Data<AppState>, req: HttpRequest) -> HttpResponse {
    let flow = Flow::ListOrgForUser;

    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        (),
        |state, user_from_token, _, _| user_core::list_orgs_for_user(state, user_from_token),
        &auth::DashboardNoPermissionAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn list_merchants_for_user_in_org(
    state: web::Data<AppState>,
    req: HttpRequest,
) -> HttpResponse {
    let flow = Flow::ListMerchantsForUserInOrg;

    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        (),
        |state, user_from_token, _, _| {
            user_core::list_merchants_for_user_in_org(state, user_from_token)
        },
        &auth::DashboardNoPermissionAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn list_profiles_for_user_in_org_and_merchant(
    state: web::Data<AppState>,
    req: HttpRequest,
) -> HttpResponse {
    let flow = Flow::ListProfileForUserInOrgAndMerchant;

    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        (),
        |state, user_from_token, _, _| {
            user_core::list_profiles_for_user_in_org_and_merchant_account(state, user_from_token)
        },
        &auth::DashboardNoPermissionAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn switch_org_for_user(
    state: web::Data<AppState>,
    http_req: HttpRequest,
    json_payload: web::Json<user_api::SwitchOrganizationRequest>,
) -> HttpResponse {
    let flow = Flow::SwitchOrg;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &http_req,
        json_payload.into_inner(),
        |state, user, req, _| user_core::switch_org_for_user(state, req, user),
        &auth::DashboardNoPermissionAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn switch_merchant_for_user_in_org(
    state: web::Data<AppState>,
    http_req: HttpRequest,
    json_payload: web::Json<user_api::SwitchMerchantRequest>,
) -> HttpResponse {
    let flow = Flow::SwitchMerchantV2;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &http_req,
        json_payload.into_inner(),
        |state, user, req, _| user_core::switch_merchant_for_user_in_org(state, req, user),
        &auth::DashboardNoPermissionAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn switch_profile_for_user_in_org_and_merchant(
    state: web::Data<AppState>,
    http_req: HttpRequest,
    json_payload: web::Json<user_api::SwitchProfileRequest>,
) -> HttpResponse {
    let flow = Flow::SwitchProfile;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &http_req,
        json_payload.into_inner(),
        |state, user, req, _| {
            user_core::switch_profile_for_user_in_org_and_merchant(state, req, user)
        },
        &auth::DashboardNoPermissionAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "v1")]
pub async fn clone_connector(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<user_api::CloneConnectorRequest>,
) -> HttpResponse {
    let flow = Flow::CloneConnector;

    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        json_payload.into_inner(),
        |state, _: auth::UserFromToken, req, _| user_core::clone_connector(state, req),
        &auth::JWTAuth {
            permission: Permission::MerchantInternalConnectorWrite,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


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

pub struct OrderRequestAmount


// Implementation: impl Payment for for Riskified
// File: crates/hyperswitch_connectors/src/connectors/riskified.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl Payment for for Riskified


// Function: payment_get
// File: crates/external_services/src/grpc_client/unified_connector_service.rs
// Module: external_services

// Documentation: Performs Payment Sync/Get

pub fn payment_get(
        &self,
        payment_get_request: payments_grpc::PaymentServiceGetRequest,
        connector_auth_metadata: ConnectorAuthMetadata,
        grpc_headers: GrpcHeadersUcs,
    ) -> UnifiedConnectorServiceResult<tonic::Response<payments_grpc::PaymentServiceGetResponse>>


// Implementation: impl Responder
// File: crates/router/src/routes/payments.rs
// Module: router
// Methods: 0 total (0 public)

impl Responder


// Implementation: impl Payouts for for Payone
// File: crates/hyperswitch_connectors/src/connectors/payone.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl Payouts for for Payone


// Implementation: impl UserPassword
// File: crates/router/src/types/domain/user.rs
// Module: router
// Methods: 3 total (3 public)

impl UserPassword


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

pub struct AuthenticationResponse


// Struct: ConnectorVolumeSplit
// File: crates/euclid/src/frontend/ast.rs
// Module: euclid
// Implementations: 0

pub struct ConnectorVolumeSplit


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

impl api::PaymentCapture for for Prophetpay


// Struct: ThreeDSAuthResult
// File: crates/hyperswitch_connectors/src/connectors/nexixpay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ThreeDSAuthResult


// Struct: PaymentsIncrementalAuthorizationData
// File: crates/hyperswitch_domain_models/src/router_request_types.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct PaymentsIncrementalAuthorizationData


// Implementation: impl PayoutAttemptInterface for for RouterStore
// File: crates/storage_impl/src/lib.rs
// Module: storage_impl
// Methods: 0 total (0 public)

impl PayoutAttemptInterface for for RouterStore


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

pub struct BluesnapWallet


                    if status == BankofamericaRefundStatus::Voided {
                        Err(get_error_response(
                            &Some(BankOfAmericaErrorInformation {
                                message: Some(constants::REFUND_VOIDED.to_string()),
                                reason: Some(constants::REFUND_VOIDED.to_string()),
                                details: None,
                            }),
                            &None,
                            &None,
                            None,
                            item.http_code,
                            item.response.id.clone(),
                        ))
                    } else {
                        Err(get_error_response(
                            &item.response.error_information,
                            &None,
                            &None,
                            None,
                            item.http_code,
                            item.response.id.clone(),
                        ))
                    }
                } else {
                    Ok(RefundsResponseData {
                        connector_refund_id: item.response.id,
                        refund_status,
                    })
                }
            }

            None => Ok(RefundsResponseData {
                connector_refund_id: item.response.id.clone(),
                refund_status: match item.data.response {
                    Ok(response) => response.refund_status,
                    Err(_) => common_enums::RefundStatus::Pending,
                },
            }),
        };

        Ok(Self {
            response,
            ..item.data
        })
    }
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct BankOfAmericaStandardErrorResponse {
    pub error_information: Option<ErrorInformation>,
    pub status: Option<String>,
    pub message: Option<String>,
    pub reason: Option<String>,
    pub details: Option<Vec<Details>>,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct BankOfAmericaServerErrorResponse {
    pub status: Option<String>,
    pub message: Option<String>,
    pub reason: Option<Reason>,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum Reason {
    SystemError,
    ServerTimeout,
    ServiceTimeout,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct BankOfAmericaAuthenticationErrorResponse {
    pub response: AuthenticationErrorInformation,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum BankOfAmericaErrorResponse {
    AuthenticationError(BankOfAmericaAuthenticationErrorResponse),
    StandardError(BankOfAmericaStandardErrorResponse),
}

#[derive(Debug, Deserialize, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Details {
    pub field: String,
    pub reason: String,
}

#[derive(Debug, Default, Deserialize, Serialize)]
pub struct ErrorInformation {
    pub message: String,
    pub reason: String,
    pub details: Option<Vec<Details>>,
}

#[derive(Debug, Default, Deserialize, Serialize)]
pub struct AuthenticationErrorInformation {
    pub rmsg: String,
}

fn get_error_response(
    error_data: &Option<BankOfAmericaErrorInformation>,
    processor_information: &Option<ClientProcessorInformation>,
    risk_information: &Option<ClientRiskInformation>,
    attempt_status: Option<enums::AttemptStatus>,
    status_code: u16,
    transaction_id: String,
) -> ErrorResponse {
    let avs_message = risk_information
        .clone()
        .map(|client_risk_information| {
            client_risk_information.rules.map(|rules| {
                rules
                    .iter()
                    .map(|risk_info| {
                        risk_info.name.clone().map_or("".to_string(), |name| {
                            format!(" , {}", name.clone().expose())
                        })
                    })
                    .collect::<Vec<String>>()
                    .join("")
            })
        })
        .unwrap_or(Some("".to_string()));

    let detailed_error_info = error_data.to_owned().and_then(|error_info| {
        error_info.details.map(|error_details| {
            error_details
                .iter()
                .map(|details| format!("{} : {}", details.field, details.reason))
                .collect::<Vec<_>>()
                .join(", ")
        })
    });
    let network_decline_code = processor_information
        .as_ref()
        .and_then(|info| info.response_code.clone());
    let network_advice_code = processor_information.as_ref().and_then(|info| {
        info.merchant_advice
            .as_ref()
            .and_then(|merchant_advice| merchant_advice.code_raw.clone())
    });

    let reason = get_error_reason(
        error_data
            .clone()
            .and_then(|error_details| error_details.message),
        detailed_error_info,
        avs_message,
    );
    let error_message = error_data
        .clone()
        .and_then(|error_details| error_details.reason);

    ErrorResponse {
        code: error_message
            .clone()
            .unwrap_or(hyperswitch_interfaces::consts::NO_ERROR_CODE.to_string()),
        message: error_message
            .clone()
            .unwrap_or(hyperswitch_interfaces::consts::NO_ERROR_MESSAGE.to_string()),
        reason,
        status_code,
        attempt_status,
        connector_transaction_id: Some(transaction_id.clone()),
        network_advice_code,
        network_decline_code,
        network_error_message: None,
        connector_metadata: None,
    }
}

impl
    TryFrom<(
        &SetupMandateRouterData,
        hyperswitch_domain_models::payment_method_data::Card,
    )> for BankOfAmericaPaymentsRequest
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        (item, ccard): (
            &SetupMandateRouterData,
            hyperswitch_domain_models::payment_method_data::Card,
        ),
    ) -> Result<Self, Self::Error> {
        if item.is_three_ds() {
            Err(errors::ConnectorError::NotSupported {
                message: "Card 3DS".to_string(),
                connector: "BankOfAmerica",
            })?
        };

        let order_information = OrderInformationWithBill::try_from(item)?;
        let client_reference_information = ClientReferenceInformation::from(item);
        let merchant_defined_information =
            item.request.metadata.clone().map(|metadata| {
                convert_metadata_to_merchant_defined_info(metadata.peek().to_owned())
            });
        let payment_information = PaymentInformation::try_from(&ccard)?;
        let processing_information = ProcessingInformation::try_from((None, None))?;
        Ok(Self {
            processing_information,
            payment_information,
            order_information,
            client_reference_information,
            consumer_authentication_information: None,
            merchant_defined_information,
        })
    }
}

impl TryFrom<(&SetupMandateRouterData, ApplePayWalletData)> for BankOfAmericaPaymentsRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        (item, apple_pay_data): (&SetupMandateRouterData, ApplePayWalletData),
    ) -> Result<Self, Self::Error> {
        let order_information = OrderInformationWithBill::try_from(item)?;
        let client_reference_information = ClientReferenceInformation::from(item);
        let merchant_defined_information =
            item.request.metadata.clone().map(|metadata| {
                convert_metadata_to_merchant_defined_info(metadata.peek().to_owned())
            });
        let payment_information = match item.payment_method_token.clone() {
            Some(payment_method_token) => match payment_method_token {
                PaymentMethodToken::ApplePayDecrypt(decrypt_data) => {
                    PaymentInformation::try_from(&decrypt_data)?
                }
                PaymentMethodToken::Token(_) => Err(unimplemented_payment_method!(
                    "Apple Pay",
                    "Manual",
                    "Bank Of America"
                ))?,
                PaymentMethodToken::PazeDecrypt(_) => {
                    Err(unimplemented_payment_method!("Paze", "Bank Of America"))?
                }
                PaymentMethodToken::GooglePayDecrypt(_) => Err(unimplemented_payment_method!(
                    "Google Pay",
                    "Bank Of America"
                ))?,
            },
            None => PaymentInformation::try_from(&apple_pay_data)?,
        };
        let processing_information = ProcessingInformation::try_from((
            Some(PaymentSolution::ApplePay),
            Some(apple_pay_data.payment_method.network.clone()),
        ))?;
        let ucaf_collection_indicator = match apple_pay_data
            .payment_method
            .network
            .to_lowercase()
            .as_str()
        {
            "mastercard" => Some("2".to_string()),
            _ => None,
        };
        let consumer_authentication_information = Some(BankOfAmericaConsumerAuthInformation {
            ucaf_collection_indicator,
            cavv: None,
            ucaf_authentication_data: None,
            xid: None,
            directory_server_transaction_id: None,
            specification_version: None,
        });

        Ok(Self {
            processing_information,
            payment_information,
            order_information,
            client_reference_information,
            merchant_defined_information,
            consumer_authentication_information,
        })
    }
}

impl TryFrom<(&SetupMandateRouterData, GooglePayWalletData)> for BankOfAmericaPaymentsRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        (item, google_pay_data): (&SetupMandateRouterData, GooglePayWalletData),
    ) -> Result<Self, Self::Error> {
        let order_information = OrderInformationWithBill::try_from(item)?;
        let client_reference_information = ClientReferenceInformation::from(item);
        let merchant_defined_information =
            item.request.metadata.clone().map(|metadata| {
                convert_metadata_to_merchant_defined_info(metadata.peek().to_owned())
            });
        let payment_information = PaymentInformation::try_from(&google_pay_data)?;
        let processing_information =
            ProcessingInformation::try_from((Some(PaymentSolution::GooglePay), None))?;

        Ok(Self {
            processing_information,
            payment_information,
            order_information,
            client_reference_information,
            merchant_defined_information,
            consumer_authentication_information: None,
        })
    }
}

// specific for setupMandate flow
impl TryFrom<(Option<PaymentSolution>, Option<String>)> for ProcessingInformation {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        (solution, network): (Option<PaymentSolution>, Option<String>),
    ) -> Result<Self, Self::Error> {
        let (action_list, action_token_types, authorization_options) =
            get_boa_mandate_action_details();
        let commerce_indicator = get_commerce_indicator(network);

        Ok(Self {
            capture: Some(false),
            capture_options: None,
            action_list,
            action_token_types,
            authorization_options,
            commerce_indicator,
            payment_solution: solution.map(String::from),
        })
    }
}

impl TryFrom<&SetupMandateRouterData> for OrderInformationWithBill {
    type Error = error_stack::Report<errors::ConnectorError>;

    fn try_from(item: &SetupMandateRouterData) -> Result<Self, Self::Error> {
        let email = item.request.get_email()?;
        let bill_to = build_bill_to(item.get_optional_billing(), email)?;

        Ok(Self {
            amount_details: Amount {
                total_amount: StringMajorUnit::zero(),
                currency: item.request.currency,
            },
            bill_to: Some(bill_to),
        })
    }
}

impl TryFrom<&hyperswitch_domain_models::payment_method_data::Card> for PaymentInformation {
    type Error = error_stack::Report<errors::ConnectorError>;

    fn try_from(
        ccard: &hyperswitch_domain_models::payment_method_data::Card,
    ) -> Result<Self, Self::Error> {
        let card_type = match ccard.card_network.clone().and_then(get_boa_card_type) {
            Some(card_network) => Some(card_network.to_string()),
            None => ccard.get_card_issuer().ok().map(String::from),
        };
        Ok(Self::Cards(Box::new(CardPaymentInformation {
            card: Card {
                number: ccard.card_number.clone(),
                expiration_month: ccard.card_exp_month.clone(),
                expiration_year: ccard.card_exp_year.clone(),
                security_code: ccard.card_cvc.clone(),
                card_type,
            },
        })))
    }
}

impl TryFrom<&Box<ApplePayPredecryptData>> for PaymentInformation {
    type Error = error_stack::Report<errors::ConnectorError>;

    fn try_from(apple_pay_data: &Box<ApplePayPredecryptData>) -> Result<Self, Self::Error> {
        let expiration_month = apple_pay_data.get_expiry_month().change_context(
            errors::ConnectorError::InvalidDataFormat {
                field_name: "expiration_month",
            },
        )?;
        let expiration_year = apple_pay_data.get_four_digit_expiry_year();

        Ok(Self::ApplePay(Box::new(ApplePayPaymentInformation {
            tokenized_card: TokenizedCard {
                number: apple_pay_data.application_primary_account_number.clone(),
                cryptogram: apple_pay_data
                    .payment_data
                    .online_payment_cryptogram
                    .clone(),
                transaction_type: TransactionType::ApplePay,
                expiration_year,
                expiration_month,
            },
        })))
    }
}

impl TryFrom<&ApplePayWalletData> for PaymentInformation {
    type Error = error_stack::Report<errors::ConnectorError>;

    fn try_from(apple_pay_data: &ApplePayWalletData) -> Result<Self, Self::Error> {
        let apple_pay_encrypted_data = apple_pay_data
            .payment_data
            .get_encrypted_apple_pay_payment_data_mandatory()
            .change_context(errors::ConnectorError::MissingRequiredField {
                field_name: "Apple pay encrypted data",
            })?;

        Ok(Self::ApplePayToken(Box::new(
            ApplePayTokenPaymentInformation {
                fluid_data: FluidData {
                    value: Secret::from(apple_pay_encrypted_data.clone()),
                    descriptor: None,
                },
                tokenized_card: ApplePayTokenizedCard {
                    transaction_type: TransactionType::ApplePay,
                },
            },
        )))
    }
}

impl TryFrom<&GooglePayWalletData> for PaymentInformation {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(google_pay_data: &GooglePayWalletData) -> Result<Self, Self::Error> {
        Ok(Self::GooglePay(Box::new(GooglePayPaymentInformation {
            fluid_data: FluidData {
                value: Secret::from(
                    consts::BASE64_ENGINE.encode(
                        google_pay_data
                            .tokenization_data
                            .get_encrypted_google_pay_token()
                            .change_context(errors::ConnectorError::MissingRequiredField {
                                field_name: "gpay wallet_token",
                            })?
                            .clone(),
                    ),
                ),
                descriptor: None,
            },
        })))
    }
}

fn convert_to_error_response_from_error_info(
    error_response: &BankOfAmericaErrorInformationResponse,
    status_code: u16,
) -> ErrorResponse {
    let detailed_error_info =
        error_response
            .error_information
            .to_owned()
            .details
            .map(|error_details| {
                error_details
                    .iter()
                    .map(|details| format!("{} : {}", details.field, details.reason))
                    .collect::<Vec<_>>()
                    .join(", ")
            });

    let reason = get_error_reason(
        error_response.error_information.message.to_owned(),
        detailed_error_info,
        None,
    );
    ErrorResponse {
        code: error_response
            .error_information
            .reason
            .clone()
            .unwrap_or(hyperswitch_interfaces::consts::NO_ERROR_CODE.to_string()),
        message: error_response
            .error_information
            .reason
            .clone()
            .unwrap_or(hyperswitch_interfaces::consts::NO_ERROR_MESSAGE.to_string()),
        reason,
        status_code,
        attempt_status: None,
        connector_transaction_id: Some(error_response.id.clone()),
        network_advice_code: None,
        network_decline_code: None,
        network_error_message: None,
        connector_metadata: None,
    }
}

fn get_boa_mandate_action_details() -> (
    Option<Vec<BankOfAmericaActionsList>>,
    Option<Vec<BankOfAmericaActionsTokenType>>,
    Option<BankOfAmericaAuthorizationOptions>,
) {
    (
        Some(vec![BankOfAmericaActionsList::TokenCreate]),
        Some(vec![
            BankOfAmericaActionsTokenType::PaymentInstrument,
            BankOfAmericaActionsTokenType::Customer,
        ]),
        Some(BankOfAmericaAuthorizationOptions {
            initiator: Some(BankOfAmericaPaymentInitiator {
                initiator_type: Some(BankOfAmericaPaymentInitiatorTypes::Customer),
                credential_stored_on_file: Some(true),
                stored_credential_used: None,
            }),
            merchant_intitiated_transaction: None,
        }),
    )
}

fn get_commerce_indicator(network: Option<String>) -> String {
    match network {
        Some(card_network) => match card_network.to_lowercase().as_str() {
            "amex" => "aesk",
            "discover" => "dipb",
            "mastercard" => "spa",
            "visa" => "internet",
            _ => "internet",
        },
        None => "internet",
    }
    .to_string()
}

pub fn get_error_reason(
    error_info: Option<String>,
    detailed_error_info: Option<String>,
    avs_error_info: Option<String>,
) -> Option<String> {
    match (error_info, detailed_error_info, avs_error_info) {
        (Some(message), Some(details), Some(avs_message)) => Some(format!(
            "{message}, detailed_error_information: {details}, avs_message: {avs_message}",
        )),
        (Some(message), Some(details), None) => {
            Some(format!("{message}, detailed_error_information: {details}"))
        }
        (Some(message), None, Some(avs_message)) => {
            Some(format!("{message}, avs_message: {avs_message}"))
        }
        (None, Some(details), Some(avs_message)) => {
            Some(format!("{details}, avs_message: {avs_message}"))
        }
        (Some(message), None, None) => Some(message),
        (None, Some(details), None) => Some(details),
        (None, None, Some(avs_message)) => Some(avs_message),
        (None, None, None) => None,
    }
}


// File: crates/events/src/lib.rs
// Module: events
// Public functions: 8
// Public structs: 2

#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg_hide))]
#![cfg_attr(docsrs, doc(cfg_hide(doc)))]
#![warn(missing_docs)]

//! A generic event handler system.
//! This library consists of 4 parts:
//! Event Sink: A trait that defines how events are published. This could be a simple logger, a message queue, or a database.
//! EventContext: A struct that holds the event sink and metadata about the event. This is used to create events. This can be used to add metadata to all events, such as the user who triggered the event.
//! EventInfo: A trait that defines the metadata that is sent with the event. It works with the EventContext to add metadata to all events.
//! Event: A trait that defines the event itself. This trait is used to define the data that is sent with the event and defines the event's type & identifier.

mod actix;

use std::{collections::HashMap, sync::Arc};

use error_stack::{Result, ResultExt};
use masking::{ErasedMaskSerialize, Serialize};
use router_env::logger;
use serde::Serializer;
use serde_json::Value;
use time::PrimitiveDateTime;

/// Errors that can occur when working with events.
#[derive(Debug, Clone, thiserror::Error)]
pub enum EventsError {
    /// An error occurred when publishing the event.
    #[error("Generic Error")]
    GenericError,
    /// An error occurred when serializing the event.
    #[error("Event serialization error")]
    SerializationError,
    /// An error occurred when publishing/producing the event.
    #[error("Event publishing error")]
    PublishError,
}

/// An event that can be published.
pub trait Event: EventInfo {
    /// The type of the event.
    type EventType;
    /// The timestamp of the event.
    fn timestamp(&self) -> PrimitiveDateTime;

    /// The (unique) identifier of the event.
    fn identifier(&self) -> String;

    /// The class/type of the event. This is used to group/categorize events together.
    fn class(&self) -> Self::EventType;

    /// Metadata associated with the event
    fn metadata(&self) -> HashMap<String, String> {
        HashMap::new()
    }
}

/// Hold the context information for any events
#[derive(Clone)]
pub struct EventContext<T, A>
where
    A: MessagingInterface<MessageClass = T>,
{
    message_sink: Arc<A>,
    metadata: HashMap<String, Value>,
}

/// intermediary structure to build events with in-place info.
#[must_use = "make sure to call `emit` or `try_emit` to actually emit the event"]
pub struct EventBuilder<T, A, E, D>
where
    A: MessagingInterface<MessageClass = T>,
    E: Event<EventType = T, Data = D>,
{
    message_sink: Arc<A>,
    metadata: HashMap<String, Value>,
    event: E,
}

/// A flattened event that flattens the context provided to it along with the actual event.
struct FlatMapEvent<T, A: Event<EventType = T>>(HashMap<String, Value>, A);

impl<T, A, E, D> EventBuilder<T, A, E, D>
where
    A: MessagingInterface<MessageClass = T>,
    E: Event<EventType = T, Data = D>,
{
    /// Add metadata to the event.
    pub fn with<F: ErasedMaskSerialize, G: EventInfo<Data = F> + 'static>(
        mut self,
        info: G,
    ) -> Self {
        info.data()
            .and_then(|i| {
                i.masked_serialize()
                    .change_context(EventsError::SerializationError)
            })
            .map_err(|e| {
                logger::error!("Error adding event info: {:?}", e);
            })
            .ok()
            .and_then(|data| self.metadata.insert(info.key(), data));
        self
    }
    /// Emit the event and log any errors.
    pub fn emit(self) {
        self.try_emit()
            .map_err(|e| {
                logger::error!("Error emitting event: {:?}", e);
            })
            .ok();
    }

    /// Emit the event.
    pub fn try_emit(self) -> Result<(), EventsError> {
        let ts = self.event.timestamp();
        let metadata = self.event.metadata();
        self.message_sink
            .send_message(FlatMapEvent(self.metadata, self.event), metadata, ts)
    }
}

impl<T, A> Serialize for FlatMapEvent<T, A>
where
    A: Event<EventType = T>,
{
    fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut serialize_map: HashMap<_, _> = self
            .0
            .iter()
            .filter_map(|(k, v)| Some((k.clone(), v.masked_serialize().ok()?)))
            .collect();
        match self.1.data().map(|i| i.masked_serialize()) {
            Ok(Ok(Value::Object(map))) => {
                for (k, v) in map.into_iter() {
                    serialize_map.insert(k, v);
                }
            }
            Ok(Ok(i)) => {
                serialize_map.insert(self.1.key(), i);
            }
            i => {
                logger::error!("Error serializing event: {:?}", i);
            }
        };
        serialize_map.serialize(serializer)
    }
}

impl<T, A> EventContext<T, A>
where
    A: MessagingInterface<MessageClass = T>,
{
    /// Create a new event context.
    pub fn new(message_sink: A) -> Self {
        Self {
            message_sink: Arc::new(message_sink),
            metadata: HashMap::new(),
        }
    }

    /// Add metadata to the event context.
    #[track_caller]
    pub fn record_info<G: ErasedMaskSerialize, E: EventInfo<Data = G> + 'static>(
        &mut self,
        info: E,
    ) {
        match info.data().and_then(|i| {
            i.masked_serialize()
                .change_context(EventsError::SerializationError)
        }) {
            Ok(data) => {
                self.metadata.insert(info.key(), data);
            }
            Err(e) => {
                logger::error!("Error recording event info: {:?}", e);
            }
        }
    }

    /// Emit an event.
    pub fn try_emit<E: Event<EventType = T>>(&self, event: E) -> Result<(), EventsError> {
        EventBuilder {
            message_sink: self.message_sink.clone(),
            metadata: self.metadata.clone(),
            event,
        }
        .try_emit()
    }

    /// Emit an event.
    pub fn emit<D, E: Event<EventType = T, Data = D>>(&self, event: E) {
        EventBuilder {
            message_sink: self.message_sink.clone(),
            metadata: self.metadata.clone(),
            event,
        }
        .emit()
    }

    /// Create an event builder.
    pub fn event<D, E: Event<EventType = T, Data = D>>(
        &self,
        event: E,
    ) -> EventBuilder<T, A, E, D> {
        EventBuilder {
            message_sink: self.message_sink.clone(),
            metadata: self.metadata.clone(),
            event,
        }
    }
}

/// Add information/metadata to the current context of an event.
pub trait EventInfo {
    /// The data that is sent with the event.
    type Data: ErasedMaskSerialize;
    /// The data that is sent with the event.
    fn data(&self) -> Result<Self::Data, EventsError>;

    /// The key identifying the data for an event.
    fn key(&self) -> String;
}

impl EventInfo for (String, String) {
    type Data = String;
    fn data(&self) -> Result<String, EventsError> {
        Ok(self.1.clone())
    }

    fn key(&self) -> String {
        self.0.clone()
    }
}

/// A messaging interface for sending messages/events.
/// This can be implemented for any messaging system, such as a message queue, a logger, or a database.
pub trait MessagingInterface {
    /// The type of the event used for categorization by the event publisher.
    type MessageClass;
    /// Send a message that follows the defined message class.
    fn send_message<T>(
        &self,
        data: T,
        metadata: HashMap<String, String>,
        timestamp: PrimitiveDateTime,
    ) -> Result<(), EventsError>
    where
        T: Message<Class = Self::MessageClass> + ErasedMaskSerialize;
}

/// A message that can be sent.
pub trait Message {
    /// The type of the event used for categorization by the event publisher.
    type Class;
    /// The type of the event used for categorization by the event publisher.
    fn get_message_class(&self) -> Self::Class;

    /// The (unique) identifier of the event.
    fn identifier(&self) -> String;
}

impl<T, A> Message for FlatMapEvent<T, A>
where
    A: Event<EventType = T>,
{
    type Class = T;

    fn get_message_class(&self) -> Self::Class {
        self.1.class()
    }

    fn identifier(&self) -> String {
        self.1.identifier()
    }
}


// Function: get_metadata
// File: crates/hyperswitch_domain_models/src/mandates.rs
// Module: hyperswitch_domain_models

pub fn get_metadata(&self) -> Option<pii::SecretSerdeValue>


// Function: payments_create_intent
// File: crates/router/src/routes/payments.rs
// Module: router

pub fn payments_create_intent(
    state: web::Data<app::AppState>,
    req: actix_web::HttpRequest,
    json_payload: web::Json<payment_types::PaymentsCreateIntentRequest>,
) -> impl Responder


// Implementation: impl PartialEq for for FrmMetricsBucketIdentifier
// File: crates/api_models/src/analytics/frm.rs
// Module: api_models
// Methods: 1 total (0 public)

impl PartialEq for for FrmMetricsBucketIdentifier


// Struct: User
// File: crates/router/src/routes/app.rs
// Module: router
// Implementations: 2

pub struct User


// File: crates/router/src/services/authorization.rs
// Module: router
// Public functions: 5

use std::sync::Arc;

use common_utils::id_type;
use error_stack::ResultExt;
use redis_interface::RedisConnectionPool;
use router_env::logger;

use super::authentication::AuthToken;
use crate::{
    consts,
    core::errors::{ApiErrorResponse, RouterResult, StorageErrorExt},
    routes::app::SessionStateInfo,
};

#[cfg(feature = "olap")]
pub mod info;
pub mod permission_groups;
pub mod permissions;
pub mod roles;

pub async fn get_role_info<A>(state: &A, token: &AuthToken) -> RouterResult<roles::RoleInfo>
where
    A: SessionStateInfo + Sync,
{
    if let Some(role_info) = roles::predefined_roles::PREDEFINED_ROLES.get(token.role_id.as_str()) {
        return Ok(role_info.clone());
    }

    if let Ok(role_info) = get_role_info_from_cache(state, &token.role_id)
        .await
        .map_err(|e| logger::error!("Failed to get permissions from cache {e:?}"))
    {
        return Ok(role_info.clone());
    }

    let role_info = get_role_info_from_db(
        state,
        &token.role_id,
        &token.org_id,
        token
            .tenant_id
            .as_ref()
            .unwrap_or(&state.session_state().tenant.tenant_id),
    )
    .await?;

    let token_expiry =
        i64::try_from(token.exp).change_context(ApiErrorResponse::InternalServerError)?;
    let cache_ttl = token_expiry - common_utils::date_time::now_unix_timestamp();

    if cache_ttl > 0 {
        set_role_info_in_cache(state, &token.role_id, &role_info, cache_ttl)
            .await
            .map_err(|e| logger::error!("Failed to set role info in cache {e:?}"))
            .ok();
    }
    Ok(role_info)
}

async fn get_role_info_from_cache<A>(state: &A, role_id: &str) -> RouterResult<roles::RoleInfo>
where
    A: SessionStateInfo + Sync,
{
    let redis_conn = get_redis_connection_for_global_tenant(state)?;

    redis_conn
        .get_and_deserialize_key(&get_cache_key_from_role_id(role_id).into(), "RoleInfo")
        .await
        .change_context(ApiErrorResponse::InternalServerError)
}

pub fn get_cache_key_from_role_id(role_id: &str) -> String {
    format!("{}{}", consts::ROLE_INFO_CACHE_PREFIX, role_id)
}

async fn get_role_info_from_db<A>(
    state: &A,
    role_id: &str,
    org_id: &id_type::OrganizationId,
    tenant_id: &id_type::TenantId,
) -> RouterResult<roles::RoleInfo>
where
    A: SessionStateInfo + Sync,
{
    state
        .session_state()
        .global_store
        .find_by_role_id_org_id_tenant_id(role_id, org_id, tenant_id)
        .await
        .map(roles::RoleInfo::from)
        .to_not_found_response(ApiErrorResponse::InvalidJwtToken)
}

pub async fn set_role_info_in_cache<A>(
    state: &A,
    role_id: &str,
    role_info: &roles::RoleInfo,
    expiry: i64,
) -> RouterResult<()>
where
    A: SessionStateInfo + Sync,
{
    let redis_conn = get_redis_connection_for_global_tenant(state)?;

    redis_conn
        .serialize_and_set_key_with_expiry(
            &get_cache_key_from_role_id(role_id).into(),
            role_info,
            expiry,
        )
        .await
        .change_context(ApiErrorResponse::InternalServerError)
}

pub fn check_permission(
    required_permission: permissions::Permission,
    role_info: &roles::RoleInfo,
) -> RouterResult<()> {
    role_info
        .check_permission_exists(required_permission)
        .then_some(())
        .ok_or(
            ApiErrorResponse::AccessForbidden {
                resource: required_permission.to_string(),
            }
            .into(),
        )
}

pub fn check_tenant(
    token_tenant_id: Option<id_type::TenantId>,
    header_tenant_id: &id_type::TenantId,
) -> RouterResult<()> {
    if let Some(tenant_id) = token_tenant_id {
        if tenant_id != *header_tenant_id {
            return Err(ApiErrorResponse::InvalidJwtToken).attach_printable(format!(
                "Token tenant ID: '{}' does not match Header tenant ID: '{}'",
                tenant_id.get_string_repr().to_owned(),
                header_tenant_id.get_string_repr().to_owned()
            ));
        }
    }
    Ok(())
}

fn get_redis_connection_for_global_tenant<A: SessionStateInfo>(
    state: &A,
) -> RouterResult<Arc<RedisConnectionPool>> {
    state
        .global_store()
        .get_redis_conn()
        .change_context(ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to get redis connection")
}


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

impl api::PaymentCapture for for Adyen


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

impl webhooks::IncomingWebhook for for Nomupay


// Function: from_pii_email
// File: crates/router/src/types/domain/user.rs
// Module: router

pub fn from_pii_email(email: pii::Email) -> UserResult<Self>


// Implementation: impl AnalyticsProvider
// File: crates/analytics/src/lib.rs
// Module: analytics
// Methods: 12 total (0 public)

impl AnalyticsProvider


// Struct: TransactionConfirmRequest
// File: crates/hyperswitch_connectors/src/connectors/authorizedotnet/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct TransactionConfirmRequest


// Implementation: impl ConnectorCommon for for Stripe
// File: crates/hyperswitch_connectors/src/connectors/stripe.rs
// Module: hyperswitch_connectors
// Methods: 5 total (0 public)

impl ConnectorCommon for for Stripe


// Implementation: impl api::RefundSync for for Billwerk
// File: crates/hyperswitch_connectors/src/connectors/billwerk.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::RefundSync for for Billwerk


// Implementation: impl api::PaymentVoid for for Authorizedotnet
// File: crates/hyperswitch_connectors/src/connectors/authorizedotnet.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentVoid for for Authorizedotnet


// File: crates/connector_configs/src/common_config.rs
// Module: connector_configs
// Public structs: 12

use api_models::{payment_methods, payments};
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;

#[serde_with::skip_serializing_none]
#[derive(Debug, Deserialize, serde::Serialize, Clone)]
#[serde(rename_all = "snake_case")]
pub struct ZenApplePay {
    pub terminal_uuid: Option<String>,
    pub pay_wall_secret: Option<String>,
}

#[serde_with::skip_serializing_none]
#[derive(Debug, Deserialize, serde::Serialize, Clone)]
#[serde(untagged)]
pub enum ApplePayData {
    ApplePay(payments::ApplePayMetadata),
    ApplePayCombined(payments::ApplePayCombinedMetadata),
    Zen(ZenApplePay),
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct GpayDashboardPayLoad {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub gateway_merchant_id: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none", rename = "stripe:version")]
    pub stripe_version: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(rename(
        serialize = "stripe_publishable_key",
        deserialize = "stripe:publishable_key"
    ))]
    #[serde(alias = "stripe:publishable_key")]
    #[serde(alias = "stripe_publishable_key")]
    pub stripe_publishable_key: Option<String>,
    pub merchant_name: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub merchant_id: Option<String>,
}

#[serde_with::skip_serializing_none]
#[derive(Debug, Deserialize, serde::Serialize, Clone)]
#[serde(rename_all = "snake_case")]
pub struct ZenGooglePay {
    pub terminal_uuid: Option<String>,
    pub pay_wall_secret: Option<String>,
}

#[serde_with::skip_serializing_none]
#[derive(Debug, Deserialize, serde::Serialize, Clone)]
#[serde(untagged)]
pub enum GooglePayData {
    Standard(GpayDashboardPayLoad),
    Zen(ZenGooglePay),
}

#[serde_with::skip_serializing_none]
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct PaypalSdkData {
    pub client_id: Option<String>,
}

#[serde_with::skip_serializing_none]
#[derive(Debug, Deserialize, serde::Serialize, Clone)]
#[serde(untagged)]
pub enum GoogleApiModelData {
    Standard(payments::GpayMetaData),
    Zen(ZenGooglePay),
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub struct PaymentMethodsEnabled {
    pub payment_method: api_models::enums::PaymentMethod,
    pub payment_method_types: Option<Vec<payment_methods::RequestPaymentMethodTypes>>,
}

#[serde_with::skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub struct ApiModelMetaData {
    pub merchant_config_currency: Option<api_models::enums::Currency>,
    pub merchant_account_id: Option<String>,
    pub account_name: Option<String>,
    pub terminal_id: Option<String>,
    pub merchant_id: Option<String>,
    pub google_pay: Option<GoogleApiModelData>,
    pub paypal_sdk: Option<PaypalSdkData>,
    pub apple_pay: Option<ApplePayData>,
    pub apple_pay_combined: Option<ApplePayData>,
    pub endpoint_prefix: Option<String>,
    pub mcc: Option<String>,
    pub merchant_country_code: Option<String>,
    pub merchant_name: Option<String>,
    pub acquirer_bin: Option<String>,
    pub acquirer_merchant_id: Option<String>,
    pub acquirer_country_code: Option<String>,
    pub three_ds_requestor_name: Option<String>,
    pub three_ds_requestor_id: Option<String>,
    pub pull_mechanism_for_external_3ds_enabled: Option<bool>,
    pub klarna_region: Option<KlarnaEndpoint>,
    pub source_balance_account: Option<String>,
    pub brand_id: Option<String>,
    pub destination_account_number: Option<String>,
    pub dpa_id: Option<String>,
    pub dpa_name: Option<String>,
    pub locale: Option<String>,
    pub card_brands: Option<Vec<String>>,
    pub merchant_category_code: Option<String>,
    pub merchant_configuration_id: Option<String>,
    pub tenant_id: Option<String>,
    pub platform_url: Option<String>,
    pub account_id: Option<serde_json::Value>,
    pub site: Option<String>,
}

#[serde_with::skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub enum KlarnaEndpoint {
    Europe,
    NorthAmerica,
    Oceania,
}

#[serde_with::skip_serializing_none]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, ToSchema, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct CardProvider {
    pub payment_method_type: api_models::enums::CardNetwork,
    /// List of currencies accepted or has the processing capabilities of the processor
    #[schema(example = json!(
            {
                "type": "specific_accepted",
                "list": ["USD", "INR"]
            }
        ), value_type = Option<AcceptedCurrencies>)]
    pub accepted_currencies: Option<api_models::admin::AcceptedCurrencies>,
    #[schema(example = json!(
        {
            "type": "specific_accepted",
            "list": ["UK", "AU"]
        }
    ), value_type = Option<AcceptedCountries>)]
    pub accepted_countries: Option<api_models::admin::AcceptedCountries>,
}
#[serde_with::skip_serializing_none]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, ToSchema, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct Provider {
    pub payment_method_type: api_models::enums::PaymentMethodType,
    /// List of currencies accepted or has the processing capabilities of the processor
    #[schema(example = json!(
            {
                "type": "specific_accepted",
                "list": ["USD", "INR"]
            }
        ), value_type = Option<AcceptedCurrencies>)]
    pub accepted_currencies: Option<api_models::admin::AcceptedCurrencies>,
    #[schema(example = json!(
        {
            "type": "specific_accepted",
            "list": ["UK", "AU"]
        }
    ), value_type = Option<AcceptedCountries>)]
    pub accepted_countries: Option<api_models::admin::AcceptedCountries>,
    pub payment_experience: Option<api_models::enums::PaymentExperience>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub struct ConnectorApiIntegrationPayload {
    pub connector_type: String,
    pub profile_id: common_utils::id_type::ProfileId,
    pub connector_name: api_models::enums::Connector,
    #[serde(skip_deserializing)]
    #[schema(example = "stripe_US_travel")]
    pub connector_label: Option<String>,
    pub merchant_connector_id: Option<String>,
    pub disabled: bool,
    pub test_mode: bool,
    pub payment_methods_enabled: Option<Vec<PaymentMethodsEnabled>>,
    pub metadata: Option<ApiModelMetaData>,
    pub connector_webhook_details: Option<api_models::admin::MerchantConnectorWebhookDetails>,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct DashboardPaymentMethodPayload {
    pub payment_method: api_models::enums::PaymentMethod,
    pub payment_method_type: String,
    pub provider: Option<Vec<Provider>>,
    pub card_provider: Option<Vec<CardProvider>>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde_with::skip_serializing_none]
#[serde(rename_all = "snake_case")]
pub struct DashboardRequestPayload {
    pub connector: api_models::enums::Connector,
    pub payment_methods_enabled: Option<Vec<DashboardPaymentMethodPayload>>,
    pub metadata: Option<ApiModelMetaData>,
}

#[serde_with::skip_serializing_none]
#[derive(Debug, Deserialize, serde::Serialize, Clone)]
#[serde(tag = "type", content = "options")]
pub enum InputType {
    Text,
    Number,
    Toggle,
    Radio(Vec<String>),
    Select(Vec<String>),
    MultiSelect(Vec<String>),
}

#[serde_with::skip_serializing_none]
#[derive(Debug, Deserialize, serde::Serialize, Clone)]
#[serde(rename_all = "snake_case")]
pub struct InputData {
    pub name: String,
    pub label: String,
    pub placeholder: String,
    pub required: bool,
    #[serde(flatten)]
    pub input_type: InputType,
}


// Function: build_case_insensitive_filters
// File: crates/analytics/src/opensearch.rs
// Module: analytics

pub fn build_case_insensitive_filters(
        &self,
        mut payload: Value,
        case_insensitive_filters: &[&(String, Vec<Value>)


// Function: get_connector_label
// File: crates/api_models/src/admin.rs
// Module: api_models

pub fn get_connector_label(&self, profile_name: String) -> String


// Struct: StripebillingWebhookBody
// File: crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 1

pub struct StripebillingWebhookBody


// File: crates/router/src/core/pm_auth/helpers.rs
// Module: router
// Public functions: 1

use common_utils::ext_traits::ValueExt;
use error_stack::ResultExt;
use pm_auth::types::{self as pm_auth_types, api::BoxedPaymentAuthConnector};

use crate::{
    core::errors::{self, ApiErrorResponse},
    types::{self, domain, transformers::ForeignTryFrom},
};

pub trait PaymentAuthConnectorDataExt {
    fn get_connector_by_name(name: &str) -> errors::CustomResult<Self, ApiErrorResponse>
    where
        Self: Sized;
    fn convert_connector(
        connector_name: pm_auth_types::PaymentMethodAuthConnectors,
    ) -> errors::CustomResult<BoxedPaymentAuthConnector, ApiErrorResponse>;
}

pub fn get_connector_auth_type(
    merchant_connector_account: domain::MerchantConnectorAccount,
) -> errors::CustomResult<pm_auth_types::ConnectorAuthType, ApiErrorResponse> {
    let auth_type: types::ConnectorAuthType = merchant_connector_account
        .connector_account_details
        .parse_value("ConnectorAuthType")
        .change_context(ApiErrorResponse::MerchantConnectorAccountNotFound {
            id: "ConnectorAuthType".to_string(),
        })?;

    pm_auth_types::ConnectorAuthType::foreign_try_from(auth_type)
        .change_context(ApiErrorResponse::InternalServerError)
        .attach_printable("Failed while converting ConnectorAuthType")
}


// Implementation: impl Customer
// File: crates/diesel_models/src/query/customers.rs
// Module: diesel_models
// Methods: 9 total (0 public)

impl Customer


// Function: insert_payment_attempts
// File: crates/diesel_models/src/query/user/sample_data.rs
// Module: diesel_models

pub fn insert_payment_attempts(
    conn: &PgPooledConn,
    batch: Vec<user::sample_data::PaymentAttemptBatchNew>,
) -> StorageResult<Vec<PaymentAttempt>>


// Function: get_two_letter_country_code
// File: crates/euclid_wasm/src/lib.rs
// Module: euclid_wasm

pub fn get_two_letter_country_code() -> JsResult


// Function: make_payment_attempt
// File: crates/router/src/core/payments/operations/payment_create.rs
// Module: router

pub fn make_payment_attempt(
        payment_id: &common_utils::id_type::PaymentId,
        merchant_id: &common_utils::id_type::MerchantId,
        organization_id: &common_utils::id_type::OrganizationId,
        money: (api::Amount, enums::Currency)


// Struct: CancelResponseStatus
// File: crates/hyperswitch_connectors/src/connectors/forte/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct CancelResponseStatus


// Implementation: impl BusinessPaymentLinkConfig
// File: crates/api_models/src/admin.rs
// Module: api_models
// Methods: 1 total (1 public)

impl BusinessPaymentLinkConfig


// Struct: NovalnetCancelResponse
// File: crates/hyperswitch_connectors/src/connectors/novalnet/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct NovalnetCancelResponse


// Implementation: impl ErrorResponse
// File: crates/pm_auth/src/types.rs
// Module: pm_auth
// Methods: 1 total (0 public)

impl ErrorResponse


// Struct: Details
// File: crates/hyperswitch_connectors/src/connectors/wellsfargo/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct Details


// Struct: GpayAllowedMethodsParameters
// File: crates/hyperswitch_connectors/src/connectors/trustpay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct GpayAllowedMethodsParameters


// File: crates/analytics/src/payment_intents/metrics/successful_smart_retries.rs
// Module: analytics

use std::collections::HashSet;

use api_models::{
    analytics::{
        payment_intents::{
            PaymentIntentDimensions, PaymentIntentFilters, PaymentIntentMetricsBucketIdentifier,
        },
        Granularity, TimeRange,
    },
    enums::IntentStatus,
};
use common_utils::errors::ReportSwitchExt;
use error_stack::ResultExt;
use time::PrimitiveDateTime;

use super::PaymentIntentMetricRow;
use crate::{
    enums::AuthInfo,
    query::{
        Aggregate, FilterTypes, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql,
        Window,
    },
    types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
};

#[derive(Default)]
pub(super) struct SuccessfulSmartRetries;

#[async_trait::async_trait]
impl<T> super::PaymentIntentMetric<T> for SuccessfulSmartRetries
where
    T: AnalyticsDataSource + super::PaymentIntentMetricAnalytics,
    PrimitiveDateTime: ToSql<T>,
    AnalyticsCollection: ToSql<T>,
    Granularity: GroupByClause<T>,
    Aggregate<&'static str>: ToSql<T>,
    Window<&'static str>: ToSql<T>,
{
    async fn load_metrics(
        &self,
        dimensions: &[PaymentIntentDimensions],
        auth: &AuthInfo,
        filters: &PaymentIntentFilters,
        granularity: Option<Granularity>,
        time_range: &TimeRange,
        pool: &T,
    ) -> MetricsResult<HashSet<(PaymentIntentMetricsBucketIdentifier, PaymentIntentMetricRow)>>
    {
        let mut query_builder: QueryBuilder<T> =
            QueryBuilder::new(AnalyticsCollection::PaymentIntent);

        for dim in dimensions.iter() {
            query_builder.add_select_column(dim).switch()?;
        }
        query_builder
            .add_select_column(Aggregate::Count {
                field: None,
                alias: Some("count"),
            })
            .switch()?;
        query_builder
            .add_select_column(Aggregate::Min {
                field: "created_at",
                alias: Some("start_bucket"),
            })
            .switch()?;
        query_builder
            .add_select_column(Aggregate::Max {
                field: "created_at",
                alias: Some("end_bucket"),
            })
            .switch()?;

        filters.set_filter_clause(&mut query_builder).switch()?;

        auth.set_filter_clause(&mut query_builder).switch()?;

        query_builder
            .add_custom_filter_clause("attempt_count", "1", FilterTypes::Gt)
            .switch()?;
        query_builder
            .add_custom_filter_clause("status", IntentStatus::Succeeded, FilterTypes::Equal)
            .switch()?;
        time_range
            .set_filter_clause(&mut query_builder)
            .attach_printable("Error filtering time range")
            .switch()?;

        for dim in dimensions.iter() {
            query_builder
                .add_group_by_clause(dim)
                .attach_printable("Error grouping by dimensions")
                .switch()?;
        }
        if let Some(granularity) = granularity {
            granularity
                .set_group_by_clause(&mut query_builder)
                .attach_printable("Error adding granularity")
                .switch()?;
        }

        query_builder
            .execute_query::<PaymentIntentMetricRow, _>(pool)
            .await
            .change_context(MetricsError::QueryBuildingError)?
            .change_context(MetricsError::QueryExecutionFailure)?
            .into_iter()
            .map(|i| {
                Ok((
                    PaymentIntentMetricsBucketIdentifier::new(
                        i.status.as_ref().map(|i| i.0),
                        i.currency.as_ref().map(|i| i.0),
                        i.profile_id.clone(),
                        i.connector.clone(),
                        i.authentication_type.as_ref().map(|i| i.0),
                        i.payment_method.clone(),
                        i.payment_method_type.clone(),
                        i.card_network.clone(),
                        i.merchant_id.clone(),
                        i.card_last_4.clone(),
                        i.card_issuer.clone(),
                        i.error_reason.clone(),
                        TimeRange {
                            start_time: match (granularity, i.start_bucket) {
                                (Some(g), Some(st)) => g.clip_to_start(st)?,
                                _ => time_range.start_time,
                            },
                            end_time: granularity.as_ref().map_or_else(
                                || Ok(time_range.end_time),
                                |g| i.end_bucket.map(|et| g.clip_to_end(et)).transpose(),
                            )?,
                        },
                    ),
                    i,
                ))
            })
            .collect::<error_stack::Result<
                HashSet<(PaymentIntentMetricsBucketIdentifier, PaymentIntentMetricRow)>,
                crate::query::PostProcessingError,
            >>()
            .change_context(MetricsError::PostProcessingFailure)
    }
}


// Implementation: impl api::PaymentToken for for Payeezy
// File: crates/hyperswitch_connectors/src/connectors/payeezy.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentToken for for Payeezy


// Function: mobile_payment_next_steps_check
// File: crates/router/src/core/payments/transformers.rs
// Module: router

pub fn mobile_payment_next_steps_check(
    payment_attempt: &storage::PaymentAttempt,
) -> RouterResult<Option<api_models::payments::MobilePaymentNextStepData>>


// Struct: CustomerGeneralUpdate
// File: crates/hyperswitch_domain_models/src/customer.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct CustomerGeneralUpdate


// Struct: CardInfo
// File: crates/hyperswitch_connectors/src/connectors/xendit/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct CardInfo


// Struct: EphemeralKey
// File: crates/diesel_models/src/ephemeral_key.rs
// Module: diesel_models
// Implementations: 1
// Traits: common_utils::events::ApiEventMetric

pub struct EphemeralKey


// Function: increment_blocked_count_in_cache
// File: crates/router/src/services/card_testing_guard.rs
// Module: router

pub fn increment_blocked_count_in_cache<A>(
    state: &A,
    cache_key: &str,
    expiry: i64,
) -> RouterResult<()>
where
    A: SessionStateInfo + Sync,


// Function: error_type
// File: crates/router_derive/src/macros/api_error.rs
// Module: router_derive

pub fn error_type(&self) -> #error_type_enum


// Implementation: impl SecretState for for SecuredSecret
// File: crates/hyperswitch_interfaces/src/secrets_interface/secret_state.rs
// Module: hyperswitch_interfaces
// Methods: 0 total (0 public)

impl SecretState for for SecuredSecret


// Function: get_no_three_ds_account_id
// File: crates/hyperswitch_connectors/src/connectors/paysafe/transformers.rs
// Module: hyperswitch_connectors

pub fn get_no_three_ds_account_id(
        &self,
        currency: Currency,
    ) -> Result<Secret<String>, errors::ConnectorError>


// Function: server
// File: crates/router/src/routes/app.rs
// Module: router

pub fn server(state: AppState) -> Scope


// Struct: DisputeListConstraints
// File: crates/hyperswitch_domain_models/src/disputes.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct DisputeListConstraints


// Struct: Payu
// File: crates/hyperswitch_connectors/src/connectors/payu.rs
// Module: hyperswitch_connectors
// Implementations: 17
// Traits: ConnectorCommon, ConnectorValidation, api::Payment, api::MandateSetup, api::PaymentToken, api::PaymentVoid, api::ConnectorAccessToken, api::PaymentSync, api::PaymentCapture, api::PaymentSession, api::PaymentAuthorize, api::Refund, api::RefundExecute, api::RefundSync, IncomingWebhook, ConnectorSpecifications

pub struct Payu

ConnectorCommon ConnectorValidation api::Payment api::MandateSetup api::PaymentToken api::PaymentVoid api::ConnectorAccessToken api::PaymentSync api::PaymentCapture api::PaymentSession api::PaymentAuthorize api::Refund api::RefundExecute api::RefundSync IncomingWebhook ConnectorSpecifications


// Implementation: impl Trustpay
// File: crates/hyperswitch_connectors/src/connectors/trustpay.rs
// Module: hyperswitch_connectors
// Methods: 1 total (1 public)

impl Trustpay


// Struct: ChargebeeMetadata
// File: crates/hyperswitch_connectors/src/connectors/chargebee/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ChargebeeMetadata


// Implementation: impl api::Refund for for Stripe
// File: crates/hyperswitch_connectors/src/connectors/stripe.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::Refund for for Stripe


// Function: validate_and_create_refund
// File: crates/router/src/core/refunds.rs
// Module: router

pub fn validate_and_create_refund(
    state: &SessionState,
    merchant_context: &domain::MerchantContext,
    payment_attempt: &storage::PaymentAttempt,
    payment_intent: &storage::PaymentIntent,
    refund_amount: MinorUnit,
    req: refunds::RefundRequest,
    creds_identifier: Option<String>,
) -> RouterResult<refunds::RefundResponse>


// Struct: Source
// File: crates/hyperswitch_connectors/src/connectors/checkout/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct Source


// Struct: CoingatePaymentsResponse
// File: crates/hyperswitch_connectors/src/connectors/coingate/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct CoingatePaymentsResponse


// Struct: PaymentData
// File: crates/router/src/core/payments.rs
// Module: router
// Implementations: 1

pub struct PaymentData<F>


// Struct: RoutableConnectors
// File: crates/router/src/core/routing.rs
// Module: router
// Implementations: 1

pub struct RoutableConnectors


// Implementation: impl api::PaymentVoid for for Bitpay
// File: crates/hyperswitch_connectors/src/connectors/bitpay.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentVoid for for Bitpay


// Trait: RefundDistributionAnalytics
// File: crates/analytics/src/refunds/distribution.rs
// Module: analytics

pub trait RefundDistributionAnalytics: LoadRow<RefundDistributionRow>


// Implementation: impl api::PaymentToken for for Blackhawknetwork
// File: crates/hyperswitch_connectors/src/connectors/blackhawknetwork.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentToken for for Blackhawknetwork


// Struct: ResponseRouterData
// File: crates/pm_auth/src/types.rs
// Module: pm_auth
// Implementations: 0

pub struct ResponseRouterData<Flow, R, Request, Response>


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

pub fn get_connector_image_link(self, base_url: &str) -> String


// Implementation: impl PaymentVoid for for Payone
// File: crates/hyperswitch_connectors/src/connectors/payone.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl PaymentVoid for for Payone


// Implementation: impl RequestIdStore for for MockDb
// File: crates/router/src/db.rs
// Module: router
// Methods: 0 total (0 public)

impl RequestIdStore for for MockDb


// Implementation: impl ForeignIDRef for for PaymentAttempt
// File: crates/hyperswitch_domain_models/src/payments/payment_attempt.rs
// Module: hyperswitch_domain_models
// Methods: 1 total (0 public)

impl ForeignIDRef for for PaymentAttempt


// Implementation: impl ConnectorSpecifications for for Gocardless
// File: crates/hyperswitch_connectors/src/connectors/gocardless.rs
// Module: hyperswitch_connectors
// Methods: 4 total (0 public)

impl ConnectorSpecifications for for Gocardless


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

impl api::PaymentSession for for Adyen


// Implementation: impl MasterKeyInterface for for KafkaStore
// File: crates/router/src/db/kafka_store.rs
// Module: router
// Methods: 1 total (0 public)

impl MasterKeyInterface for for KafkaStore


// Struct: SantanderCard
// File: crates/hyperswitch_connectors/src/connectors/santander/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct SantanderCard


// Struct: NordeaErrorBody
// File: crates/hyperswitch_connectors/src/connectors/nordea/responses.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct NordeaErrorBody