package com.seatel.mobilehall.ui.profile.activity

import android.Manifest
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Typeface
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.provider.MediaStore
import android.text.SpannableStringBuilder
import android.text.TextUtils
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.Toast
import androidx.core.content.FileProvider
import androidx.lifecycle.lifecycleScope
import com.android.volley.VolleyError
import com.bumptech.glide.Glide
import com.canhub.cropper.CropImageContract
import com.canhub.cropper.CropImageContractOptions
import com.canhub.cropper.CropImageOptions
import com.canhub.cropper.CropImageView
import com.seatel.mobilehall.BuildConfig
import com.seatel.mobilehall.R
import com.seatel.mobilehall.data.network.SeatelSuperRequest
import com.seatel.mobilehall.databinding.ActivityProfileBinding
import com.seatel.mobilehall.ui.base.activity.BaseActivity
import com.seatel.mobilehall.ui.home.interactor.ProfileInteractor
import com.seatel.mobilehall.ui.home.presenter.ProfilePresenter
import com.seatel.mobilehall.ui.login.activity.LoginActivity
import com.seatel.mobilehall.ui.login.activity.UpdatedSimProfileActivity
import com.seatel.mobilehall.ui.login.model.ProfileModel
import com.seatel.mobilehall.ui.login.model.UploadImageResponse
import com.seatel.mobilehall.ui.profile.fragment.BottomSheetFragment
import com.seatel.mobilehall.ui.profile.interactor.BottomSheetInteractor
import com.seatel.mobilehall.ui.profile.interactor.UploadImageInteractor
import com.seatel.mobilehall.ui.profile.presenter.UploadImagePresenter
import com.seatel.mobilehall.util.Constant.REQUEST_CROP_PHOTO
import com.seatel.mobilehall.util.Constant.REQUEST_LOAD_PHOTO
import com.seatel.mobilehall.util.Constant.REQUEST_TAKE_PHOTO
import com.seatel.mobilehall.util.FileUtils
import com.seatel.mobilehall.util.FontCache
import com.seatel.mobilehall.util.PermissionUtil
import com.seatel.mobilehall.util.SeatelAlertDialog
import com.seatel.mobilehall.util.SeatelUtils
import id.zelory.compressor.Compressor
import id.zelory.compressor.constraint.format
import id.zelory.compressor.constraint.quality
import id.zelory.compressor.constraint.resolution
import kotlinx.coroutines.launch
import java.io.File
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

