package com.icing.dialer.activities

import android.Manifest
import android.app.role.RoleManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.database.Cursor
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.CallLog
import android.telecom.TelecomManager
import android.util.Log
import androidx.core.content.ContextCompat
import com.icing.dialer.KeystoreHelper
import com.icing.dialer.services.CallService
import com.icing.dialer.services.MyInCallService
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity : FlutterActivity() {
    private val KEYSTORE_CHANNEL = "com.example.keystore"
    private val CALLLOG_CHANNEL = "com.example.calllog"
    private val CALL_CHANNEL = "call_service"
    private val TAG = "MainActivity"
    private val REQUEST_CODE_SET_DEFAULT_DIALER = 1001

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d(TAG, "onCreate started")
        Log.d(TAG, "Waiting for Flutter to signal permissions")
    }

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        Log.d(TAG, "Configuring Flutter engine")

        MyInCallService.channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CALL_CHANNEL)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CALL_CHANNEL)
            .setMethodCallHandler { call, result ->
                when (call.method) {
                    "permissionsGranted" -> {
                        Log.d(TAG, "Received permissionsGranted from Flutter")
                        checkAndRequestDefaultDialer()
                        result.success(true)
                    }
                    "makeGsmCall" -> {
                        val phoneNumber = call.argument<String>("phoneNumber")
                        if (phoneNumber != null) {
                            val success = CallService.makeGsmCall(this, phoneNumber)
                            if (success) {
                                result.success(mapOf("status" to "calling", "phoneNumber" to phoneNumber))
                            } else {
                                result.error("CALL_FAILED", "Failed to initiate call", null)
                            }
                        } else {
                            result.error("INVALID_PHONE_NUMBER", "Phone number is required", null)
                        }
                    }
                    "hangUpCall" -> {
                        val success = CallService.hangUpCall(this)
                        if (success) {
                            result.success(mapOf("status" to "ended"))
                        } else {
                            result.error("HANGUP_FAILED", "Failed to end call", null)
                        }
                    }
                    "answerCall" -> {
                        val success = MyInCallService.currentCall?.let {
                            it.answer(0) // 0 for default video state (audio-only)
                            Log.d(TAG, "Answered call")
                            true
                        } ?: false
                        if (success) {
                            result.success(mapOf("status" to "answered"))
                        } else {
                            result.error("ANSWER_FAILED", "No active call to answer", null)
                        }
                    }
                    else -> result.notImplemented()
                }
            }

        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, KEYSTORE_CHANNEL)
            .setMethodCallHandler { call, result -> KeystoreHelper(call, result).handleMethodCall() }

        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CALLLOG_CHANNEL)
            .setMethodCallHandler { call, result ->
                if (call.method == "getCallLogs") {
                    val callLogs = getCallLogs()
                    result.success(callLogs)
                } else {
                    result.notImplemented()
                }
            }
    }

    private fun checkAndRequestDefaultDialer() {
        val telecomManager = getSystemService(TELECOM_SERVICE) as TelecomManager
        val currentDefault = telecomManager.defaultDialerPackage
        Log.d(TAG, "Current default dialer: $currentDefault, My package: $packageName")

        if (currentDefault != packageName) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                val roleManager = getSystemService(Context.ROLE_SERVICE) as RoleManager
                if (roleManager.isRoleAvailable(RoleManager.ROLE_DIALER) && !roleManager.isRoleHeld(RoleManager.ROLE_DIALER)) {
                    val intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_DIALER)
                    startActivityForResult(intent, REQUEST_CODE_SET_DEFAULT_DIALER)
                    Log.d(TAG, "Launched RoleManager intent for default dialer on API 29+")
                } else {
                    Log.d(TAG, "RoleManager: Available=${roleManager.isRoleAvailable(RoleManager.ROLE_DIALER)}, Held=${roleManager.isRoleHeld(RoleManager.ROLE_DIALER)}")
                }
            } else {
                val intent = Intent(TelecomManager.ACTION_CHANGE_DEFAULT_DIALER)
                    .putExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME, packageName)
                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                try {
                    startActivityForResult(intent, REQUEST_CODE_SET_DEFAULT_DIALER)
                    Log.d(TAG, "Launched TelecomManager intent for default dialer")
                } catch (e: Exception) {
                    Log.e(TAG, "Failed to launch default dialer prompt: ${e.message}", e)
                    launchDefaultAppsSettings()
                }
            }
        } else {
            Log.d(TAG, "Already the default dialer")
        }
    }

    private fun launchDefaultAppsSettings() {
        val settingsIntent = Intent(android.provider.Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS)
        startActivity(settingsIntent)
        Log.d(TAG, "Opened default apps settings as fallback")
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        Log.d(TAG, "onActivityResult: requestCode=$requestCode, resultCode=$resultCode, data=$data")
        if (requestCode == REQUEST_CODE_SET_DEFAULT_DIALER) {
            if (resultCode == RESULT_OK) {
                Log.d(TAG, "User accepted default dialer change")
            } else {
                Log.w(TAG, "Default dialer prompt canceled or failed (resultCode=$resultCode)")
                launchDefaultAppsSettings()
            }
        }
    }

    private fun getCallLogs(): List<Map<String, Any?>> {
        val logsList = mutableListOf<Map<String, Any?>>()
        val cursor: Cursor? = contentResolver.query(
            CallLog.Calls.CONTENT_URI, null, null, null, CallLog.Calls.DATE + " DESC"
        )
        cursor?.use {
            while (it.moveToNext()) {
                val number = it.getString(it.getColumnIndexOrThrow(CallLog.Calls.NUMBER))
                val type = it.getInt(it.getColumnIndexOrThrow(CallLog.Calls.TYPE))
                val date = it.getLong(it.getColumnIndexOrThrow(CallLog.Calls.DATE))
                val duration = it.getLong(it.getColumnIndexOrThrow(CallLog.Calls.DURATION))

                val map = mutableMapOf<String, Any?>(
                    "number" to number,
                    "type" to type,
                    "date" to date,
                    "duration" to duration
                )
                logsList.add(map)
            }
        }
        return logsList
    }
}