package com.icing.dialer.services

import android.app.KeyguardManager
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.media.AudioManager
import android.os.Build
import android.telecom.Call
import android.telecom.InCallService
import android.telecom.CallAudioState
import android.util.Log
import androidx.core.app.NotificationCompat
import com.icing.dialer.activities.MainActivity
import io.flutter.plugin.common.MethodChannel

class MyInCallService : InCallService() {
    companion object {
        var channel: MethodChannel? = null
        var currentCall: Call? = null
        private const val TAG = "MyInCallService"
        private const val NOTIFICATION_CHANNEL_ID = "incoming_call_channel"
        private const val NOTIFICATION_ID = 1
        var wasPhoneLocked: Boolean = false
        private var instance: MyInCallService? = null

        fun toggleMute(mute: Boolean): Boolean {
            return instance?.let { service ->
                try {
                    service.setMuted(mute)
                    Log.d(TAG, "Requested to set call mute state to $mute")
                    true
                } catch (e: Exception) {
                    Log.e(TAG, "Failed to set mute state: $e")
                    false
                }
            } ?: false
        }

        fun toggleSpeaker(speaker: Boolean): Boolean {
            return instance?.let { service ->
                try {
                    val route = if (speaker) CallAudioState.ROUTE_SPEAKER else CallAudioState.ROUTE_EARPIECE
                    service.setAudioRoute(route)
                    Log.d(TAG, "Requested to set audio route to $route")
                    true
                } catch (e: Exception) {
                    Log.e(TAG, "Failed to set audio route: $e")
                    false
                }
            } ?: false
        }

        fun sendDtmfTone(digit: String): Boolean {
            return instance?.let { service ->
                try {
                    currentCall?.let { call ->
                        call.playDtmfTone(digit[0])
                        call.stopDtmfTone()
                        Log.d(TAG, "Sent DTMF tone: $digit")
                        true
                    } ?: false
                } catch (e: Exception) {
                    Log.e(TAG, "Failed to send DTMF tone: $e")
                    false
                }
            } ?: false
        }
    }

    private val callCallback = object : Call.Callback() {
        override fun onStateChanged(call: Call, state: Int) {
            super.onStateChanged(call, state)
            val stateStr = when (state) {
                Call.STATE_DIALING -> "dialing"
                Call.STATE_ACTIVE -> "active"
                Call.STATE_DISCONNECTED -> "disconnected"
                Call.STATE_DISCONNECTING -> "disconnecting"
                Call.STATE_RINGING -> "ringing"
                else -> "unknown"
            }
            Log.d(TAG, "State changed: $stateStr for call ${call.details.handle}")
            channel?.invokeMethod("callStateChanged", mapOf(
                "callId" to call.details.handle.toString(),
                "state" to stateStr,
                "wasPhoneLocked" to wasPhoneLocked
            ))
            if (state == Call.STATE_RINGING) {
                val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
                wasPhoneLocked = keyguardManager.isKeyguardLocked
                Log.d(TAG, "Phone locked at ringing: $wasPhoneLocked")
                showIncomingCallScreen(call.details.handle.toString().replace("tel:", ""))
            } else if (state == Call.STATE_DISCONNECTED || state == Call.STATE_DISCONNECTING) {
                Log.d(TAG, "Call ended: ${call.details.handle}, wasPhoneLocked: $wasPhoneLocked")
                channel?.invokeMethod("callEnded", mapOf(
                    "callId" to call.details.handle.toString(),
                    "wasPhoneLocked" to wasPhoneLocked
                ))
                currentCall = null
                cancelNotification()
            }
        }
    }

    override fun onCallAdded(call: Call) {
        super.onCallAdded(call)
        instance = this
        currentCall = call
        val stateStr = when (call.state) {
            Call.STATE_DIALING -> "dialing"
            Call.STATE_ACTIVE -> "active"
            Call.STATE_RINGING -> "ringing"
            else -> "dialing"
        }
        Log.d(TAG, "Call added: ${call.details.handle}, state: $stateStr")
        channel?.invokeMethod("callAdded", mapOf(
            "callId" to call.details.handle.toString(),
            "state" to stateStr
        ))
        if (stateStr == "ringing") {
            val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
            wasPhoneLocked = keyguardManager.isKeyguardLocked
            Log.d(TAG, "Phone locked at call added: $wasPhoneLocked")
            showIncomingCallScreen(call.details.handle.toString().replace("tel:", ""))
        }
        call.registerCallback(callCallback)
        if (callAudioState != null) {
        val audioState = callAudioState
            channel?.invokeMethod("audioStateChanged", mapOf(
                "route" to audioState.route,
                "muted" to audioState.isMuted,
                "speaker" to (audioState.route == CallAudioState.ROUTE_SPEAKER)
            ))
        } else {
            Log.w("MyInCallService", "callAudioState is null in onCallAdded")
        }
    }

    override fun onCallRemoved(call: Call) {
        super.onCallRemoved(call)
        Log.d(TAG, "Call removed: ${call.details.handle}, wasPhoneLocked: $wasPhoneLocked")
        call.unregisterCallback(callCallback)
        channel?.invokeMethod("callRemoved", mapOf(
            "callId" to call.details.handle.toString(),
            "wasPhoneLocked" to wasPhoneLocked
        ))
        currentCall = null
        instance = null
        cancelNotification()
    }

    override fun onCallAudioStateChanged(state: CallAudioState) {
        super.onCallAudioStateChanged(state)
        Log.d(TAG, "Audio state changed: route=${state.route}, muted=${state.isMuted}")
        channel?.invokeMethod("audioStateChanged", mapOf(
            "route" to state.route,
            "muted" to state.isMuted,
            "speaker" to (state.route == CallAudioState.ROUTE_SPEAKER)
        ))
    }

    private fun showIncomingCallScreen(phoneNumber: String) {
        val intent = Intent(this, MainActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
            putExtra("phoneNumber", phoneNumber)
            putExtra("isIncomingCall", true)
            putExtra("showIncomingCallScreen", true)
            putExtra("wasPhoneLocked", wasPhoneLocked)
        }

        val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
        if (keyguardManager.isKeyguardLocked) {
            startActivity(intent)
            Log.d(TAG, "Launched MainActivity directly for locked screen, phoneNumber: $phoneNumber")
        } else {
            val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                val channel = NotificationChannel(
                    NOTIFICATION_CHANNEL_ID,
                    "Incoming Calls",
                    NotificationManager.IMPORTANCE_HIGH
                ).apply {
                    description = "Notifications for incoming calls"
                    enableVibration(true)
                    setShowBadge(true)
                }
                notificationManager.createNotificationChannel(channel)
            }

            val pendingIntent = PendingIntent.getActivity(
                this, 0, intent,
                PendingIntent.FLAG_UPDATE_CURRENT or (if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) PendingIntent.FLAG_IMMUTABLE else 0)
            )

            val notification = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
                .setSmallIcon(android.R.drawable.ic_dialog_alert)
                .setContentTitle("Incoming Call")
                .setContentText("Call from $phoneNumber")
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setFullScreenIntent(pendingIntent, true)
                .setAutoCancel(true)
                .setOngoing(true)
                .build()

            startActivity(intent)
            notificationManager.notify(NOTIFICATION_ID, notification)
            Log.d(TAG, "Launched MainActivity with notification for unlocked screen, phoneNumber: $phoneNumber")
        }
    }

    private fun cancelNotification() {
        val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.cancel(NOTIFICATION_ID)
        Log.d(TAG, "Notification canceled")
    }
}