/*
 * Created by WebID Solutions GmbH | www.webid-solutions.de.
 * See the file "LICENSE" for the full license governing this code.
 */
package de.webidsolutions.metaplugindemo

import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.ActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import de.webidsolutions.auto_ident_product_plugin.AutoIdProductPlugin
import de.webidsolutions.eid_product_plugin.EIdProductPlugin
import de.webidsolutions.meta_plugin.EMetaPluginFailReason
import de.webidsolutions.meta_plugin.WebIdMetaPlugin
import de.webidsolutions.metaplugindemo.scenes.MetaPluginDemoScreen
import de.webidsolutions.metaplugindemo.scenes.ThemingChoice
import de.webidsolutions.metaplugindemo.tasks.EApiResult
import de.webidsolutions.metaplugindemo.tasks.MetaPluginVerifyTask
import de.webidsolutions.mobile_app.sdk.WebIdMobileAppSdkException
import de.webidsolutions.mobile_app.sdk.WebIdSdkEnvironment
import de.webidsolutions.mobile_app.sdk.domain.VerifyActionIdResult
import de.webidsolutions.mobile_app.sdk.impl.AsyncTaskResultGeneric
import de.webidsolutions.pay_ident_product_plugin.AccountIdProductPlugin
import de.webidsolutions.plugin_core.EProductPluginErrors
import de.webidsolutions.plugin_core.IEPluginError
import de.webidsolutions.plugin_core.IProductPluginWebId
import de.webidsolutions.plugin_core.IProductPluginWebId.Companion.getProductPluginResult
import de.webidsolutions.plugin_core.ProductPluginErrorResult
import de.webidsolutions.plugin_core.ProductPluginResult
import de.webidsolutions.plugin_core.WebIdPluginInterruptedException
import de.webidsolutions.video_ident.plugin.videocall.VideoOptionsConfig
import de.webidsolutions.video_ident_product_plugin.VideoIdProductFailReason
import de.webidsolutions.video_ident_product_plugin.VideoIdProductPlugin
import java.lang.Integer.parseInt
import java.net.URI

// TODO set your configs
private val config = VideoOptionsConfig(
    true,
    false,
    false
)

// TODO insert your Action id
private const val actionId = "348758601"

// TODO choose your environment
private val chosenEnvironment: EWebIDEnv = EWebIDEnv.TEST
// private val chosenEnvironment: EWebIDEnv = EWebIDEnv.PRODUCTION

/**
 * Demo App which starts the [MetaPlugin] and handles its result.
 */
