package com.secspace.lib.common.function

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.os.Environment
import android.util.Log
import com.secspace.lib.common.utils.ImeiUtil.uniqueId
import com.skr.activation.api.ActivationApi
import com.skr.activation.constant.Constant
import com.skr.activation.constant.Constant.*
import com.skr.activation.network.linstener.CheckLocalActiveStatusListener
import com.skr.activation.utils.DesUtil
import com.skr.activation.utils.XmlUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.xmlpull.v1.XmlPullParserException
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.net.URL
import java.net.URLConnection
import java.text.SimpleDateFormat
import java.util.*

const val PROBATION = "probation"
const val SP_TRIAL_ACTIVE_START_TIME = "trialActiveStartTime"
const val PROBATION_TIME: Long = 7 * 24 * 60 * 60 * 1000

object ActivationHelper {
    private const val TAG = "ActivationHelper"
    private val FILE_PATH = Environment.getExternalStorageDirectory().toString() + "/."
    private const val PROBATION_FILE_NAME = "probation.xml"
    private const val ACTIVATE_FILE_NAME = "activate.xml"

    fun active(context: Activity, listener: ActivationListener, force: Boolean = false) {
        ActivationApi.getInstance().isActiveFromLocalAndNet(context.packageName, object : CheckLocalActiveStatusListener {
            override fun hasActivated() {
                listener.activated()
            }

            override fun needActivate() {
                Log.i(TAG, "needActivate")
                GlobalScope.launch(Dispatchers.Main) {
                    if (force) {
                        ActivationApi.getInstance().setUseNormalDialog(true)
                        ActivationApi.getInstance().startActivateActivity(context, context.packageName, false)
                        return@launch
                    }
                    val isProbation = isProbationFromLocal(context)
                    if (isProbation) {
                        listener.activated()
                    } else {
                        DialogManager.getInstance().showBuyCodeDialog(context)
//                        ActivationApi.getInstance().setUseNormalDialog(true)
//                        ActivationApi.getInstance().startActivateActivity(context, context.packageName, false)
                    }
                }
            }

            override fun onError() {}
        })
    }

    private suspend fun getCurrentTimeByNet(): Long {
        return withContext(Dispatchers.IO) {
            Log.i(TAG, "getCurrentTimeByNet 1")
            val url = URL("http://www.bjtime.cn")
            Log.i(TAG, "getCurrentTimeByNet 2")
            val uc: URLConnection = url.openConnection()
            Log.i(TAG, "getCurrentTimeByNet 3")
            uc.connect()
            Log.i(TAG, "getCurrentTimeByNet 4")
            val ld: Long = uc.date
            Log.i(TAG, "getCurrentTimeByNet 5 : $ld")
            val date = Date(ld)
            Log.i(TAG, "getCurrentTimeByNet 6")
            Log.e(TAG, "long:$ld, ${date.year}/${date.month}/${date.day} ${date.hours}:${date.minutes}:${date.seconds}")
            return@withContext ld
        }
    }

    private suspend fun isProbationFromLocal(context: Context): Boolean {
        return withContext(Dispatchers.IO) {
            val file = File(FILE_PATH + context.packageName, PROBATION_FILE_NAME)
            if (!file.exists()) {
                probation(context)
                return@withContext true
            }
            val map: HashMap<String?, *>?
            map = try {
                XmlUtils.readMapXml(FileInputStream(file))
            } catch (e: XmlPullParserException) {
                Log.e(TAG, "ERROR: ${e.message}")
                return@withContext false
            } catch (e: IOException) {
                Log.e(TAG, "ERROR: ${e.message}")
                return@withContext false
            }
            if (map != null && map.containsKey(Constant.SP_TRIAL_ACTIVE_END_TIME)) {
                val endTime: Long = DesUtil.decrypt(map[Constant.SP_TRIAL_ACTIVE_END_TIME].toString()).toLong()
//                val currentTime = getCurrentTimeByNet()
                val currentTime: Long = System.currentTimeMillis()
                if (currentTime > endTime) {
                    return@withContext false
                }
                return@withContext true
            }
            return@withContext false
        }
    }

