package com.secspace.sms.receivers

import android.annotation.SuppressLint
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.database.Cursor
import android.os.Handler
import android.os.Looper
import android.provider.Telephony
import androidx.core.app.NotificationCompat
import com.google.gson.Gson
import com.secspace.log.Log
import com.secspace.sms.App
import com.secspace.sms.R
import com.secspace.sms.extensions.*
import com.secspace.sms.helpers.*
import com.secspace.sms.models.Conversation
import com.secspace.sms.models.Message
import com.secspace.sms.models.RecentCall
import com.secspace.sms.popup.MyPushWindow
import com.secspace.sms.util.AES
import com.secspace.sms.util.PhoneFromUtil
import com.secspace.sms.util.PhoneUtils
import com.secspace.sms.util.SmsCountUtil
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.PERMISSION_READ_CALL_LOG
import com.simplemobiletools.commons.helpers.SimpleContactsHelper
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.helpers.isOreoPlus
import com.simplemobiletools.commons.models.PhoneNumber
import com.simplemobiletools.commons.models.SimpleContact
import com.simplemobiletools.commons.util.GsonUtil

class SmsReceiver : BroadcastReceiver() {
    private val TAG: String = "SmsReceiver"

    private val mContent = App.APP_CONTEXT
    private var CALL_NOTIFICATION_ID = 1

    override fun onReceive(context: Context, intent: Intent) {

        val messages = Telephony.Sms.Intents.getMessagesFromIntent(intent)
        var address = ""
        var body = ""
        var subject = ""
        var date = 0L
        var threadId = 0L
        var status = Telephony.Sms.STATUS_NONE
        val type = Telephony.Sms.MESSAGE_TYPE_INBOX
        val read = 0
        val subscriptionId = intent.getIntExtra("subscription", -1)

        val privateCursor: Cursor? = context.getMyContactsCursor(favoritesOnly = false, withPhoneNumbersOnly = true)
        ensureBackgroundThread {
            messages.forEach {
                address = it.originatingAddress ?: ""
                subject = it.pseudoSubject
                status = it.status
                body += it.messageBody
                date = System.currentTimeMillis()
                threadId = context.getThreadId(address)
                Log.d(TAG, "onReceive: address = $address  body = $body  date = $date")
            }

            if (address.isNotEmpty()) {
                findConversationWithPhoneNumber(context, address,body,threadId) {phoneNumberResult->
                    if (context.baseConfig.blockUnknownNumbers) {
                        val simpleContactsHelper = SimpleContactsHelper(context)
                        simpleContactsHelper.exists(address, privateCursor) { exists ->
                            if (exists) {
                                handleMessage(context, address, subject, body, date, read, threadId, type, subscriptionId, status, phoneNumberResult) {
                                    badgeTotalNumber(context)
//                                    sendNotification(phoneNumberResult, body)
                                }
                            }
                        }
                    } else {
                        handleMessage(context, address, subject, body, date, read, threadId, type, subscriptionId, status, phoneNumberResult) {
                            badgeTotalNumber(context)
//                            sendNotification(phoneNumberResult, body)
                        }
                    }
                }
            }
        }
    }


