package com.moneyhash.reactnativesdk import com.moneyhash.sdk.android.common.IntentType import com.moneyhash.sdk.android.model.IntentDetails import com.moneyhash.sdk.android.model.MethodsResult import com.moneyhash.sdk.android.model.embed.EmbedStyle import com.moneyhash.shared.datasource.network.model.common.MethodMetaData import com.moneyhash.shared.datasource.network.model.payment.methods.IntentMethods import com.moneyhash.shared.datasource.network.model.payment.methods.MethodType import com.moneyhash.shared.datasource.network.model.vault.VaultData import com.moneyhash.shared.securevault.fields.FieldType import com.moneyhash.sdk.android.common.locale.SDKLocale import com.moneyhash.sdk.android.googlePay.NativeGooglePayConfig import com.moneyhash.sdk.android.model.receipt.NativePayReceipt import com.moneyhash.shared.datasource.network.model.IntentOperation import com.moneyhash.shared.datasource.network.model.customfields.CustomFieldValue import com.moneyhash.shared.datasource.network.model.discount.DiscountData import com.moneyhash.shared.datasource.network.model.discount.DiscountItem import com.moneyhash.shared.datasource.network.model.fees.FeeItem import com.moneyhash.shared.datasource.network.model.fees.FeesData import com.moneyhash.shared.datasource.network.model.payment.IntentStateDetails import com.moneyhash.shared.datasource.network.model.payment.LookupData import com.moneyhash.shared.datasource.network.model.payment.installment.InstallmentPlan import com.moneyhash.shared.datasource.network.model.payment.installment.InstallmentPlanData import com.moneyhash.shared.datasource.network.model.vault.CardFieldState import com.moneyhash.shared.datasource.network.model.vault.CardFormState import com.moneyhash.shared.securevault.models.CardFormConfiguration import com.moneyhash.shared.util.extensions.JsonWithIgnoredUnknownKeys import kotlinx.serialization.encodeToString import kotlinx.serialization.json.JsonArray import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonNull import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonPrimitive import kotlinx.serialization.json.decodeFromJsonElement internal object DataConverter { internal fun getMethodMetaData(data: Map?): MethodMetaData? { if (data.isNullOrEmpty()) return null val cvv = data["cvv"] as? String return MethodMetaData(cvv = cvv) } internal fun getVaultData(data: Map?): VaultData? { if (data.isNullOrEmpty()) return null try { val json = data.toJsonObject() return JsonWithIgnoredUnknownKeys.decodeFromJsonElement(json) } catch (throwable: Throwable) { return null } } internal fun getNativePayReceipt(receiptData: Map?): NativePayReceipt? { if (receiptData.isNullOrEmpty()) return null try { val json = receiptData.toJsonObject() return JsonWithIgnoredUnknownKeys.decodeFromJsonElement(json) } catch (throwable: Throwable) { return null } } internal fun getInstallmentPlanData(installmentPlanData: Map?): InstallmentPlanData? { if (installmentPlanData.isNullOrEmpty()) return null try { val json = installmentPlanData.toJsonObject() return JsonWithIgnoredUnknownKeys.decodeFromJsonElement(json) } catch (throwable: Throwable) { return null } } internal fun getNativeGooglePayConfig(config: Map?): NativeGooglePayConfig? { if (config.isNullOrEmpty()) return null try { val json = config.toJsonObject() return JsonWithIgnoredUnknownKeys.decodeFromJsonElement(json) } catch (throwable: Throwable) { return null } } internal fun getNativePayReceiptJson(receipt: NativePayReceipt?): String? { if (receipt == null) return null return JsonWithIgnoredUnknownKeys.encodeToString(receipt) } internal fun getVaultDataJson(vaultData: VaultData?): String? { if (vaultData == null) return null return JsonWithIgnoredUnknownKeys.encodeToString(vaultData) } internal fun getMethodType(type: String?): MethodType { return if (type.isNullOrEmpty()) return MethodType.PAYMENT_METHOD else MethodType.from(type) } internal fun getIntentType(type: String?): IntentType { return if (type.equals("Payout", true)) IntentType.Payout else IntentType.Payment } internal fun getIntentOperation(operation: String?): IntentOperation? { return if (operation.isNullOrEmpty()) null else IntentOperation.from(operation) } internal fun getCardFormStateJson(cardFormResult: CardFormState?): String? { if (cardFormResult == null) return null return JsonWithIgnoredUnknownKeys.encodeToString(cardFormResult) } internal fun getIntentMethodResultJson( methodsResult: MethodsResult ): String { return JsonWithIgnoredUnknownKeys.encodeToString(methodsResult) } internal fun getIntentMethodJson(intentMethods: IntentMethods?): String? { if (intentMethods == null) return null return JsonWithIgnoredUnknownKeys.encodeToString(intentMethods) } internal fun getIntentDetailsJson(intentDetails: IntentDetails?): String? { if (intentDetails == null) return null return JsonWithIgnoredUnknownKeys.encodeToString(intentDetails) } internal fun getCardFieldStateJson(cardFieldState: CardFieldState?): String? { if (cardFieldState == null) return null return JsonWithIgnoredUnknownKeys.encodeToString(cardFieldState) } internal fun getIntentStateDetailsJson(intentStateDetails: IntentStateDetails?): String? { if (intentStateDetails == null) return null return JsonWithIgnoredUnknownKeys.encodeToString(intentStateDetails) } internal fun getLookupDataJson(lookupData: LookupData?): String? { if (lookupData == null) return null return JsonWithIgnoredUnknownKeys.encodeToString(lookupData) } internal fun getEmbedStyleJson(embedStyle: EmbedStyle) = JsonWithIgnoredUnknownKeys.encodeToString(embedStyle) internal fun getEmbedStyle(data: Map?): EmbedStyle? { if (data.isNullOrEmpty()) return null try { val json = data.toJsonObject() return JsonWithIgnoredUnknownKeys.decodeFromJsonElement(json) } catch (throwable: Throwable) { return null } } internal fun getFieldType(type: String?): FieldType { return when (type.orEmpty().lowercase()) { "card_number" -> FieldType.CARD_NUMBER "card_holder_name" -> FieldType.CARD_HOLDER_NAME "expiry_year" -> FieldType.EXPIRE_YEAR "expiry_month" -> FieldType.EXPIRE_MONTH "cvv" -> FieldType.CVV else -> throw IllegalArgumentException("Unknown type: $type") } } internal fun getLocale(locale: String): SDKLocale { return when (locale) { "fr" -> SDKLocale.FRENCH "ar" -> SDKLocale.ARABIC else -> SDKLocale.ENGLISH } } internal fun getFeesItems(fees: List>?): List { if (fees.isNullOrEmpty()) return emptyList() val list = mutableListOf() try { fees.forEach { val json = it.toJsonObject() list.add(JsonWithIgnoredUnknownKeys.decodeFromJsonElement(json)) } return list } catch (throwable: Throwable) { return listOf() } } internal fun getDiscountItem(data: Map?): DiscountItem? { if (data.isNullOrEmpty()) return null try { val json = data.toJsonObject() return JsonWithIgnoredUnknownKeys.decodeFromJsonElement(json) } catch (throwable: Throwable) { return null } } internal fun getFeesDataJson(feesData: FeesData?): String? { if (feesData == null) return null return JsonWithIgnoredUnknownKeys.encodeToString(feesData) } internal fun getDiscountDataJson(discountData: DiscountData?): String? { if (discountData == null) return null return JsonWithIgnoredUnknownKeys.encodeToString(discountData) } internal fun getCustomFields(json: Map?): Map { return json?.mapNotNull { (key, value) -> val valueMap = value as? Map<*, *> val customFieldValue = valueMap?.let { getCustomFieldValue(it) } if (customFieldValue != null) key to customFieldValue else null }?.toMap().orEmpty() } internal fun getInstallmentPlanJson(installmentPlan: InstallmentPlan?): String? { if (installmentPlan == null) return null return JsonWithIgnoredUnknownKeys.encodeToString(installmentPlan) } internal fun getCardFormConfiguration(configuration: Map?): CardFormConfiguration? { if (configuration.isNullOrEmpty()) return null return try { val json = configuration.toJsonObject() JsonWithIgnoredUnknownKeys.decodeFromJsonElement(json) } catch (throwable: Throwable) { null } } internal fun getGooglePayConfig(configuration: Map?): NativeGooglePayConfig? { if (configuration.isNullOrEmpty()) return null return try { val json = configuration.toJsonObject() JsonWithIgnoredUnknownKeys.decodeFromJsonElement(json) } catch (throwable: Throwable) { null } } private fun getCustomFieldValue(json: Map<*, *>): CustomFieldValue? { val type = json["type"] as? String ?: run { println("Error: Missing or invalid 'type'") return null } return when (type.lowercase()) { "number" -> { val value = json["value"] when (value) { is Int -> CustomFieldValue.IntValue(value) is Float -> CustomFieldValue.FloatValue(value) is Double -> { if (value % 1.0 == 0.0) { // Value is effectively an integer CustomFieldValue.IntValue(value.toInt()) } else { CustomFieldValue.DoubleValue(value) } } else -> null } } "boolean" -> { val value = json["value"] as? Boolean if (value != null) { CustomFieldValue.BooleanValue(value) } else { null } } "string" -> { val value = json["value"] as? String if (value != null) { CustomFieldValue.StringValue(value) } else { null } } else -> { null } } } internal fun getBankAccountStatusJson(status: com.moneyhash.sdk.android.bank.BankAccountStatus): String { return JsonWithIgnoredUnknownKeys.encodeToString(status.value) } } internal fun Any?.toJsonElement(): JsonElement { return when (this) { is Number -> JsonPrimitive(this) is Boolean -> JsonPrimitive(this) is String -> JsonPrimitive(this) is Array<*> -> this.toJsonArray() is List<*> -> this.toJsonArray() is Map<*, *> -> this.toJsonObject() is JsonElement -> this else -> JsonNull } } internal fun Array<*>.toJsonArray(): JsonArray { val array = mutableListOf() this.forEach { array.add(it.toJsonElement()) } return JsonArray(array) } internal fun List<*>.toJsonArray(): JsonArray { val array = mutableListOf() this.forEach { array.add(it.toJsonElement()) } return JsonArray(array) } internal fun Map<*, *>.toJsonObject(): JsonObject { val map = mutableMapOf() this.forEach { if (it.key is String) { map[it.key as String] = it.value.toJsonElement() } } return JsonObject(map) }