package com.amz.genie.activities

import android.Manifest
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.text.TextUtils
import android.util.Log
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import com.amz.genie.R
import com.amz.genie.helpers.Preferences
import com.amz.genie.helpers.Utils.isNetworkAvailable
import com.amz.genie.models.Login
import com.amz.genie.services.APIMain
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.textfield.TextInputEditText
import com.google.firebase.messaging.FirebaseMessaging
import com.google.gson.Gson
import com.google.gson.JsonParser
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONObject
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response

class LoginActivity : BaseActivity() {
    private lateinit var tietUsername: TextInputEditText
    private lateinit var tietPassword: TextInputEditText
    private lateinit var tvForgotPassword: TextView
    private lateinit var btLogin: Button

    private lateinit var handler: Handler
    private var backPressedTime: Long = 0
    private val notificationPermission = Manifest.permission.POST_NOTIFICATIONS
    private lateinit var notificationPermissionLauncher: ActivityResultLauncher<String>
    private var pendingUserData: Login? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)

        initUI()
    }

    private fun initUI() {
        tietUsername = findViewById(R.id.tiet_username_login)
        tietPassword = findViewById(R.id.tiet_password_login)
        tvForgotPassword = findViewById(R.id.tv_forgot_password_login)
        btLogin = findViewById(R.id.bt_login)

        handler = Handler(Looper.getMainLooper())
        initializePermissionLaunchers()

        setupActions()
    }

    private fun initializePermissionLaunchers() {
        // Notification permission launcher
        notificationPermissionLauncher = registerForActivityResult(
            ActivityResultContracts.RequestPermission()
        ) { isGranted ->
            if (isGranted) {
                // Notification permission granted
                Log.d("NotificationPermission", "Push notification permission granted")
                showCustomNotificationDialog(true)
            } else {
                // Notification permission denied
                Log.w("NotificationPermission", "Push notification permission denied")
                showCustomNotificationDialog(false)
            }

            // Proceed with login regardless of notification permission
            pendingUserData?.let {
                proceedAfterPermission(it)
            } ?: run {
                showProgressDialog(false)
                Snackbar.make(
                    findViewById(android.R.id.content),
                    "Authentication error, please try again",
                    Snackbar.LENGTH_LONG
                ).show()
            }
        }
    }

    private fun setupActions() {
        onBackPressedDispatcher.addCallback(this,
            object : OnBackPressedCallback(true) {
                override fun handleOnBackPressed() {
                    if (backPressedTime + 2000 > System.currentTimeMillis()) {
                        finishAffinity()
                    } else {
                        Toast.makeText(
                            this@LoginActivity,
                            "Tekan Sekali Lagi Untuk Keluar",
                            Toast.LENGTH_SHORT
                        ).show()
                        backPressedTime = System.currentTimeMillis()
                    }
                }
            })

        btLogin.setOnClickListener {
            val username: String = tietUsername.text.toString().trim()
            val password: String = tietPassword.text.toString().trim { it <= ' ' }
            if (!TextUtils.isEmpty(username) && !TextUtils.isEmpty(password)) {
                if (isNetworkAvailable(this)) {
                    showProgressDialog(true)

                    val paramObject = JSONObject()
                    paramObject.put("username", username)
                    paramObject.put("password", password)

                    val requestBody: RequestBody = paramObject.toString().toRequestBody(
                        "application/json".toMediaTypeOrNull())

                    val call: Call<Login> = APIMain.require().accountServices.login(requestBody)
                    call.enqueue(object: Callback<Login> {
                        override fun onResponse(
                            call: Call<Login?>,
                            response: Response<Login?>
                        ) {
                            if (response.isSuccessful) {
                                val result: Login? = response.body()
                                result?.let {
                                    pendingUserData = it
                                    checkNotificationPermission()
                                }

                            } else {
                                showProgressDialog(false)

                                val message = if (response.code() == 400) {
                                    val errorJson = response.errorBody()?.string()
                                    if (!errorJson.isNullOrEmpty()) {
                                        JsonParser.parseString(errorJson).asJsonObject["message"]?.asString ?: "Bad Request"
                                    } else {
                                        "Bad Request"
                                    }
                                } else {
                                    "${response.code()}, ${response.message()}"
                                }

                                Snackbar.make(findViewById(android.R.id.content),
                                    message,
                                    Snackbar.LENGTH_LONG
                                ).show()
                                response.errorBody()?.close()
                            }
                        }

                        override fun onFailure(
                            call: Call<Login?>,
                            t: Throwable
                        ) {
                            showProgressDialog(false)

                            Snackbar.make(findViewById(android.R.id.content),
                                t.message.toString(),
                                Snackbar.LENGTH_LONG
                            ).show()
                        }

                    })

                } else {
                    showProgressDialog(false)

                    Snackbar.make(findViewById(android.R.id.content),
                        ContextCompat.getString(this@LoginActivity,
                            R.string.no_internet_message),
                        Snackbar.LENGTH_LONG
                    ).show()
                }
            }
        }
    }

    private fun checkNotificationPermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            if (ContextCompat.checkSelfPermission(this, notificationPermission)
                != PackageManager.PERMISSION_GRANTED) {
                Log.d("NotificationPermission", "Showing notification explanation dialog")
                showNotificationExplanationDialog()
            } else {
                Log.d("NotificationPermission", "Push notification permission already granted")
                showCustomNotificationDialog(true)
                pendingUserData?.let {
                    proceedAfterPermission(it)
                }
            }
        } else {
            Log.d("NotificationPermission", "No notification permission required for Android < 13")
            pendingUserData?.let {
                proceedAfterPermission(it)
            }
        }
    }

    private fun showNotificationExplanationDialog() {
        AlertDialog.Builder(this)
            .setTitle(getString(R.string.enable_push_notifications))
            .setMessage(getString(R.string.notification_explanation))
            .setPositiveButton(getString(R.string.allow_notifications)) { dialog, _ ->
                dialog.dismiss()
                Log.d("NotificationPermission", "Requesting notification permission")
                notificationPermissionLauncher.launch(notificationPermission)
            }
            .setNegativeButton(getString(R.string.not_now)) { dialog, _ ->
                dialog.dismiss()
                Log.w("NotificationPermission", "User declined notification permission")
                showCustomNotificationDialog(false)
                pendingUserData?.let { proceedAfterPermission(it) }
            }
            .setCancelable(false)
            .show()
    }

    private fun showCustomNotificationDialog(isGranted: Boolean) {
        if (isGranted) {
            handler.post {
                Snackbar.make(
                    findViewById(android.R.id.content),
                    "Notifikasi push sudah diaktifkan! Anda akan menerima pembaruan penting.",
                    Snackbar.LENGTH_SHORT
                ).show()
            }
        } else {
            handler.post {
                Snackbar.make(
                    findViewById(android.R.id.content),
                    "Notifikasi dinonaktifkan. Anda bisa mengaktifkannya nanti di Pengaturan.",
                    Snackbar.LENGTH_SHORT
                ).show()
            }
        }
    }

    private fun proceedAfterPermission(userData: Login) {
        showProgressDialog(false)

        Preferences.setAccessToken(this@LoginActivity, "Bearer ${userData.access_token}")
        Preferences.setRefreshToken(this@LoginActivity, "Bearer ${userData.refresh_token}")

        val gson = Gson()
        val data = gson.toJson(userData.user)
        Preferences.setUserData(this@LoginActivity, data)

        setupFCMAndLogin(userData)

        pendingUserData = null
    }

    private fun setupFCMAndLogin(userData: Login) {
        val newTopic = userData.user.kode.toString().trim()
        if (newTopic.isBlank()) {
            Log.w("FCM", "newTopic blank, skip subscribe")
            completeLoginProcess()
            return
        }

        val oldTopic = Preferences.getLastFcmTopic(this).trim()

        FirebaseMessaging.getInstance().token.addOnCompleteListener { tokenTask ->
            if (tokenTask.isSuccessful) {
                Log.d("FCM", "Token: ${tokenTask.result}")
            } else {
                Log.w("FCM", "Failed to get token", tokenTask.exception)
            }

            // 1) Unsubscribe old topic jika beda
            val doSubscribeNew = {
                FirebaseMessaging.getInstance().subscribeToTopic(newTopic)
                    .addOnCompleteListener { subTask ->
                        Log.d(
                            "FCM",
                            "subscribe topic=$newTopic success=${subTask.isSuccessful} err=${subTask.exception}"
                        )

                        if (subTask.isSuccessful) {
                            Preferences.setLastFcmTopic(this, newTopic)
                        }
                        completeLoginProcess()
                    }
            }

            if (oldTopic.isNotBlank() && oldTopic != newTopic) {
                FirebaseMessaging.getInstance().unsubscribeFromTopic(oldTopic)
                    .addOnCompleteListener { unSubTask ->
                        Log.d(
                            "FCM",
                            "unsubscribe oldTopic=$oldTopic success=${unSubTask.isSuccessful} err=${unSubTask.exception}"
                        )
                        doSubscribeNew()
                    }
            } else {
                // old kosong atau sama -> langsung subscribe
                doSubscribeNew()
            }
        }
    }

    private fun completeLoginProcess() {
        showProgressDialog(false)
        navigateTo(MainActivity::class.java, R.anim.right_in,
            R.anim.left_out)
        finish()
    }

    override fun onDestroy() {
        super.onDestroy()
        handler.removeCallbacksAndMessages(null)
    }
}