    /**
     * 1.先从短信DB库查找
     * 2.未找到再从 通话记录中查找
     */
    private fun findConversationWithPhoneNumber(context: Context, phoneNumber: String,body :String,threadId: Long,confirmCallBack: (String) -> Unit) {
        var lastNumber = ""
        Log.d(TAG, "SmsReceiver phoneNumber:${phoneNumber}   body = $body  threadId = $threadId")
        val hasPerMissionResult = context.hasPermission(PERMISSION_READ_CALL_LOG)
        if (hasPerMissionResult) {

            //1
            val listMessageData = context.getMessages(threadId, false)
            if (listMessageData.isNotEmpty()) {
                val listContains: List<Message> = listMessageData.filter { msg -> msg.body.contains("\u200B") }
                if (listContains.isNotEmpty()) {
                    PhoneUtils.phoneNumberFormat(phoneNumber) { itNumber ->
                        lastNumber = itNumber
                    }
                }
            }
           /* val allConversations = context.conversationsDB.getNonArchived() as ArrayList<Conversation>
            Log.d(TAG, "SmsReceiver handleMessage allConversations:${GsonUtil.parseListToJson(allConversations)}")
            if(allConversations.isNotEmpty()){
                val listConversation: List<Conversation> = allConversations.filter {
                    Log.d(TAG, "SmsReceiver 短信内容相等  = ${it.threadId == threadId  && it.isSFNumber }")
                    it.threadId == threadId && it.isSFNumber
                }
                android.util.Log.d(TAG, "findConversationWithPhoneNumber  listConversation = $listConversation")
                if (listConversation.isNotEmpty()) {
                    lastNumber = listConversation.first().title
                }
            }*/

            //2
            if (lastNumber.isEmpty()) {
                RecentsHelper(context = context).getRecentCalls(false, Int.MAX_VALUE) { recents: List<RecentCall> ->
                    val listCallRecent: List<RecentCall> = recents.distinctBy { it.phoneNumber }
                Log.d(TAG, "SmsReceiver最近通话 recents:${GsonUtil.parseListToJson(listCallRecent)}")
                    val findResult = listCallRecent.filter { it.isShunFeng }.count {
                        Log.d(TAG, "SmsReceiver findResult  isNumber = ${PhoneFromUtil.isNumeric(it.phoneNumber)}")

                        if (PhoneFromUtil.isNumeric(it.phoneNumber)) {
                            if(phoneNumber.contains("+86")){
                                it.phoneNumber == phoneNumber.replace("+86","")
                            }else{
                                it.phoneNumber == phoneNumber
                            }
                        } else {
                            if(phoneNumber.contains("+86")) {
                                AES.decrypt(it.phoneNumber) == phoneNumber.replace("+86","")
                            }else{
                                AES.decrypt(it.phoneNumber) == phoneNumber
                            }
                        }
                    }
                    Log.d(TAG, "SmsReceiverfindResult:${findResult}   phoneNumber = ${phoneNumber.trim()}")
                    //从最近通话记录中找到了号码 进行掩码操作
                    if (findResult > 0) {
                        PhoneUtils.phoneNumberFormat(phoneNumber) { itNumber ->
                            lastNumber = itNumber
                        }
                    }
                }
            }
            Log.d(TAG, "SmsReceiver   lastNumber = $lastNumber")
        }
        if (lastNumber == "") {
            confirmCallBack.invoke(phoneNumber)
        } else {
            confirmCallBack.invoke(lastNumber)
        }
    }


    @SuppressLint("SuspiciousIndentation")
    private fun handleMessage(
        context: Context,
        address: String,
        subject: String,
        body: String,
        date: Long,
        read: Int,
        threadId: Long,
        type: Int,
        subscriptionId: Int,
        status: Int,
        aesPhoneNumber: String,
        confirmCallBack: () -> Unit
    ) {
        if (isMessageFilteredOut(context, body)) {
            return
        }
        val photoUri = SimpleContactsHelper(context).getPhotoUriFromPhoneNumber(address)
        val bitmap = context.getNotificationBitmap(photoUri)
        Handler(Looper.getMainLooper()).post {
            if (!context.isNumberBlocked(address)) {
                val privateCursor = context.getMyContactsCursor(favoritesOnly = false, withPhoneNumbersOnly = true)
                ensureBackgroundThread {
                    val newMessageId: Long = context.insertNewSMS(address, subject, body, date, read, threadId, type, subscriptionId)
                    //最新消息会话
                    val conversation: Conversation = context.getConversations(threadId).firstOrNull() ?: return@ensureBackgroundThread
                    Log.d(TAG, "handleMessage:  toJson = ${Gson().toJson(conversation)}")
                    if (aesPhoneNumber.isNotBlank() || body.contains("\u200B")) {
                        conversation.title = aesPhoneNumber
                        conversation.isSFNumber = true
                    }
                    Log.d(TAG, "SmsReceiverhandleConversation 掩码后的 Json:${GsonUtil.parseBeanToJson(conversation)}")
                    try {
                        context.insertOrUpdateConversation(conversation)
                    } catch (ignored: Exception) {
                    }

                    val senderName = context.getNameFromAddress(address, privateCursor)
                    val phoneNumber = PhoneNumber(address, 0, "", address)

                    /*if (aesPhoneNumber.isNotBlank()) {
                        senderName = context.getNameFromAddress(aesPhoneNumber, privateCursor)
                        phoneNumber = PhoneNumber(aesPhoneNumber, 0, "", aesPhoneNumber)
                    }*/

                    val participant = SimpleContact(0, 0, senderName, photoUri, arrayListOf(phoneNumber), ArrayList(), ArrayList())
                    val participants = arrayListOf(participant)
                    val messageDate = (date / 1000).toInt()


                    val message =
                        Message(
                            newMessageId,
                            body,
                            type,
                            status,
                            participants,
                            messageDate,
                            false,
                            threadId,
                            false,
                            null,
                            address,
                            senderName,
                            photoUri,
                            subscriptionId
                        )
                    Log.d(TAG, "SmsReceiver handleMessage 消息插入成功  ")
                    context.messagesDB.insertOrUpdate(message)
                    if (context.config.isArchiveAvailable) {
                        context.updateConversationArchivedStatus(threadId, false)
                    }
                    refreshMessages()
                    if (aesPhoneNumber.isNotBlank()) {
                        context.showReceivedMessageNotification(newMessageId, aesPhoneNumber, body, threadId, bitmap)
                    } else {
                        context.showReceivedMessageNotification(newMessageId, address, body, threadId, bitmap)

                    }
                }
            }

            Log.d(TAG, "SmsReceiver  aesPhoneNumber 手机号是否加密 :${aesPhoneNumber}")
            if (aesPhoneNumber.isNotBlank()) {
                val tipPopup = MyPushWindow(context, aesPhoneNumber, body)
                tipPopup.show()
            } else {
                Log.d(TAG, "SmsReceiver  短信内容  = ${body}   address = $address ")
                if (body.contains("\u200B")) {
                    if (address.contains("+86")) {
                        address.replace("+86", "")
                    }
                    PhoneUtils.phoneNumberFormat(address) { itNumber ->
                        val tipPopup = MyPushWindow(context, itNumber, body)
                        tipPopup.show()
                    }
                } else {
                    val tipPopup = MyPushWindow(context, address, body)
                    tipPopup.show()
                }
            }
        }
        confirmCallBack.invoke()
    }

