package com.doverfuelingsolutions.issp.view

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.core.os.bundleOf
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.lifecycleScope
import com.doverfuelingsolutions.issp.R
import com.doverfuelingsolutions.issp.api.FuelInfoApi
import com.doverfuelingsolutions.issp.api.SystemApi
import com.doverfuelingsolutions.issp.api.WayneApiConfig
import com.doverfuelingsolutions.issp.api.dto.DFSResult
import com.doverfuelingsolutions.issp.api.ftp.WayneFTPClient
import com.doverfuelingsolutions.issp.data.GlobalData
import com.doverfuelingsolutions.issp.databinding.ActivityPreferenceBinding
import com.doverfuelingsolutions.issp.utils.*
import com.doverfuelingsolutions.issp.utils.log.DFSLog
import com.doverfuelingsolutions.issp.utils.sp.SPKeys
import com.doverfuelingsolutions.issp.utils.sp.SPUtil
import com.doverfuelingsolutions.issp.view.fragment.FragmentPreference
import com.tencent.bugly.beta.Beta
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.io.File
import kotlin.coroutines.resume

class PreferenceActivity : AppCompatActivity(),
    View.OnClickListener {

    companion object {

        const val codeRequestResult = 1001
        const val isMiddleModified = "isMiddleModified"
        const val isFuelModified = "isFuelModified"
        const val isChooseOrderTypeModified = "isChooseOrderTypeModified"

        fun start(context: Context) {
            Intent(context, PreferenceActivity::class.java).let { context.startActivity(it) }
        }

        fun startForResult(activity: Activity) {
            Intent(activity, PreferenceActivity::class.java).let {
                it.putExtra("forResult", true)
                activity.startActivityForResult(it, codeRequestResult)
            }
        }
    }

    private val binding: ActivityPreferenceBinding by lazy {
        DataBindingUtil.setContentView(this, R.layout.activity_preference)
    }
    private val viewModel = PreferenceViewModel()

    private var isForResult = false
    private var oldMiddleInfo = ""
    private var oldFuelInfo = ""
    private var oldSystemInfo = ""
    private var oldChooseOrderType = ""

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        supportActionBar?.hide()
        binding.lifecycleOwner = this
        binding.viewModel = viewModel
        binding.handler = this
        if (savedInstanceState == null) {
            supportFragmentManager
                .beginTransaction()
                .replace(R.id.container, FragmentPreference())
                .commit()
        }

        val forResult = intent.getBooleanExtra("forResult", false)
        if (forResult) {
            isForResult = true
            oldMiddleInfo = makeMiddleInfo()
            oldFuelInfo = makeFuelInfo()
            oldSystemInfo = makeSystemInfo()
            oldChooseOrderType = SPUtil.getString(SPKeys.ORDER_CHOOSE)
        } else {
            isForResult = false
        }
    }

    override fun onResume() {
        super.onResume()

        WindowUtil.setFullscreen(this)
    }

    override fun onBackPressed() {
        val hasMiddleModified = makeMiddleInfo() != oldMiddleInfo
        val hasFuelModified = makeFuelInfo() != oldFuelInfo
        val hasSystemModified = makeSystemInfo() != oldSystemInfo
        if (hasSystemModified) SystemApi.regenerateAllService()
        if (hasFuelModified) FuelInfoApi.generateService()
        if (isForResult) {
            setResult(Activity.RESULT_OK, Intent().apply {
                putExtra(isMiddleModified, hasMiddleModified)
                putExtra(isFuelModified, hasFuelModified)
                putExtra(isChooseOrderTypeModified, oldChooseOrderType != SPUtil.getString(SPKeys.ORDER_CHOOSE))
            })
            finish()
        } else {
            super.onBackPressed()
        }
    }

    override fun onClick(v: View?) {
        when (v) {
            binding.checkUpdate -> {
                Beta.checkUpgrade()
                // processUpdate()
            }
            binding.buttonClose -> {
                onBackPressed()
            }
            binding.buttonReLogin -> {
                GlobalData.isLogin = false
                GlobalData.password.set("")
                GlobalData.accessToken.set("")
                GlobalData.accessTokenExpire.set(0L)
                LoginActivity.start(this, bundleOf(Pair(LoginActivity.autoLogin, false)))
            }
            binding.uploadLog -> uploadLog()
        }
    }

    private fun makeMiddleInfo(): String {
        return "${SPUtil.getString(SPKeys.MIDDLE_IP)}, ${SPUtil.getString(SPKeys.MIDDLE_PORT)}, ${SPUtil.getString(
            SPKeys.MIDDLE_WORKSTATION_ID
        )}"
    }

    private fun makeFuelInfo(): String {
        return "${SPUtil.getString(SPKeys.FUEL_IP)}, ${SPUtil.getString(SPKeys.FUEL_PORT)}"
    }

    private fun makeSystemInfo(): String {
        return "${SPUtil.getString(SPKeys.SERVER_DOMAIN)}, ${SPUtil.getString(SPKeys.SERVER_PORT_CONFIG)}, ${SPUtil.getString(
            SPKeys.SERVER_PORT_BASE
        )}, ${SPUtil.getString(SPKeys.SERVER_PORT_TRX)}, ${SPUtil.getString(SPKeys.SERVER_PORT_ASSETS)}"
    }

    private fun processUpdate() {
        lifecycleScope.launch {
            val currentVersion = AppUtil.getVersionName()
            DFSLog.i("current version is $currentVersion")

            viewModel.isSubmitting.value = true
            val result = SystemApi.remoteVersion()
            viewModel.isSubmitting.value = false

            if (!result.success || result.data == null) {
                DFSLog.e("latest version check failed: ${result.message}")
                DFSToastUtil.fail(
                    StringUtil.get(
                        R.string.fail_behave_reason,
                        StringUtil.get(R.string.check_update),
                        result.message
                    )
                )
                return@launch
            }

            if (result.data.versionList.isEmpty()) {
                DFSLog.e("check version update: no update")
                DFSToastUtil.fail(R.string.no_update_version)
                return@launch
            }

            val remoteVersion = result.data.versionList.last()
            val compare = AppUtil.compareVersion(remoteVersion.version, currentVersion)
            if (compare <= 0) {
                DFSLog.i("latest version check: ${remoteVersion.version}")
                DFSToastUtil.fail(R.string.current_version_is_latest)
                return@launch
            }

            UpgradeActivity.start(
                this@PreferenceActivity,
                remoteVersion.version,
                remoteVersion.name,
                remoteVersion.info
            )
        }
    }

    private fun uploadLog() {
        viewModel.isSubmitting.value = true
        GlobalScope.launch(Dispatchers.IO) {
            val localFiles = File(DFSLog.folder).listFiles { file -> file.isFile && file.extension.isEmpty() }
            if (localFiles.isNullOrEmpty()) {
                DFSToastUtil.fail(R.string.no_log)
                return@launch
            }

            val failList = arrayListOf<String>()
            val mWayneFTPClient = WayneFTPClient(WayneApiConfig.DOMAIN_DEFAULT.replace("http://", ""), "androidPos", "111111")
            val remoteFolder = "/isspt/log/${DeviceUtil.generateSerialNumber()}"
            mWayneFTPClient.connect()
            localFiles.forEach {
                val zipFilePath = "${it.absolutePath}.zip"
                val resultZip = ZipUtils.buildZip(it.absolutePath, zipFilePath, true)
                if (resultZip) {
                    val zipFile = File(zipFilePath)
                    val resultUpload = mWayneFTPClient.uploadFile(zipFile, remoteFolder)
                    zipFile.delete()

                    if (!resultUpload) failList.add(it.name)
                } else {
                    failList.add(it.name)
                }
            }
            mWayneFTPClient.close()

            lifecycleScope.launch {
                viewModel.isSubmitting.value = false
            }

            when {
                localFiles.size == failList.size -> {
                    DFSToastUtil.fail(R.string.log_upload_fail)
                }
                failList.isNotEmpty() -> {
                    DFSToastUtil.success(StringUtil.get(R.string.log_upload_fail_partly, failList.joinToString(", ")))
                }
                else -> {
                    DFSToastUtil.success(R.string.log_upload_done)
                }
            }
        }
    }

    class PreferenceViewModel : ViewModel() {
        val isSubmitting = MutableLiveData(false)
    }
}