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.*
import com.simplemobiletools.commons.models.PhoneNumber
import com.simplemobiletools.commons.models.SimpleContact
import com.simplemobiletools.commons.models.contacts.Contact
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 blockedNumberList = context.getBlockedNumbers().map { it.number }
        Log.d(TAG, "onReceive: 黑名单列表 = ${Gson().toJson(blockedNumberList)}")
        if (blockedNumberList.contains(address)) {
            return
        }
        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()) {
                if (address.contains("+86")) {
                    address = address.replace("+86", "")
                }
                findConversationWithPhoneNumber(context, address, body, threadId) { phoneNumberResult ->
                    Log.d(TAG, "onReceive: phoneNumberResult = $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)
                                }
                            }
                        }
                    } else {
                        handleMessage(context, address, subject, body, date, read, threadId, type, subscriptionId, status, phoneNumberResult) {
                            badgeTotalNumber(context)
                        }
                    }
                }
            }
        }
    }


    /**
     * 1.先从短信DB库查找
     * 2.未找到再从 通话记录中查找
     */
    private fun findConversationWithPhoneNumber(context: Context, phoneNumber: String, body: String, threadId: Long, confirmCallBack: (String) -> Unit) {
        var lastNumberOrName = ""
        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 ->
                        lastNumberOrName = itNumber
                    }
                }
            }

            //2
            if (lastNumberOrName.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)}")
                    if (listCallRecent.isNotEmpty()) {
                        val findResult = listCallRecent.filter { it.isShunFeng }.count {
                            Log.d(TAG, "SmsReceiver findResult  isNumber = ${PhoneFromUtil.isNumeric(it.phoneNumber)}")

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

                            ContactsHelper(mContent).getContacts(showOnlyContactsWithNumbers = true) { contacts ->
                                if (contacts.isEmpty())return@getContacts
                                Log.d(TAG, "SmsReceiver contacts = ${Gson().toJson(contacts)}")
                                val listPhoneNumbers = contacts.flatMap { it.phoneNumbers }.map { it.normalizedNumber.ifBlank { it.value } }
                                Log.d(TAG, "SmsReceiver listPhoneNumbers = ${Gson().toJson(listPhoneNumbers)}")
                                if (!listPhoneNumbers.contains(phoneNumber)) return@getContacts

                                listPhoneNumbers.forEachIndexed { index, number ->
                                    if (number == phoneNumber) {
                                        lastNumberOrName = contacts[index].name
                                        Log.d(TAG, "SmsReceiver lastNumberOrName  = $lastNumberOrName   通讯录名称是 = ${contacts[index].name}")
                                        return@forEachIndexed
                                    }
                                }
                            }
                        }
                    }
                }
            }
            Log.d(TAG, "SmsReceiver   lastNumberOrName = $lastNumberOrName")
        }
        if (lastNumberOrName == "") {
            confirmCallBack.invoke(phoneNumber)
        } else {
            confirmCallBack.invoke(lastNumberOrName)
        }
    }


    @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)
        var notificationUserName = ""//通讯录如果有备注则优先展示备注，其次手机号

        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)
                    //最新消息会话  必须在insertNewSMS 后获取,否则读取的read状态不生效
                    val conversation: Conversation = context.getConversations(threadId).firstOrNull() ?: return@ensureBackgroundThread
                    Log.d(TAG, "handleMessage: conversation toJson = ${Gson().toJson(conversation)} ")
                    if (!PhoneFromUtil.isNumeric(conversation.userName)) {
                        notificationUserName = conversation.userName
                    }
                    if (aesPhoneNumber.contains("*") || 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)

                    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()
                    Log.d(
                        TAG,
                        "handleMessage: notificationUserName = $notificationUserName  掩码号码 aesPhoneNumber = $aesPhoneNumber  正常号码 address = $address  threadId = $threadId"
                    )
                    if (notificationUserName.isNotEmpty()) {
                        context.showReceivedMessageNotification(newMessageId, notificationUserName, body, threadId, bitmap, normalNumber = address)
                    } else if (aesPhoneNumber.contains("*")) {
                        Log.d(TAG, "handleMessage: 掩码号码")
                        context.showReceivedMessageNotification(newMessageId, aesPhoneNumber, body, threadId, bitmap, normalNumber = address)
                    } else {
                        context.showReceivedMessageNotification(newMessageId, address, body, threadId, bitmap)
                    }
                }
            }

            Log.d(TAG, "SmsReceiver  aesPhoneNumber 手机号是否加密 :${aesPhoneNumber}")
            Log.d(TAG, "SmsReceiver: notificationUserName = $notificationUserName  aesPhoneNumber = $aesPhoneNumber  address = $address")
            if (notificationUserName.isNotEmpty()) {
                val tipPopup = MyPushWindow(context, notificationUserName, body)
                tipPopup.show()
            } else if (aesPhoneNumber.isNotBlank()) {
                val tipPopup = MyPushWindow(context, aesPhoneNumber, body)
                tipPopup.show()
            } else {
                Log.d(TAG, "SmsReceiver  短信内容  = $body   address = $address ")
                if (body.contains("\u200B")) {
                    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)

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