    private suspend fun probation(context: Context) {
        val map: MutableMap<String?, String?> = HashMap()
        Log.i(TAG, "probation before")
//        val currentTime = getCurrentTimeByNet()
        val currentTime: Long = System.currentTimeMillis()
        Log.i(TAG, "probation after")
        val endTime = currentTime + PROBATION_TIME
        map[Constant.SP_IS_ACTIVE] = DesUtil.encrypt(PROBATION)
        map[Constant.SP_TRIAL_ACTIVE_END_TIME] = DesUtil.encrypt(endTime.toString())
        map[Constant.SP_ACTIVE_CODE] = DesUtil.encrypt("无")
        map[SP_TRIAL_ACTIVE_START_TIME] = DesUtil.encrypt(currentTime.toString())
        try {
            val fileDir = File(FILE_PATH + context.packageName)
            if (!fileDir.exists()) {
                fileDir.mkdirs()
            }
            val file = File(fileDir, PROBATION_FILE_NAME)
            if (!file.exists()) {
                file.createNewFile()
            }
            XmlUtils.writeMapXml(map, FileOutputStream(file))
        } catch (e: XmlPullParserException) {
            e.printStackTrace()
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

    private fun getValueByXmlKey(context: Context, key: String, fileName: String): String {
        val file = File(FILE_PATH + context.packageName, fileName)
        if (!file.exists()) {
            Log.d(TAG, "getValueByXmlKey $fileName 不存在")
            return ""
        }
        val map: HashMap<String, *>
        map = try {
            XmlUtils.readMapXml(FileInputStream(file))
        } catch (e: XmlPullParserException) {
            Log.d(TAG, "Error ${e.message}")
            return ""
        } catch (e: IOException) {
            Log.d(TAG, "Error ${e.message}")
            return ""
        }
        Log.i(TAG, "getValueByXmlKey ${map.keys.toTypedArray().contentToString()}, key is $key, ${map.containsKey(key)}")
        if (map != null && map.containsKey(key)) {
            val result = map[key]
            if (result != null) {
                return DesUtil.decrypt(result.toString())
            }
        }
        return ""
    }

    fun getActivationType(context: Context): String? {
        val activationState = getValueByXmlKey(context, SP_IS_ACTIVE, ACTIVATE_FILE_NAME)
        if (activationState.isNotEmpty()) {
            return when (activationState) {
                ACTIVE_TYPE_RELEASE_CODE -> "正式激活"
                ACTIVE_TYPE_TRIAL_CODE -> "试用激活"
                CAN_NOT_ACTIVE -> "无法激活"
                else -> "激活异常"
            }
        }
        val state = getValueByXmlKey(context, SP_IS_ACTIVE, PROBATION_FILE_NAME)
        if (state == PROBATION)
            return "试用期"
        return "已过期"
    }

    fun getActivationCode(context: Context): String? {
        val activationCode = getValueByXmlKey(context, SP_ACTIVE_CODE, ACTIVATE_FILE_NAME)
        if (activationCode.isNotEmpty()) {
            return activationCode
        }
        return getValueByXmlKey(context, SP_ACTIVE_CODE, PROBATION_FILE_NAME)
    }

    fun getActivationTimeStart(context: Context): String? {
        val time = getValueByXmlKey(context, SP_TRIAL_ACTIVE_START_TIME, PROBATION_FILE_NAME)
        if(time.isEmpty()) return "未获取到时间"
        val longTime: Long? = time.toLong()
        val format = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US)
        return format.format(longTime?.let { Date(it) })
    }

    fun getActivationTimeEnd(context: Context): String? {
        val activationEndTime = getValueByXmlKey(context, SP_TRIAL_ACTIVE_END_TIME, ACTIVATE_FILE_NAME)
        if (activationEndTime.isNotEmpty()) {
            return activationEndTime.replace("  ", " ")
        }
        val time = getValueByXmlKey(context, SP_TRIAL_ACTIVE_END_TIME, PROBATION_FILE_NAME)
        if(time.isEmpty()) return "未获取到时间"
        val longTime: Long? = time.toLong()
        val format = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US)
        return format.format(longTime?.let { Date(it) })
    }

    @SuppressLint("PrivateApi")
    fun init(context: Context) {
        val imei = uniqueId(context, false)
        ActivationApi.getInstance().init(context, Class.forName("com.android.launcher3.Launcher"), imei, true)
    }

    interface ActivationListener {
        fun activated()
    }
}