    private fun isMessageFilteredOut(context: Context, body: String): Boolean {
        for (blockedKeyword in context.config.blockedKeywords) {
            if (body.contains(blockedKeyword, ignoreCase = true)) {
                return true
            }
        }
        return false
    }

    /**
     * 统计未读消息数量
     *
     * 存储值在 Mainactivity.kt 完成
     * 此处只做获取数值操作
     * 1.未获取到值则表明没有未读短信，直接+1显示
     * 2.获取到值也要数量+1 显示
     */
    private fun badgeTotalNumber(context: Context) {

        val readTotalResult: Int = Config.newInstance(context).badgeTotalNumber
        val totalResult = readTotalResult + 1
        SmsCountUtil.setBadgeNum(context, totalResult)

        Config.newInstance(context).badgeTotalNumber = totalResult
        Log.d(TAG, "badgeTotalNumber  readTotalResult = $totalResult ")
    }


    /**
     * 发送通知栏消息推送
     */
    private fun sendNotification(maskPhoneResult: String, body: String) {

        val notificationManager = mContent.notificationManager
//        val isHighPriority = mContent.powerManager.isInteractive
        val channelId = /*if (isHighPriority) Constant.HIGH_PRIORITY else*/ Constant.LOW_PRIORITY

        if (isOreoPlus()) {
            val importance = NotificationManager.IMPORTANCE_DEFAULT
            val name = /*if (isHighPriority) Constant.HIGH_CHANNEL_PRIORITY else*/ Constant.LOW_CHANNEL_PRIORITY

            NotificationChannel(channelId, name, importance).apply {
                setSound(null, null)
                notificationManager.createNotificationChannel(this)
            }
        }

        val builder = NotificationCompat.Builder(mContent, channelId)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setPriority(NotificationCompat.PRIORITY_LOW)
            .setCategory(Notification.CATEGORY_MESSAGE)
            .setDefaults(Notification.DEFAULT_SOUND)
            .setContentTitle(maskPhoneResult)
            .setContentText(body)
            .setSound(null)
            .setAutoCancel(true)
            .setChannelId(channelId)

        val buildNotification = builder.build()
        notificationManager.notify(CALL_NOTIFICATION_ID, buildNotification)

        android.util.Log.d(TAG, "sendNotification: 发送通知栏消息推送")
    }
}


