use common_utils::{pii, types::FloatMajorUnit};
use domain_types::{
    connector_flow::{Authorize, Capture, SetupMandate, Void},
    connector_types::{
        MandateReference, PaymentFlowData, PaymentVoidData, PaymentsAuthorizeData,
        PaymentsCaptureData, PaymentsResponseData, PaymentsSyncData, RefundFlowData,
        RefundSyncData, RefundsData, RefundsResponseData, ResponseId, SetupMandateRequestData,
    },
    errors::{ConnectorError, IntegrationError},
    payment_method_data::{PaymentMethodData, PaymentMethodDataTypes, RawCardNumber},
    router_data::ConnectorSpecificConfig,
    router_data_v2::RouterDataV2,
    router_request_types::SyncRequestType,
};
use error_stack::{Report, ResultExt};
use hyperswitch_masking::Secret;
use serde::{Deserialize, Serialize};

use crate::{connectors::helcim::HelcimRouterData, types::ResponseRouterData};

// Note: HelcimRouterData is generated by the macro, so we don't define it here
// The macro generates: pub struct crate::connectors::helcim::HelcimRouterData<RD: FlowTypes, T: PaymentMethodDataTypes + ..., T> { pub connector: Helcim<T>, pub router_data: RD }

pub fn check_currency(
    currency: common_enums::Currency,
) -> Result<common_enums::Currency, IntegrationError> {
    if currency == common_enums::Currency::USD {
        Ok(currency)
    } else {
        Err(IntegrationError::NotSupported {
            message: format!("currency {currency} is not supported for this merchant account"),
            connector: "Helcim",
            context: Default::default(),
        })
    }
}

// Auth Struct
pub struct HelcimAuthType {
    pub(super) api_key: Secret<String>,
}

