package es.verdnatura.presentation.view.feature.delivery.activity

import android.Manifest
import android.content.DialogInterface
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.location.Location
import android.view.View
import androidx.appcompat.app.AlertDialog
import androidx.core.app.ActivityCompat
import androidx.lifecycle.lifecycleScope
import com.google.android.gms.location.LocationResult
import com.google.android.gms.location.LocationServices
import com.google.gson.Gson
import es.verdnatura.MobileApplication
import es.verdnatura.R
import es.verdnatura.databinding.ActivitySignBinding
import es.verdnatura.db.DeliveryDatabase
import es.verdnatura.domain.toast
import es.verdnatura.presentation.base.BaseActivity
import es.verdnatura.presentation.base.LocationUpdateCallback
import es.verdnatura.presentation.base.database
import es.verdnatura.presentation.view.component.CustomDialog
import es.verdnatura.presentation.view.feature.delivery.model.ClientTicket
import es.verdnatura.presentation.view.feature.delivery.model.MyLocation
import es.verdnatura.presentation.view.feature.delivery.model.SignedTickets
import es.verdnatura.presentation.view.feature.delivery.viewmodels.DeliveryViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale


class SignedActivity : BaseActivity<ActivitySignBinding>(), LocationUpdateCallback {

    override fun getLayoutId(): Int = R.layout.activity_sign

    private lateinit var fusedLocationClient: com.google.android.gms.location.FusedLocationProviderClient
    private var lastLocationCurrent: MyLocation = MyLocation(0.0, 0.0)
    private lateinit var ticketsSet: HashSet<Long>
    private lateinit var clientTicket: ClientTicket
    private lateinit var db: DeliveryDatabase

    override fun init() {

        when (intent.getStringExtra("objectSigned")) {

            "ticket" -> {
                binding.mainToolbar.toolbarTitle.text = getString(R.string.sign)
                clientTicket = intent.extras!!.getSerializable("clientTicketList") as ClientTicket
                setViews(clientTicket)
                setLocation()
            }

        }
        setEvents()

        binding.splashProgress.visibility = View.GONE
        db = database(this.applicationContext)
    }

    private fun setToolBar() {
        binding.mainToolbar.toolbarTitle.text = getString(R.string.sign)
    }

    private fun showDialogConfirm() {
        val customDialog = CustomDialog(this)
        customDialog.setTitle(getString(R.string.confirm))
            .setDescription(getString(R.string.sureSign))
            .setOkButton(getString(R.string.ok)) {

                reviewDistance()
                customDialog.dismiss()

            }.setKoButton(getString(R.string.cancel)) {
                customDialog.dismiss()
            }
            .show()
    }

    private fun reviewDistance() {

        val locationCurrent = Location("").apply {
            this.latitude = lastLocationCurrent.Latitude
            this.longitude = lastLocationCurrent.Longitude
        }
        val locationClient = Location("").apply {
            this.latitude = clientTicket.Latitude ?: 0.0
            this.longitude = clientTicket.Longitude ?: 0.0
        }


        if (clientTicket.Latitude != null  && clientTicket.Longitude != null) {
            if (locationCurrent.distanceTo(locationClient) > 100 ) {

                val customDialogDistance = CustomDialog(this)
                customDialogDistance.setTitle(getString(R.string.confirm))
                    .setDescription(getString(R.string.locationDiferent)+ getString(R.string.distance) + locationCurrent.distanceTo(locationClient))
                    .setOkButton(getString(R.string.keep)) {

                        uploadImage(MyLocation(locationClient.latitude, locationClient.longitude))
                        customDialogDistance.dismiss()

                    }.setKoButton(getString(R.string.modify)) {
                        uploadImage(lastLocationCurrent)
                        customDialogDistance.dismiss()
                    }
                    .show()
            }else{
                uploadImage(MyLocation(locationClient.longitude, locationClient.latitude))
            }
        }else{
            uploadImage(lastLocationCurrent)
        }

     /*   if (locationCurrent.distanceTo(locationClient) > 100 && clientTicket.Latitude != null  && clientTicket.Longitude != null) {


            val customDialogDistance = CustomDialog(this)
            customDialogDistance.setTitle(getString(R.string.confirm))
                .setDescription(getString(R.string.locationDiferent))
                .setOkButton(getString(R.string.keep)) {

                    uploadImage(MyLocation(locationClient.latitude, locationClient.longitude))
                    customDialogDistance.dismiss()

                }.setKoButton(getString(R.string.modify)) {
                    uploadImage(lastLocationCurrent)
                    customDialogDistance.dismiss()
                }
                .show()
        } else {
            if (locationClient.latitude != null && locationClient.longitude != null) {
                uploadImage(MyLocation(locationClient.longitude, locationClient.latitude))
            } else {
                uploadImage(MyLocation(locationCurrent.longitude, locationCurrent.latitude))
            }
        }*/
    }

