package kr.co.vividnext.sodalive.user.signup

import android.content.Intent
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.activity.result.contract.ActivityResultContracts
import coil.load
import coil.transform.RoundedCornersTransformation
import com.github.dhaval2404.imagepicker.ImagePicker
import com.jakewharton.rxbinding4.widget.textChanges
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.schedulers.Schedulers
import kr.co.vividnext.sodalive.base.BaseActivity
import kr.co.vividnext.sodalive.common.Constants
import kr.co.vividnext.sodalive.common.LoadingDialog
import kr.co.vividnext.sodalive.common.RealPathUtil
import kr.co.vividnext.sodalive.databinding.ActivitySignupBinding
import kr.co.vividnext.sodalive.extensions.dpToPx
import kr.co.vividnext.sodalive.main.MainActivity
import kr.co.vividnext.sodalive.settings.terms.TermsActivity
import kr.co.vividnext.sodalive.user.Gender
import org.koin.android.ext.android.inject

class SignUpActivity : BaseActivity<ActivitySignupBinding>(ActivitySignupBinding::inflate) {

    private val viewModel: SignUpViewModel by inject()
    private val onBackPressedCallback = object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            onClickBackButton()
        }
    }

    private lateinit var loadingDialog: LoadingDialog

    private val imageResult =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            val resultCode = result.resultCode
            val data = result.data

            if (resultCode == RESULT_OK) {
                // Image Uri will not be null for RESULT_OK
                val fileUri = data?.data!!
                binding.ivProfile.background = null
                binding.ivProfile.load(fileUri) {
                    crossfade(true)
                    transformations(RoundedCornersTransformation(13.3f.dpToPx()))
                }
                viewModel.profileImageUri = fileUri
            } else if (resultCode == ImagePicker.RESULT_ERROR) {
                Toast.makeText(this, ImagePicker.getError(data), Toast.LENGTH_SHORT).show()
            }
        }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        onBackPressedDispatcher.addCallback(this, onBackPressedCallback)

        viewModel.getRealPathFromURI = {
            RealPathUtil.getRealPath(applicationContext, it)
        }

        bindData()
    }

    override fun setupView() {
        binding.toolbar.tvBack.text = "회원가입"
        binding.toolbar.tvBack.setOnClickListener { onClickBackButton() }

        loadingDialog = LoadingDialog(this, layoutInflater)

        binding.ivPhotoPicker.setOnClickListener {
            ImagePicker.with(this)
                .crop()
                .galleryOnly()
                .galleryMimeTypes( // Exclude gif images
                    mimeTypes = arrayOf(
                        "image/png",
                        "image/jpg",
                        "image/jpeg"
                    )
                )
                .createIntent { imageResult.launch(it) }
        }

        binding.tvMale.setOnClickListener {
            viewModel.changeGender(Gender.MALE)
        }

        binding.tvFemale.setOnClickListener {
            viewModel.changeGender(Gender.FEMALE)
        }

        binding.tvNone.setOnClickListener {
            viewModel.changeGender(Gender.NONE)
        }

        binding.tvTermsOfService.setOnClickListener {
            val intent = Intent(applicationContext, TermsActivity::class.java)
            intent.putExtra(Constants.EXTRA_TERMS, Constants.EXTRA_TERMS)
            startActivity(intent)
        }

        binding.tvPrivacyPolicy.setOnClickListener {
            val intent = Intent(applicationContext, TermsActivity::class.java)
            intent.putExtra(Constants.EXTRA_TERMS, Constants.EXTRA_PRIVACY)
            startActivity(intent)
        }

        binding.ivTermsOfService.setOnClickListener {
            viewModel.onClickCheckboxTermsOfService()
        }

        binding.ivPrivacyPolicy.setOnClickListener {
            viewModel.onClickCheckboxPrivacyPolicy()
        }

        binding.tvSignUp.setOnClickListener {
            viewModel.signUp {
                it?.let { Toast.makeText(applicationContext, it, Toast.LENGTH_LONG).show() }
                finishAffinity()
                val nextIntent = Intent(applicationContext, MainActivity::class.java)
                val extras = intent.getBundleExtra(Constants.EXTRA_DATA)
                    ?: if (intent.extras != null) {
                        intent.extras
                    } else {
                        null
                    }
                if (extras != null) {
                    nextIntent.putExtra(Constants.EXTRA_DATA, extras)
                }
                startActivity(nextIntent)
            }
        }
    }

    private fun bindData() {
        compositeDisposable.add(
            binding.etEmail.textChanges().skip(1)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    viewModel.email = it.toString()
                }
        )

        compositeDisposable.add(
            binding.etPassword.textChanges().skip(1)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    viewModel.password = it.toString()
                }
        )

        compositeDisposable.add(
            binding.etPasswordRe.textChanges().skip(1)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    viewModel.passwordRe = it.toString()
                }
        )

        compositeDisposable.add(
            binding.etNickname.textChanges().skip(1)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    viewModel.nickname = it.toString()
                }
        )

        viewModel.isAgreeTermsOfServiceLiveData.observe(this) {
            binding.ivTermsOfService.isSelected = it
        }

        viewModel.isAgreePrivacyPolicyLiveData.observe(this) {
            binding.ivPrivacyPolicy.isSelected = it
        }

        viewModel.genderLiveData.observe(this) {
            binding.tvMale.isSelected = false
            binding.tvFemale.isSelected = false
            binding.tvNone.isSelected = false

            when (it) {
                Gender.MALE -> binding.tvMale.isSelected = true
                Gender.FEMALE -> binding.tvFemale.isSelected = true
                Gender.NONE -> binding.tvNone.isSelected = true
                else -> {
                }
            }
        }

        viewModel.signUpErrorLiveData.observe(this) {
            Toast.makeText(applicationContext, it.message, Toast.LENGTH_LONG).show()

            when (it.errorProperty) {
                "email" -> {
                    viewModel.setStep(step = SignUpViewModel.EmailSignUpStep.STEP_1)
                    binding.etEmail.error = it.message
                    binding.etEmail.requestFocus()
                }

                "password" -> {
                    viewModel.setStep(step = SignUpViewModel.EmailSignUpStep.STEP_1)
                    binding.etPassword.error = it.message
                    binding.etPassword.requestFocus()
                }

                "nickname" -> {
                    binding.etNickname.error = it.message
                    binding.etNickname.requestFocus()
                }
            }
        }

        viewModel.isLoading.observe(this) {
            if (it) {
                loadingDialog.show(screenWidth)
            } else {
                loadingDialog.dismiss()
            }
        }

        viewModel.toastLiveData.observe(this) {
            it?.let { Toast.makeText(applicationContext, it, Toast.LENGTH_LONG).show() }
        }

        viewModel.stepLiveData.observe(this) {
            if (it == SignUpViewModel.EmailSignUpStep.STEP_2) {
                binding.toolbar.tvBack.text = "프로필 설정"
                binding.tvSignUp.text = "회원가입"
                binding.llStep1.visibility = View.GONE
                binding.llStep2.visibility = View.VISIBLE
            } else {
                binding.toolbar.tvBack.text = "회원가입"
                binding.tvSignUp.text = "다음"
                binding.llStep1.visibility = View.VISIBLE
                binding.llStep2.visibility = View.GONE
            }
        }
    }

    private fun onClickBackButton() {
        if (viewModel.stepLiveData.value!! == SignUpViewModel.EmailSignUpStep.STEP_2) {
            viewModel.setStep(SignUpViewModel.EmailSignUpStep.STEP_1)
        } else {
            finish()
        }
    }
}