class ProfileActivity : BaseActivity<ActivityProfileBinding>, View.OnClickListener,
    ProfileInteractor.View,
    BottomSheetInteractor.View, UploadImageInteractor.View {

    private var mCameraRequest: PermissionUtil.PermissionRequestObject? = null
    private var mImageCaptureUri: Uri? = null
    private lateinit var mOutputFile: File
    private lateinit var mBottomSheet: BottomSheetFragment
    private lateinit var mUploadImagePresenter: UploadImagePresenter
    private var compressedImage: File? = null
    private var profileUpdate: Boolean = false
    private var profileUpdateMessage: String = ""

    private var isEdit = false
    private lateinit var mMenu: MenuItem
    private var mDataProfile: ProfileModel? = null

    constructor() : super()

    override fun getViewBinding(): ActivityProfileBinding {
        return ActivityProfileBinding.inflate(layoutInflater)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //     setContentView(R.layout.activity_profile)
        super.activityEnterRightAnimation()
        init()
        if (isNoneSeatel()) {
            binding.viewUpdatedProfile.visibility = View.GONE
            binding.lineBottom.visibility = View.GONE
        }
    }

    override fun onBackPressed() {
        super.onBackPressed()
        super.activityExitLeftAnimation()
        finish()
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {

        val inflater = menuInflater
        inflater.inflate(R.menu.menu_profile, menu)
        this.mMenu = menu.findItem(R.id.edit_menu)

        val customFont = FontCache.getFont(this, Typeface.NORMAL)
        val plain = FontCache.get(this, customFont)

//        val face = Typeface.createFromAsset(assets, "fonts/HelveticaNeue-Regular.ttf")
        val title =
            SpannableStringBuilder(SeatelUtils.translatForDialog(this, getString(R.string.edit)))
        title.setSpan(plain, 0, title.length, 0)
        mMenu.title = title

        if (!isMainAccountLogin()) mMenu.isVisible = false

        return super.onCreateOptionsMenu(menu)
    }


    override fun onGalleryClicked() {
        mBottomSheet.dismiss()
        loadFile()
    }

    override fun onCameraClicked() {
        mBottomSheet.dismiss()
        showCamera()
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {

        if (item.itemId == R.id.edit_menu) updateMenu()
        return super.onOptionsItemSelected(item)
    }

    override fun onLoadDataSucceed(profileModel: ProfileModel) {
        mDataProfile = profileModel
        hideProgress()
        fillDataProfile(profileModel)

    }

    private fun fillDataProfile(profileModel: ProfileModel) {
        if (profileModel.certType.isNotEmpty()) binding.textViewId.text =
            SeatelUtils.translatForDialog(
                this, profileModel.certType
            ) + ": " + profileModel.certNumber
        else {
            binding.viewId.visibility = View.GONE
            binding.lineId.visibility = View.GONE
        }
        if (profileModel.custName.isEmpty()) {
            binding.viewName.visibility = View.GONE
            binding.lineName.visibility = View.GONE
        } else binding.textViewCartName.text = profileModel.custName
        binding.textViewCartPhoneNumber.text = SeatelUtils.phoneNumberFormat(profileModel.msisdn)
        binding.textViewEmail.text = profileModel.email

        if (TextUtils.isEmpty(binding.textViewEmail.text.trim())) binding.layoutEmail.visibility =
            View.GONE

        if (!TextUtils.isEmpty(profileModel.imageUrl)) Glide.with(this).load(profileModel.imageUrl)
            .placeholder(R.drawable.ic_yes_profile).dontAnimate().into(binding.imageViewProfile)

        binding.textViewPassword.visibility = View.VISIBLE

        profileUpdate = profileModel.isCanUpdateProfile
        profileUpdateMessage = profileModel.message
    }

    override fun onLoadDataFailed(error: VolleyError) {
        Log.d("onLoadDataFailed::>>>", "onLoadDataFailed: ${error.message}")
        hideProgress()
        SeatelAlertDialog.with(this, SeatelSuperRequest.getErrorMessageFrom(error)).show()
    }

    private fun init() {
        val profilePresenter = ProfilePresenter(this)
//        mDataProfile = Gson().fromJson<ProfileModel>(SeatelSharePreferences.getConstant(this).userInfo, ProfileModel::class.java)
        if (mDataProfile == null) {
            showProgress()
            profilePresenter.loadData(getPhoneLogin())
        } else fillDataProfile(mDataProfile!!)

        binding.imageViewCamera.setOnClickListener {
            mBottomSheet.show(supportFragmentManager, "BottomSheetFragment")
        }
        mBottomSheet = BottomSheetFragment()
        mBottomSheet.setBottomSheetView(this)
        binding.viewUpdatedProfile.setOnClickListener {
            if (profileUpdate) {
                LoginActivity.launchWithAddNewPhone(this, false, true)
            } else {
                binding.textProfileUpdate.visibility = View.VISIBLE
                binding.textProfileUpdate.text = profileUpdateMessage
            }

        }
    }

    private fun updateMenu() {

        if (isEdit) {
            binding.imageViewEditPass.visibility = View.GONE
            binding.imageViewCamera.visibility = View.GONE
            mMenu.title = SeatelUtils.translatForDialog(this, getString(R.string.edit))
            isEdit = false
        } else {
            binding.imageViewEditPass.visibility = View.VISIBLE
            binding.imageViewCamera.visibility = View.VISIBLE
            mMenu.title = SeatelUtils.translatForDialog(this, getString(R.string.cancel))
            isEdit = true
            binding.imageViewEditPass.setOnClickListener(this)
        }
    }

    override fun onClick(v: View?) {
        ChangePasswordActivity.lunch(this)
    }

    companion object {
        fun lunch(context: Context) {
            val intent = Intent(context, ProfileActivity::class.java)
            context.startActivity(intent)
        }
    }


    private fun showCamera() {

        mCameraRequest = PermissionUtil.with(this).request(
            Manifest.permission.CAMERA
        ).onAllGranted(object : PermissionUtil.Func() {

            override fun call() {
                dispatchTakePictureIntent(REQUEST_TAKE_PHOTO)
            }

        }).onAnyDenied(object : PermissionUtil.Func() {
            override fun call() {
                Toast.makeText(
                    this@ProfileActivity,
                    "Camera permission is needed to open camera.",
                    Toast.LENGTH_LONG
                ).show()
            }
        }).askPermission(99)
    }


    override fun onRequestPermissionsResult(
        requestCode: Int, permissions: Array<out String>, grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        mCameraRequest!!.onRequestPermissionsResult(requestCode, permissions, grantResults)
    }


    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if (resultCode != RESULT_OK) return

        when (requestCode) {

            REQUEST_LOAD_PHOTO -> if (data != null && data.data != null) {
                val actualImage = FileUtils.from(this, data.data)
                lifecycleScope.launch {
                    val compressedImageFile = Compressor.compress(this@ProfileActivity, actualImage)
                    mImageCaptureUri = Uri.fromFile(compressedImageFile)
                    setImageCrop()
                }

            }

            REQUEST_TAKE_PHOTO -> setImageCrop()

            REQUEST_CROP_PHOTO -> setImage()
        }
    }


    override fun onUploadFailed(error: VolleyError) {
        hideProgress()
        SeatelAlertDialog.with(this, SeatelSuperRequest.getErrorMessageFrom(error)).show()
    }

    override fun onUploadSucceed(data: UploadImageResponse) {
        mUploadImagePresenter.onUpdate(getPhoneLogin(), data.data[0].filename)
    }

    override fun onUpdateSucceed() {
        hideProgress()
        isEdit = true
        updateMenu()
        Glide.with(this).load(mOutputFile).dontAnimate().into(binding.imageViewProfile)
    }

    private fun setImage() {
        showProgress()
        mUploadImagePresenter = UploadImagePresenter(this)
        mUploadImagePresenter.onUpload(mOutputFile)
    }

    private val cropImage = registerForActivityResult(CropImageContract()) { result ->
        if (result.isSuccessful) {
            result.uriContent.let {
                val actualImage = FileUtils.from(this, it)
                lifecycleScope.launch {
                    val mCompressFile =
                        Compressor.compress(this@ProfileActivity, actualImage) {
                            resolution(640, 480)
                            quality(90)
                            format(Bitmap.CompressFormat.WEBP)

                        }
                    mOutputFile = mCompressFile
                    setImage()

                }
            }
        }
    }

    private fun setImageCrop() {

        cropImage.launch(
            CropImageContractOptions(
                uri = mImageCaptureUri,
                cropImageOptions = CropImageOptions(
                    guidelines = CropImageView.Guidelines.ON,
                    outputCompressFormat = Bitmap.CompressFormat.PNG
                )
            )
        )
    }


    private fun dispatchTakePictureIntent(requestCode: Int) {

        val intentTakePhoto = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
        val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
        val imageFileName = "IMG_$timeStamp.jpg"
        try {
            val f = File.createTempFile(
                "IMG_$timeStamp", ".jpg", getExternalFilesDir(Environment.DIRECTORY_PICTURES)
            )
            mImageCaptureUri =
                FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".provider", f)
            intentTakePhoto.putExtra(MediaStore.EXTRA_OUTPUT, mImageCaptureUri)
            intentTakePhoto.putExtra("listPhotoName", imageFileName)
            startActivityForResult(intentTakePhoto, requestCode)
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

    private fun loadFile() {

        var intent: Intent? = null

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            mCameraRequest = PermissionUtil.with(this).request(
                Manifest.permission.READ_MEDIA_IMAGES
            ).onAllGranted(object : PermissionUtil.Func() {

                override fun call() {
                    if (intent != null) return
                    intent =
                        Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
                    startActivityForResult(intent!!, REQUEST_LOAD_PHOTO)
                }

            }).onAnyDenied(object : PermissionUtil.Func() {
                override fun call() {
                    Toast.makeText(
                        this@ProfileActivity,
                        "Storage permission is needed to access file.",
                        Toast.LENGTH_LONG
                    ).show()
                }
            }).askPermission(99)
        } else {
            mCameraRequest = PermissionUtil.with(this).request(
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
            ).onAllGranted(object : PermissionUtil.Func() {

                override fun call() {
                    if (intent != null) return
                    intent =
                        Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
                    startActivityForResult(intent!!, REQUEST_LOAD_PHOTO)
                }

            }).onAnyDenied(object : PermissionUtil.Func() {
                override fun call() {
                    Toast.makeText(
                        this@ProfileActivity,
                        "Storage permission is needed to access file.",
                        Toast.LENGTH_LONG
                    ).show()
                }
            }).askPermission(99)
        }
    }

    private fun getCompressFile(actualImage: File): File {

        /* return Compressor(this).setMaxWidth(640).setMaxHeight(480)
                 .setQuality(90)
                 .setCompressFormat(Bitmap.CompressFormat.WEBP)
                 .setDestinationDirectoryPath(getExternalFilesDir(Environment.DIRECTORY_PICTURES)?.absolutePath)
                 .compressToFile(actualImage)*/
        actualImage.let { imageFile ->
            lifecycleScope.launch {
                compressedImage = Compressor.compress(this@ProfileActivity, imageFile) {
                    resolution(640, 480)
                    quality(90)
                    format(Bitmap.CompressFormat.WEBP)
                }
            }
        }

        return compressedImage!!
    }
}
