package xyz.r0r5chach.dermy_app

import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.widget.EditText
import android.widget.Toast
import androidx.fragment.app.findFragment
import androidx.preference.Preference
import androidx.preference.PreferenceManager
import androidx.preference.PreferenceViewHolder
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import okhttp3.MediaType
import okhttp3.RequestBody
import org.json.JSONObject
import xyz.r0r5chach.dermy_app.api.DermyApi
import xyz.r0r5chach.dermy_app.fragments.SettingsFragment


@DelicateCoroutinesApi
class AccountPreference @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
): Preference(context, attrs, defStyleAttr) {
    private val preferences = PreferenceManager.getDefaultSharedPreferences(context)
    private lateinit var usernameField: EditText
    private lateinit var passwordField: EditText
    private lateinit var loggedIn: List<View>
    private lateinit var loggedOut: List<View>

    init {
        widgetLayoutResource = R.layout.fragment_account
    }

    override fun onBindViewHolder(holder: PreferenceViewHolder) {
        super.onBindViewHolder(holder)
        usernameField = holder.findViewById(R.id.username_field) as EditText
        passwordField = holder.findViewById(R.id.password_field) as EditText

        val loginButton = holder.findViewById(R.id.login_button)
        val registerButton = holder.findViewById(R.id.register_button)
        val logOutButton = holder.findViewById(R.id.logout_button)
        val backupButton = holder.findViewById(R.id.backup_button)
        val restoreButton = holder.findViewById(R.id.restore_button)

        loggedIn = listOf(backupButton, restoreButton, logOutButton)
        loggedOut = listOf(usernameField, passwordField, loginButton, registerButton)

        checkSet()

        loginButton.setOnClickListener {
            val api = DermyApi(preferences.getString("instance_url", null)!!).getInstance()
            val toast = Toast.makeText(context, "User does not exist", Toast.LENGTH_SHORT)
            GlobalScope.launch {
                try {
                    val saltRes = api.getSalt(usernameField.text.toString())

                    if (saltRes.containsKey("_salt")) {
                        val salt = saltRes["_salt"]
                        val hashedPassword = "abc" //TODO: Hash password
                        val body =
                            RequestBody.create(
                                MediaType.get("application/json"),JSONObject()
                                .put("username", usernameField.text.toString())
                                .put("_auth", JSONObject().put("_hash", hashedPassword)).toString())


                        val loginRes = api.login(body)

                        if (loginRes.containsKey("_api_key")) {
                            preferences.edit()
                                .putString("api_key", loginRes["_api_key"])
                                .apply()
                            toast.setText("Login successful")
                            toast.show()
                            back()
                        } else {
                            toast.show()
                        }
                    } else {
                        toast.show()
                    }
                }
                catch(e: Exception) {
                    Log.d("$e", "$e")
                    toast.setText("Login request has failed")
                    toast.show()
                }
            }
        }

        registerButton.setOnClickListener {
            val api = DermyApi(preferences.getString("instance_url", null)!!).getInstance()
            val toast = Toast.makeText(context, "User already exists", Toast.LENGTH_SHORT)
            GlobalScope.launch {
                try {
                    val salt = "1234" //TODO: Make salt
                    val hashedPassword = "abc" //TODO: hash password
                    val body =
                        RequestBody.create(MediaType.get("application/json"),
                            JSONObject()
                                .put("username", usernameField.text.toString())
                                .put("_auth", JSONObject().put("_salt", salt).put("_hash", hashedPassword))
                                .toString())
                    val registerRes = api.register(body)

                    if (registerRes.containsKey("_success")) {
                        toast.setText("Registration successful")
                        toast.show()
                    } else {
                        toast.show()
                    }
                }
                catch (e: Exception) {
                    Log.d("$e", "$e")
                    toast.setText("Registration request failed")
                    toast.show()
                }
            }
        }

        logOutButton.setOnClickListener {
            val api = DermyApi(preferences.getString("instance_url", null)!!).getInstance()
            val toast = Toast.makeText(context, "Your API key does not belong to any user", Toast.LENGTH_SHORT)

            GlobalScope.launch {
                try {
                    val key = preferences.getString("api_key", null)!!
                    preferences.edit().remove("api_key").apply()


                    val logoutRes = api.logout(key)
                    if (logoutRes.containsKey("_success")) {
                        toast.setText("Logout successful")
                        toast.show()
                        back()
                    } else {
                        toast.show()
                    }
                }
                catch (e: Exception) {
                    Log.d("$e", "$e")
                    toast.setText("Logout request failed")
                    toast.show()
                }
            }
        }

        backupButton.setOnClickListener {
            //TODO: Handle Backup

            Toast.makeText(context, "Backup Button Pressed", Toast.LENGTH_SHORT).show() //TODO: Change text to relevant message
        }

        restoreButton.setOnClickListener {
            //TODO: Handle Restore
            Toast.makeText(context, "Restore Button Pressed", Toast.LENGTH_SHORT).show() //TODO: Change text to relevant message
        }
    }
    private fun checkSet() {
        if(preferences.getString("api_key", null) != null) {
            changeView(loggedIn, loggedOut)
        }
        else {
            changeView(loggedOut, loggedIn)
        }
    }

    private fun changeView(show: List<View>, hide: List<View>) {
        show.forEach { it.visibility = View.VISIBLE }
        hide.forEach { it.visibility = View.GONE }
    }

    private fun back() {
        usernameField.findFragment<SettingsFragment>().parentFragmentManager.popBackStack()
    }
}