    private fun setEvents() {
        binding.btnSave.setOnClickListener {
            showDialogConfirm()
        }
        binding.mainToolbar.backButton.setOnClickListener {
            finish()
        }
    }


    private fun setViews(clientTicketList: ClientTicket) {

        if (clientTicketList != null) {

            binding.nameAddress.text = clientTicketList.ClientName
            ticketsSet = HashSet()
            var sum = 0
            for (exp in clientTicketList.tickets) {
                ticketsSet.add(exp.Id)
                sum += exp.Packages
            }
            binding.idTickets.text = ticketsSet.toList().toString()
            binding.totalPackages.text = sum.toString()
        }

    }

    private fun uploadImage(location: MyLocation) {

        val deliveryViewModel = DeliveryViewModel(application as MobileApplication)
        val drawing = binding.ink.bitmap
        val file = File(BitMapToString(drawing, tickets = ticketsSet.toList()))
        val queryMap: MutableMap<String?, String?> = HashMap()
        queryMap["tickets"] = ticketsSet.toString()
        queryMap["location"] = Gson().toJson(location)
        queryMap["signedTime"] =
            SimpleDateFormat("yyyy-LL-dd HH:mm", Locale.getDefault()).format(
                Date()
            )

        var mySign =
            SignedTickets(
                queryMap,
                baseContext.externalCacheDir.toString() + "/" + file.name
            )

        binding.splashProgress.visibility = View.VISIBLE
        deliveryViewModel.saveSign(
            mySign.fileName, mySign.queryMapList,
        )

        deliveryViewModel.responseSign.observe(this) {
            binding.splashProgress.visibility = View.GONE
            if (!it.isError) {
                getString(R.string.ok).toast(this)
                finish()
            } else {
                it.errorMessage.toast(this)
                lifecycleScope.launch {
                    withContext(Dispatchers.IO) {
                        db.signedTicketDao().insert(mySign)
                    }
                }

            }
        }

    }

    @Throws(IOException::class)
    fun BitMapToString(bitmap: Bitmap, tickets: List<Long>): String {
        var fileNameSign = baseContext.externalCacheDir.toString() + "/sign"
        for (ticket in tickets) {
            fileNameSign += "_$ticket"
        }
        //Create a file to write bitmap data
        val f = File("$fileNameSign.png")
        f.createNewFile()

        //Convert bitmap to byte array
        val baos = ByteArrayOutputStream()
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos)
        val b = baos.toByteArray()

        //write the bytes in file
        val fos = FileOutputStream(f)
        fos.write(b)
        fos.flush()
        fos.close()
        return "$fileNameSign.png"
    }

    private fun setLocation() {
        ActivityCompat.requestPermissions(
            this,
            arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
            111
        )
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
        locationUpdateCallback = this
        requestLocationUpdates(fusedLocationClient)


    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {

        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        val permission = Manifest.permission.ACCESS_FINE_LOCATION
        if (requestCode == 111) {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                requestLocationUpdates(fusedLocationClient)
            } else {
                if (!shouldShowRequestPermissionRationale(permission)) {

                    val builder = AlertDialog.Builder(this)
                    builder.apply {
                        setTitle(getString(R.string.permissionRequired))
                        setMessage(getString(R.string.manuallyPermission))
                        setPositiveButton(
                            "Aceptar"
                        ) { dialog, which ->
                            finish()
                        }

                    }

                    val dialog = builder.create()
                    dialog.show()

                } else {

                    val activity = this
                    val builder = AlertDialog.Builder(this)
                    builder.apply {
                        setTitle(getString(R.string.permissionRequired))
                        setMessage(getString(R.string.advicePermission))
                        setPositiveButton(
                            getString(R.string.accept)
                        ) { dialog, which ->
                            dialog.dismiss()
                            ActivityCompat.requestPermissions(
                                activity,
                                arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
                                111
                            )


                        }
                        setNegativeButton(
                            getString(R.string.cancel)
                        ) { dialog, which ->
                            finish()
                        }
                    }

                    val dialog = builder.create()
                    dialog.show()
                }

            }
        }
    }

    override fun onLocationReceived(location: LocationResult) {
        if (location.locations.isNotEmpty()) {
            lastLocationCurrent.Longitude = location.locations.last().longitude
            lastLocationCurrent.Latitude = location.locations.last().latitude
            println("ubicación - Latitud: $lastLocationCurrent.Latitude, Longitud: $lastLocationCurrent.Longitude")
        } else {
            println("ubicación vacía")
        }
    }

}



