package com.myidsdk import android.content.Context import com.facebook.react.bridge.ReadableMap import uz.myid.android.sdk.capture.MyIdConfig import uz.myid.android.sdk.capture.model.MyIdCameraResolution import uz.myid.android.sdk.capture.model.MyIdCameraSelector import uz.myid.android.sdk.capture.model.MyIdCameraShape import uz.myid.android.sdk.capture.model.MyIdEntryType import uz.myid.android.sdk.capture.model.MyIdEnvironment import uz.myid.android.sdk.capture.model.MyIdImageFormat import uz.myid.android.sdk.capture.model.MyIdLocale import uz.myid.android.sdk.capture.model.MyIdOrganizationDetails import uz.myid.android.sdk.capture.model.MyIdResidency import uz.myid.android.sdk.capture.model.MyIdScreenOrientation /** * Translates the JS config payload into a [MyIdConfig]. * * A `withX(...)` call only happens when the key is actually present, so an * omitted option keeps the SDK's own default instead of being overwritten with * a value invented here. * * Unrecognised enum strings fall back to the SDK default rather than throwing — * a typo should not hard-fail a verification the user already started. */ internal object MyidSdkConfigMapper { fun build(config: ReadableMap, context: Context): MyIdConfig { val builder = MyIdConfig.Builder(config.requireString("sessionId")) .withClientHash( config.requireString("clientHash"), config.requireString("clientHashId") ) config.optInt("minAge")?.let { builder.withMinAge(it) } config.optDouble("distance")?.let { builder.withDistance(it.toFloat()) } config.optBoolean("withSoundGuides")?.let { builder.withSoundGuides(it) } config.optBoolean("showErrorScreen")?.let { builder.withErrorScreen(it) } config.optString("huaweiAppId")?.let { builder.withHuaweiAppId(it) } config.optEnum("environment")?.let { builder.withEnvironment( when (it) { "DEBUG" -> MyIdEnvironment.Debug else -> MyIdEnvironment.Production } ) } config.optEnum("entryType")?.let { builder.withEntryType( when (it) { "FACE_DETECTION" -> MyIdEntryType.FaceDetection "VIDEO_IDENTIFICATION" -> MyIdEntryType.VideoIdentification else -> MyIdEntryType.Identification } ) } config.optEnum("residency")?.let { builder.withResidency( when (it) { "USER_DEFINED" -> MyIdResidency.UserDefined "NON_RESIDENT" -> MyIdResidency.NonResident else -> MyIdResidency.Resident } ) } config.optEnum("locale")?.let { builder.withLocale( when (it) { "UZBEK_CYRILLIC" -> MyIdLocale.UzbekCyrillic "KARAKALPAK" -> MyIdLocale.Karakalpak "TAJIK" -> MyIdLocale.Tajik "ENGLISH" -> MyIdLocale.English "RUSSIAN" -> MyIdLocale.Russian else -> MyIdLocale.Uzbek } ) } config.optEnum("cameraShape")?.let { builder.withCameraShape( when (it) { "ELLIPSE" -> MyIdCameraShape.Ellipse else -> MyIdCameraShape.Circle } ) } config.optEnum("cameraSelector")?.let { builder.withCameraSelector( when (it) { "BACK" -> MyIdCameraSelector.Back else -> MyIdCameraSelector.Front } ) } config.optEnum("cameraResolution")?.let { builder.withCameraResolution( when (it) { "HIGH" -> MyIdCameraResolution.High else -> MyIdCameraResolution.Low } ) } config.optEnum("imageFormat")?.let { builder.withImageFormat( when (it) { "JPEG" -> MyIdImageFormat.JPEG else -> MyIdImageFormat.PNG } ) } config.optEnum("screenOrientation")?.let { builder.withScreenOrientation( when (it) { "LANDSCAPE" -> MyIdScreenOrientation.Landscape "FULL" -> MyIdScreenOrientation.Full else -> MyIdScreenOrientation.Portrait } ) } config.optMap("organizationDetails")?.let { details -> builder.withOrganizationDetails( MyIdOrganizationDetails( phoneNumber = details.optString("phone"), logo = details.optString("logo")?.let { context.drawableIdOrNull(it) } ) ) } return builder.build() } private fun ReadableMap.requireString(key: String): String = optString(key) ?: throw IllegalArgumentException("Missing required config field: $key") private fun ReadableMap.optString(key: String): String? = if (hasKey(key) && !isNull(key)) getString(key) else null /** Enum values travel as strings; normalise case so 'debug' works like 'DEBUG'. */ private fun ReadableMap.optEnum(key: String): String? = optString(key)?.uppercase() private fun ReadableMap.optInt(key: String): Int? = if (hasKey(key) && !isNull(key)) getDouble(key).toInt() else null private fun ReadableMap.optDouble(key: String): Double? = if (hasKey(key) && !isNull(key)) getDouble(key) else null private fun ReadableMap.optBoolean(key: String): Boolean? = if (hasKey(key) && !isNull(key)) getBoolean(key) else null private fun ReadableMap.optMap(key: String): ReadableMap? = if (hasKey(key) && !isNull(key)) getMap(key) else null /** Resolves a drawable by name; a missing asset degrades to no logo. */ private fun Context.drawableIdOrNull(name: String): Int? = resources.getIdentifier(name, "drawable", packageName).takeIf { it != 0 } }