internal class MainActivity : ComponentActivity
    () {

    private var logText by mutableStateOf("")


//    private lateinit var coreSdk: IWebIdMobileAppSdk

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MaterialTheme {
                MetaPluginDemoScreen(
                    logText = logText,
                    onStartClicked = { useAutoIdent, usePayOnServer, useEidOnServer, useVideo, themingChoice ->
                        clearLog()
                        writeLog(getString(R.string.starting))
                        createCoreSdk(
                            useAutoIdent = useAutoIdent,
                            usePayOnServer = usePayOnServer,
                            useEidOnServer = useEidOnServer,
                            useVideo = useVideo,
                            themingChoice = themingChoice
                        )
                    }
                )
            }
        }

    }

    /* CORE SDK */

    /**
     * Creates the Core SDK from the existing credentials.
     */
    private fun createCoreSdk(
        useAutoIdent: Boolean,
        usePayOnServer: Boolean,
        useEidOnServer: Boolean,
        useVideo: Boolean,
        themingChoice: ThemingChoice
    ) {
        writeLog(getString(R.string.creating_core_sdk))

        // should be provided to you -> currently just using demo credentials
        val selectedUri: URI = chosenEnvironment.uri
        val username: String = chosenEnvironment.username
        val apiKey: String = chosenEnvironment.apiKey

        // actual creation of the core SDK
        val environment = WebIdSdkEnvironment(
            selectedUri,
            *chosenEnvironment.shaPins
        )

        writeLog(getString(R.string.core_sdk_creation_successful))
        validateActionId()

        val selectProductPlugins = getSelectedPlugins(
            useAutoIdent = useAutoIdent,
            usePayOnServer = usePayOnServer,
            useEidOnServer = useEidOnServer,
            useVideo = useVideo
        )

        val metaPlugin = WebIdMetaPlugin(
            environment,
            username,
            apiKey,
            this.applicationContext,
            selectProductPlugins
        )
        MetaPluginVerifyTask(metaPlugin)
            .setOnPostExecuteCallback(
                metaPluginVerifyCallback(
                    metaPlugin = metaPlugin,
                    themingChoice = themingChoice
                )
            )
            .execute(actionId)
    }

    /**
     * Validates the WebID actionID
     */
    private fun validateActionId() {
        writeLog(getString(R.string.validate_action_id))

        try {
            parseInt(actionId)
            if (actionId.length != 9) {
                throw NumberFormatException()
            }
        } catch (e: NumberFormatException) {
            writeLog(getString(R.string.action_id_not_valid))
        }
    }

    // add result launcher for intent
    private val activityResultLauncher = registerForActivityResult(
        ActivityResultContracts.StartActivityForResult(),
        this::onPluginResultCallback
    )

    private fun getSelectedPlugins(
        useAutoIdent: Boolean,
        usePayOnServer: Boolean,
        useEidOnServer: Boolean,
        useVideo: Boolean
    ): ArrayList<IProductPluginWebId> {
        return ArrayList(
            listOfNotNull(
               if (useAutoIdent) AutoIdProductPlugin() else null,
                if (usePayOnServer) AccountIdProductPlugin() else null,
                if (useEidOnServer) EIdProductPlugin() else null,
                if (useVideo) VideoIdProductPlugin(config) else null,
            )
        )
    }

    private fun metaPluginVerifyCallback(metaPlugin: WebIdMetaPlugin,
                                         themingChoice: ThemingChoice
    ): (AsyncTaskResultGeneric<VerifyActionIdResult?, EApiResult>) -> Unit {

        return { result ->
            if (result.errorResult == EApiResult.SUCCESS) {
                try {
                    when (themingChoice) {
                        ThemingChoice.XML -> {
                            metaPlugin.startPlugin(
                                this,
                                activityResultLauncher,
                                true
                            )
                        }

                        ThemingChoice.COMPOSE -> {
                                metaPlugin.startPlugin(
                                    this,
                                    activityResultLauncher,
                                    null,
                                    null
                                )
                        }
                    }
                } catch (e: WebIdMobileAppSdkException) {
                    e.printStackTrace()
                    writeLog(e.message.toString())
                }
            } else {
                val metaPluginVerifyError = result.errorResult
                writeLog(metaPluginVerifyError.toString())
            }
        }
    }

    private fun onPluginResultCallback(activityResult: ActivityResult) {
        var result: String?
        try {
            // Get data and handle potential null case
            // If data is null, plugin was interrupted
            val data: Intent = activityResult.data ?: throw WebIdPluginInterruptedException()
            // Retrieve the plugin result and handle any errors
            val pluginResult: ProductPluginResult<*> = getProductPluginResult<IEPluginError>(
                data, activityResult.resultCode
            )
            val resultInfo: String? = pluginResult.info
            val failReason: ProductPluginErrorResult<*>? = pluginResult.error
            // Successful plugin execution
            if (failReason == null) {
                result = "Success"
                if (resultInfo != null) {
                    result += " $resultInfo"
                    // your code to handle the successful plugin execution
                }
                writeLog(result)
            } else {
                // failure case
                if (failReason.specificResult != null) {
                    val specificResult: IEPluginError? =
                        failReason.specificResult as IEPluginError?
                    // handle EMetaPluginFailReason
                    if (specificResult is EMetaPluginFailReason) {
                        if (specificResult == EMetaPluginFailReason.EID_PENDING_AUTHADA) {
                            // handle EID_PENDING_AUTHADA as described in code documentation
                            writeLog("EID_PENDING_AUTHADA")
                        } else {
                            // handle all other EMetaPluginFailReason as described in code documentation
                            writeLog("MetaPluginFailReason: $specificResult")
                        }
                    } else {
                        // handle EVideoIdentProductPluginFailReasons
                        if (specificResult is VideoIdProductFailReason) {
                            if (specificResult == VideoIdProductFailReason.CALL_CENTER_CLOSED) {
                                // handle CALL_CENTER_CLOSED as described in code documentation
                                writeLog("CALL_CENTER_CLOSED")
                            } else {
                                // handle all other EVideoIdentProductPluginFailReasons errors as described in the code documentation
                                writeLog("VideoIdentFailReason: $specificResult")
                            }
                        }
                    }
                } else {
                    if (failReason.genericResult == EProductPluginErrors.UNKNOWN) {
                        // handle UNKNOWN as described in code documentation
                        writeLog("Unknown Error")
                    } else {
                        // handle all other EProductPluginErrors errors as described in the code documentation
                        writeLog("Error: ${failReason.genericResult}")
                    }
                }
            }
        } catch (e: WebIdPluginInterruptedException) {
            // Handle interruption in your preferred way
            writeLog("Plugin interrupted: ${e.message}")
        }
    }

    /* MISC */

    /**
     * Add an entry to the log.
     */
    @SuppressLint("SetTextI18n")
    private fun writeLog(entry: String) {
        logText += "$entry\n"
    }

    /**
     * Resets the text log of this activity.
     */
    private fun clearLog() {
        logText = ""
    }

}