impl TryFrom<&ConnectorSpecificConfig> for HelcimAuthType {
    type Error = Report<IntegrationError>;
    fn try_from(auth_type: &ConnectorSpecificConfig) -> Result<Self, Self::Error> {
        match auth_type {
            ConnectorSpecificConfig::Helcim { api_key, .. } => Ok(Self {
                api_key: api_key.to_owned(),
            }),
            _ => Err(IntegrationError::FailedToObtainAuthType {
                context: Default::default(),
            }
            .into()),
        }
    }
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct HelcimPaymentsRequest<
    T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Serialize,
> {
    amount: FloatMajorUnit,
    currency: common_enums::Currency,
    ip_address: Secret<String, pii::IpAddress>,
    card_data: HelcimCard<T>,
    invoice: HelcimInvoice,
    billing_address: HelcimBillingAddress,
    #[serde(skip_serializing_if = "Option::is_none")]
    ecommerce: Option<bool>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct HelcimBillingAddress {
    name: Secret<String>,
    street1: Secret<String>,
    postal_code: Secret<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    street2: Option<Secret<String>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    city: Option<Secret<String>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    email: Option<pii::Email>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct HelcimInvoice {
    invoice_number: String,
    line_items: Vec<HelcimLineItems>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct HelcimLineItems {
    description: String,
    quantity: u8,
    price: FloatMajorUnit,
    total: FloatMajorUnit,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct HelcimCard<
    T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Serialize,
> {
    card_number: RawCardNumber<T>,
    card_expiry: Secret<String>,
    card_c_v_v: Secret<String>,
}

impl<T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Serialize>
    TryFrom<
        HelcimRouterData<
            RouterDataV2<
                Authorize,
                PaymentFlowData,
                PaymentsAuthorizeData<T>,
                PaymentsResponseData,
            >,
            T,
        >,
    > for HelcimPaymentsRequest<T>
{
    type Error = Report<IntegrationError>;
    fn try_from(
        item: HelcimRouterData<
            RouterDataV2<
                Authorize,
                PaymentFlowData,
                PaymentsAuthorizeData<T>,
                PaymentsResponseData,
            >,
            T,
        >,
    ) -> Result<Self, Self::Error> {
        let card_data = match &item.router_data.request.payment_method_data {
            PaymentMethodData::Card(card) => HelcimCard {
                card_expiry: card
                    .get_card_expiry_month_year_2_digit_with_delimiter("".to_string())?,
                card_number: card.card_number.clone(),
                card_c_v_v: card.card_cvc.clone(),
            },
            _ => {
                return Err(IntegrationError::NotImplemented(
                    ("payment method").into(),
                    Default::default(),
                )
                .into())
            }
        };

        let req_address = item
            .router_data
            .resource_common_data
            .get_billing_address()?;

        let billing_address = HelcimBillingAddress {
            name: req_address.get_full_name()?,
            street1: req_address.get_line1()?.to_owned(),
            postal_code: req_address.get_zip()?.to_owned(),
            street2: req_address.line2.clone(),
            city: req_address.city.clone(),
            email: item.router_data.request.email.clone(),
        };

        let ip_address = item.router_data.request.get_ip_address()?;

        let amount = item
            .connector
            .amount_converter
            .convert(
                item.router_data.request.minor_amount,
                item.router_data.request.currency,
            )
            .change_context(IntegrationError::AmountConversionFailed {
                context: Default::default(),
            })?;

        let line_items = vec![HelcimLineItems {
            description: item
                .router_data
                .resource_common_data
                .description
                .clone()
                .unwrap_or("No Description".to_string()),
            quantity: 1,
            price: amount,
            total: amount,
        }];

        let invoice = HelcimInvoice {
            invoice_number: item
                .router_data
                .resource_common_data
                .connector_request_reference_id
                .clone(),
            line_items,
        };

        let currency = check_currency(item.router_data.request.currency)?;

        Ok(Self {
            amount,
            currency,
            ip_address,
            card_data,
            invoice,
            billing_address,
            ecommerce: None,
        })
    }
}

// PaymentsResponse
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum HelcimPaymentStatus {
    Approved,
    Declined,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum HelcimTransactionType {
    Purchase,
    PreAuth,
    Capture,
    Verify,
    Reverse,
}

impl From<HelcimPaymentsResponse> for common_enums::AttemptStatus {
    fn from(item: HelcimPaymentsResponse) -> Self {
        match item.transaction_type {
            HelcimTransactionType::Purchase | HelcimTransactionType::Verify => match item.status {
                HelcimPaymentStatus::Approved => Self::Charged,
                HelcimPaymentStatus::Declined => Self::Failure,
            },
            HelcimTransactionType::PreAuth => match item.status {
                HelcimPaymentStatus::Approved => Self::Authorized,
                HelcimPaymentStatus::Declined => Self::AuthorizationFailed,
            },
            HelcimTransactionType::Capture => match item.status {
                HelcimPaymentStatus::Approved => Self::Charged,
                HelcimPaymentStatus::Declined => Self::CaptureFailed,
            },
            HelcimTransactionType::Reverse => match item.status {
                HelcimPaymentStatus::Approved => Self::Voided,
                HelcimPaymentStatus::Declined => Self::VoidFailed,
            },
        }
    }
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct HelcimPaymentsResponse {
    status: HelcimPaymentStatus,
    transaction_id: u64,
    invoice_number: Option<String>,
    #[serde(rename = "type")]
    transaction_type: HelcimTransactionType,
    #[serde(skip_serializing_if = "Option::is_none")]
    errors: Option<String>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct HelcimMetaData {
    pub preauth_transaction_id: String,
}

impl<T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Serialize>
    TryFrom<ResponseRouterData<HelcimPaymentsResponse, Self>>
    for RouterDataV2<Authorize, PaymentFlowData, PaymentsAuthorizeData<T>, PaymentsResponseData>
{
    type Error = Report<ConnectorError>;
    fn try_from(
        item: ResponseRouterData<HelcimPaymentsResponse, Self>,
    ) -> Result<Self, Self::Error> {
        //PreAuth Transaction ID is stored in connector metadata
        //Initially resource_id is stored as NoResponseID for manual capture
        //After Capture Transaction is completed it is updated to store the Capture ID

        let is_auto_capture = item.router_data.request.is_auto_capture();

        let resource_id = if is_auto_capture {
            ResponseId::ConnectorTransactionId(item.response.transaction_id.to_string())
        } else {
            ResponseId::NoResponseId
        };

        let connector_metadata = if !is_auto_capture {
            Some(serde_json::json!(HelcimMetaData {
                preauth_transaction_id: item.response.transaction_id.to_string()
            }))
        } else {
            None
        };

        let status = common_enums::AttemptStatus::from(item.response.clone());

        Ok(Self {
            response: Ok(PaymentsResponseData::TransactionResponse {
                resource_id,
                redirection_data: None,
                connector_metadata,
                network_txn_id: None,
                network_txn_link_id: None,
                connector_response_reference_id: item.response.invoice_number.clone(),
                incremental_authorization_allowed: None,
                mandate_reference: None,
                status_code: item.http_code,
                splits: None,
            }),
            resource_common_data: PaymentFlowData {
                status,
                ..item.router_data.resource_common_data
            },
            ..item.router_data
        })
    }
}

impl<F> TryFrom<ResponseRouterData<HelcimPaymentsResponse, Self>>
    for RouterDataV2<F, PaymentFlowData, PaymentsSyncData, PaymentsResponseData>
{
    type Error = Report<ConnectorError>;
    fn try_from(
        item: ResponseRouterData<HelcimPaymentsResponse, Self>,
    ) -> Result<Self, Self::Error> {
        match item.router_data.request.sync_type {
            SyncRequestType::SinglePaymentSync => {
                let status = common_enums::AttemptStatus::from(item.response.clone());

                Ok(Self {
                    response: Ok(PaymentsResponseData::TransactionResponse {
                        resource_id: ResponseId::ConnectorTransactionId(
                            item.response.transaction_id.to_string(),
                        ),
                        redirection_data: None,
                        connector_metadata: None,
                        network_txn_id: None,
                        network_txn_link_id: None,
                        connector_response_reference_id: item.response.invoice_number.clone(),
                        incremental_authorization_allowed: None,
                        mandate_reference: None,
                        status_code: item.http_code,
                        splits: None,
                    }),
                    resource_common_data: PaymentFlowData {
                        status,
                        ..item.router_data.resource_common_data
                    },
                    ..item.router_data
                })
            }
            SyncRequestType::MultipleCaptureSync => {
                Err(Report::new(
                    ConnectorError::unexpected_response_error_with_context(
                        item.http_code,
                        Some("manual multiple capture sync not supported".to_string()),
                    ),
                ))
                // let capture_sync_response_list =
                //     utils::construct_captures_response_hashmap(vec![item.response]);
                // Ok(Self {
                //     response: Ok(PaymentsResponseData::MultipleCaptureResponse {
                //         capture_sync_response_list,
                //     }),
                //     ..item.router_data
                // })
            }
        }
    }
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct HelcimCaptureRequest {
    pre_auth_transaction_id: u64,
    amount: FloatMajorUnit,
    ip_address: Secret<String, pii::IpAddress>,
    #[serde(skip_serializing_if = "Option::is_none")]
    ecommerce: Option<bool>,
}

impl<T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Serialize>
    TryFrom<
        HelcimRouterData<
            RouterDataV2<Capture, PaymentFlowData, PaymentsCaptureData, PaymentsResponseData>,
            T,
        >,
    > for HelcimCaptureRequest
{
    type Error = Report<IntegrationError>;
    fn try_from(
        item: HelcimRouterData<
            RouterDataV2<Capture, PaymentFlowData, PaymentsCaptureData, PaymentsResponseData>,
            T,
        >,
    ) -> Result<Self, Self::Error> {
        let ip_address = item.router_data.request.get_ip_address()?;
        let amount = item
            .connector
            .amount_converter
            .convert(
                item.router_data.request.minor_amount_to_capture,
                item.router_data.request.currency,
            )
            .change_context(IntegrationError::AmountConversionFailed {
                context: Default::default(),
            })?;

        Ok(Self {
            pre_auth_transaction_id: item
                .router_data
                .request
                .get_connector_transaction_id()?
                .parse::<u64>()
                .change_context(IntegrationError::RequestEncodingFailed {
                    context: Default::default(),
                })?,
            amount,
            ip_address,
            ecommerce: None,
        })
    }
}

impl<F> TryFrom<ResponseRouterData<HelcimPaymentsResponse, Self>>
    for RouterDataV2<F, PaymentFlowData, PaymentsCaptureData, PaymentsResponseData>
{
    type Error = Report<ConnectorError>;
    fn try_from(
        item: ResponseRouterData<HelcimPaymentsResponse, Self>,
    ) -> Result<Self, Self::Error> {
        let status = common_enums::AttemptStatus::from(item.response.clone());

        Ok(Self {
            response: Ok(PaymentsResponseData::TransactionResponse {
                resource_id: ResponseId::ConnectorTransactionId(
                    item.response.transaction_id.to_string(),
                ),
                redirection_data: None,
                connector_metadata: None,
                network_txn_id: None,
                network_txn_link_id: None,
                connector_response_reference_id: item.response.invoice_number.clone(),
                incremental_authorization_allowed: None,
                mandate_reference: None,
                status_code: item.http_code,
                splits: None,
            }),
            resource_common_data: PaymentFlowData {
                status,
                ..item.router_data.resource_common_data
            },
            ..item.router_data
        })
    }
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct HelcimVoidRequest {
    card_transaction_id: u64,
    ip_address: Secret<String, pii::IpAddress>,
    #[serde(skip_serializing_if = "Option::is_none")]
    ecommerce: Option<bool>,
}

impl<T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Serialize>
    TryFrom<
        HelcimRouterData<
            RouterDataV2<Void, PaymentFlowData, PaymentVoidData, PaymentsResponseData>,
            T,
        >,
    > for HelcimVoidRequest
{
    type Error = Report<IntegrationError>;
    fn try_from(
        item: HelcimRouterData<
            RouterDataV2<Void, PaymentFlowData, PaymentVoidData, PaymentsResponseData>,
            T,
        >,
    ) -> Result<Self, Self::Error> {
        let ip_address = item.router_data.request.get_ip_address()?;

        Ok(Self {
            card_transaction_id: item
                .router_data
                .request
                .connector_transaction_id
                .parse::<u64>()
                .change_context(IntegrationError::RequestEncodingFailed {
                    context: Default::default(),
                })?,
            ip_address,
            ecommerce: None,
        })
    }
}

// Old void implementation removed - using the updated one above

impl<F> TryFrom<ResponseRouterData<HelcimPaymentsResponse, Self>>
    for RouterDataV2<F, PaymentFlowData, PaymentVoidData, PaymentsResponseData>
{
    type Error = Report<ConnectorError>;
    fn try_from(
        item: ResponseRouterData<HelcimPaymentsResponse, Self>,
    ) -> Result<Self, Self::Error> {
        let status = common_enums::AttemptStatus::from(item.response.clone());

        Ok(Self {
            response: Ok(PaymentsResponseData::TransactionResponse {
                resource_id: ResponseId::ConnectorTransactionId(
                    item.response.transaction_id.to_string(),
                ),
                redirection_data: None,
                connector_metadata: None,
                network_txn_id: None,
                network_txn_link_id: None,
                connector_response_reference_id: item.response.invoice_number.clone(),
                incremental_authorization_allowed: None,
                mandate_reference: None,
                status_code: item.http_code,
                splits: None,
            }),
            resource_common_data: PaymentFlowData {
                status,
                ..item.router_data.resource_common_data
            },
            ..item.router_data
        })
    }
}

// SetupMandate Request
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct HelcimSetupMandateRequest<
    T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Serialize,
> {
    amount: FloatMajorUnit,
    currency: common_enums::Currency,
    ip_address: Secret<String, pii::IpAddress>,
    card_data: HelcimCard<T>,
    invoice: HelcimInvoice,
    billing_address: HelcimBillingAddress,
    #[serde(skip_serializing_if = "Option::is_none")]
    ecommerce: Option<bool>,
}

// SetupMandate TryFrom implementation
impl<T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Serialize>
    TryFrom<
        HelcimRouterData<
            RouterDataV2<
                SetupMandate,
                PaymentFlowData,
                SetupMandateRequestData<T>,
                PaymentsResponseData,
            >,
            T,
        >,
    > for HelcimSetupMandateRequest<T>
{
    type Error = Report<IntegrationError>;
    fn try_from(
        item: HelcimRouterData<
            RouterDataV2<
                SetupMandate,
                PaymentFlowData,
                SetupMandateRequestData<T>,
                PaymentsResponseData,
            >,
            T,
        >,
    ) -> Result<Self, Self::Error> {
        let card_data = match &item.router_data.request.payment_method_data {
            PaymentMethodData::Card(card) => HelcimCard {
                card_expiry: card
                    .get_card_expiry_month_year_2_digit_with_delimiter("".to_string())?,
                card_number: card.card_number.clone(),
                card_c_v_v: card.card_cvc.clone(),
            },
            _ => {
                return Err(IntegrationError::NotImplemented(
                    ("payment method").into(),
                    Default::default(),
                )
                .into())
            }
        };

        let req_address = item
            .router_data
            .resource_common_data
            .get_billing_address()?;

        let billing_address = HelcimBillingAddress {
            name: req_address.get_full_name()?,
            street1: req_address.get_line1()?.to_owned(),
            postal_code: req_address.get_zip()?.to_owned(),
            street2: req_address.line2.clone(),
            city: req_address.city.clone(),
            email: item.router_data.request.email.clone(),
        };

        let ip_address = item.router_data.request.get_ip_address()?;

        let amount = item
            .connector
            .amount_converter
            .convert(
                item.router_data
                    .request
                    .minor_amount
                    .unwrap_or(common_utils::types::MinorUnit::new(0)),
                item.router_data.request.currency,
            )
            .change_context(IntegrationError::AmountConversionFailed {
                context: Default::default(),
            })?;

        let line_items = vec![HelcimLineItems {
            description: item
                .router_data
                .resource_common_data
                .description
                .clone()
                .unwrap_or("Setup Mandate".to_string()),
            quantity: 1,
            price: amount,
            total: amount,
        }];

        let invoice = HelcimInvoice {
            invoice_number: item
                .router_data
                .resource_common_data
                .connector_request_reference_id
                .clone(),
            line_items,
        };

        let currency = check_currency(item.router_data.request.currency)?;

        Ok(Self {
            amount,
            currency,
            ip_address,
            card_data,
            invoice,
            billing_address,
            ecommerce: None,
        })
    }
}

// SetupMandate Response implementation
impl<T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Serialize>
    TryFrom<ResponseRouterData<HelcimPaymentsResponse, Self>>
    for RouterDataV2<
        SetupMandate,
        PaymentFlowData,
        SetupMandateRequestData<T>,
        PaymentsResponseData,
    >
{
    type Error = Report<ConnectorError>;
    fn try_from(
        item: ResponseRouterData<HelcimPaymentsResponse, Self>,
    ) -> Result<Self, Self::Error> {
        let status = common_enums::AttemptStatus::from(item.response.clone());
        let mandate_reference = MandateReference {
            connector_mandate_id: Some(item.response.transaction_id.to_string()),
            payment_method_id: None,
            connector_mandate_request_reference_id: None,
            mandate_metadata: None,
        };

        Ok(Self {
            response: Ok(PaymentsResponseData::TransactionResponse {
                resource_id: ResponseId::ConnectorTransactionId(
                    item.response.transaction_id.to_string(),
                ),
                redirection_data: None,
                connector_metadata: None,
                network_txn_id: None,
                network_txn_link_id: None,
                connector_response_reference_id: item.response.invoice_number.clone(),
                incremental_authorization_allowed: None,
                mandate_reference: Some(Box::new(mandate_reference)),
                status_code: item.http_code,
                splits: None,
            }),
            resource_common_data: PaymentFlowData {
                status,
                ..item.router_data.resource_common_data
            },
            ..item.router_data
        })
    }
}

// REFUND:
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct HelcimRefundRequest {
    amount: FloatMajorUnit,
    original_transaction_id: u64,
    ip_address: Secret<String, pii::IpAddress>,
    #[serde(skip_serializing_if = "Option::is_none")]
    ecommerce: Option<bool>,
}

impl<F, T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Serialize>
    TryFrom<HelcimRouterData<RouterDataV2<F, RefundFlowData, RefundsData, RefundsResponseData>, T>>
    for HelcimRefundRequest
{
    type Error = Report<IntegrationError>;
    fn try_from(
        item: HelcimRouterData<
            RouterDataV2<F, RefundFlowData, RefundsData, RefundsResponseData>,
            T,
        >,
    ) -> Result<Self, Self::Error> {
        let original_transaction_id = item
            .router_data
            .request
            .connector_transaction_id
            .parse::<u64>()
            .change_context(IntegrationError::RequestEncodingFailed {
                context: Default::default(),
            })?;

        let ip_address = item.router_data.request.get_ip_address()?;
        let amount = item
            .connector
            .amount_converter
            .convert(
                item.router_data.request.minor_refund_amount,
                item.router_data.request.currency,
            )
            .change_context(IntegrationError::AmountConversionFailed {
                context: Default::default(),
            })?;

        Ok(Self {
            amount,
            original_transaction_id,
            ip_address,
            ecommerce: None,
        })
    }
}

// Old implementation removed - using the updated one above

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum HelcimRefundTransactionType {
    Refund,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RefundResponse {
    status: HelcimPaymentStatus,
    transaction_id: u64,
    #[serde(rename = "type")]
    transaction_type: HelcimRefundTransactionType,
}

impl From<RefundResponse> for common_enums::RefundStatus {
    fn from(item: RefundResponse) -> Self {
        match item.transaction_type {
            HelcimRefundTransactionType::Refund => match item.status {
                HelcimPaymentStatus::Approved => Self::Success,
                HelcimPaymentStatus::Declined => Self::Failure,
            },
        }
    }
}

impl<F> TryFrom<ResponseRouterData<RefundResponse, Self>>
    for RouterDataV2<F, RefundFlowData, RefundsData, RefundsResponseData>
{
    type Error = Report<ConnectorError>;
    fn try_from(item: ResponseRouterData<RefundResponse, Self>) -> Result<Self, Self::Error> {
        Ok(Self {
            response: Ok(RefundsResponseData {
                connector_refund_id: item.response.transaction_id.to_string(),
                refund_status: common_enums::RefundStatus::from(item.response),
                status_code: item.http_code,
                acquirer_reference_number: None,
            }),
            ..item.router_data
        })
    }
}

impl<F> TryFrom<ResponseRouterData<RefundResponse, Self>>
    for RouterDataV2<F, RefundFlowData, RefundSyncData, RefundsResponseData>
{
    type Error = Report<ConnectorError>;
    fn try_from(item: ResponseRouterData<RefundResponse, Self>) -> Result<Self, Self::Error> {
        Ok(Self {
            response: Ok(RefundsResponseData {
                connector_refund_id: item.response.transaction_id.to_string(),
                refund_status: common_enums::RefundStatus::from(item.response),
                status_code: item.http_code,
                acquirer_reference_number: None,
            }),
            ..item.router_data
        })
    }
}

#[derive(Debug, strum::Display, Deserialize, Serialize)]
#[serde(untagged)]
pub enum HelcimErrorTypes {
    StringType(String),
    JsonType(serde_json::Value),
}

#[derive(Debug, Deserialize, Serialize)]
pub struct HelcimPaymentsErrorResponse {
    pub errors: HelcimErrorTypes,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum HelcimErrorResponse {
    Payment(HelcimPaymentsErrorResponse),
    General(String),
}

// Type aliases for different flow responses to avoid duplicate struct generation
pub type HelcimPaymentsSyncResponse = HelcimPaymentsResponse;
pub type HelcimPaymentsCaptureResponse = HelcimPaymentsResponse;
pub type HelcimPaymentsVoidResponse = HelcimPaymentsResponse;
pub type RefundSyncResponse = RefundResponse;
