package com.amz.genie.helpers

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.database.Cursor
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.net.Uri
import android.provider.OpenableColumns
import android.util.Base64
import android.util.Log
import android.view.View
import android.webkit.MimeTypeMap
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.amz.genie.activities.LoginActivity
import com.google.firebase.FirebaseApp
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.messaging.FirebaseMessaging
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.asRequestBody
import java.io.File
import java.io.FileOutputStream
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale

object Utils {
    fun isNetworkAvailable(context: Context): Boolean {
        val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        val network = connectivityManager.activeNetwork ?: return false
        val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
        return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
    }

    fun formatDateTime(raw: String): String {
        return try {
            val locale = Locale("id", "ID")
            val inFmt = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", locale)
            val date = inFmt.parse(raw) ?: return raw

            fun isSameDay(a: Calendar, b: Calendar): Boolean {
                return a.get(Calendar.YEAR) == b.get(Calendar.YEAR) &&
                        a.get(Calendar.DAY_OF_YEAR) == b.get(Calendar.DAY_OF_YEAR)
            }

            val cal = Calendar.getInstance().apply { time = date }
            val today = Calendar.getInstance()
            val yesterday = Calendar.getInstance().apply { add(Calendar.DAY_OF_YEAR, -1) }

            val timeStr = SimpleDateFormat("HH:mm", locale).format(date)

            when {
                isSameDay(cal, today) -> timeStr
                isSameDay(cal, yesterday) -> "Kemarin $timeStr"
                isWithinLastDays(date, 7) -> {
                    val dayStr = SimpleDateFormat("EEEE", locale).format(date).replace(".", "")
                    "$dayStr $timeStr"
                }
                else -> {
                    val dateStr = SimpleDateFormat("dd/MM/yy", locale).format(date)
                    "$dateStr $timeStr"
                }
            }
        } catch (e: Exception) {
            raw
        }
    }

    private fun isWithinLastDays(date: Date, days: Int): Boolean {
        val diff = System.currentTimeMillis() - date.time
        val limit = days.toLong() * 24L * 60L * 60L * 1000L
        return diff in 0 until limit
    }

    fun isFemale(gender: String?): Boolean {
        return gender == "P"
    }

    fun showEmpty(isEmpty: Boolean, tvEmpty: TextView, rl: RecyclerView) {
        tvEmpty.visibility = if (isEmpty) View.VISIBLE else View.GONE
        rl.visibility = if (isEmpty) View.GONE else View.VISIBLE
    }

    fun Context.queryDisplayName(uri: Uri): String? {
        val projection = arrayOf(OpenableColumns.DISPLAY_NAME)
        return runCatching {
            contentResolver.query(uri, projection, null, null, null)?.use { cursor: Cursor ->
                val idx = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
                if (idx == -1) return@use null
                cursor.moveToFirst()
                cursor.getString(idx)
            }
        }.getOrNull()
    }

    fun Context.copyUriToCacheFile(
        uri: Uri,
        prefix: String = "ATTACH_"
    ): File {
        val mime = contentResolver.getType(uri).orEmpty()

        val nameFromProvider = queryDisplayName(uri)
        val extFromMime = runCatching {
            MimeTypeMap.getSingleton().getExtensionFromMimeType(mime)
        }.getOrNull().orEmpty()

        // Nama file aman
        val baseName = nameFromProvider?.takeIf { it.isNotBlank() }
            ?: "${prefix}${System.currentTimeMillis()}"

        val safeName = when {
            extFromMime.isNotBlank() && !baseName.endsWith(".$extFromMime", true) -> "$baseName.$extFromMime"
            else -> baseName
        }

        val outFile = File(cacheDir, safeName)

        contentResolver.openInputStream(uri)?.use { input ->
            FileOutputStream(outFile).use { output ->
                input.copyTo(output)
            }
        } ?: throw IllegalStateException("Gagal membuka file dari Uri: $uri")

        return outFile
    }

    fun Context.uriToMultipartPart(
        partName: String,
        uri: Uri,
        filenameOverride: String? = null
    ): MultipartBody.Part {
        val mime = contentResolver.getType(uri).orEmpty()
        val file = copyUriToCacheFile(uri)

        val mediaType = mime.toMediaTypeOrNull()
        val body = file.asRequestBody(mediaType)

        val filename = filenameOverride ?: (queryDisplayName(uri) ?: file.name)
        return MultipartBody.Part.createFormData(partName, filename, body)
    }

    fun forceLogoutAndGoLogin(activity: Activity) {
        val firebaseReady = FirebaseApp.getApps(activity.applicationContext).isNotEmpty()

        // ambil topic sebelum clear prefs
        val oldTopic = Preferences.getLastFcmTopic(activity).trim()

        fun finishLogout() {
            // clear semua data setelah unsubscribe selesai
            Preferences.clearAll(activity)
            goLoginClearTask(activity)
        }

        // Sign out FirebaseAuth (kalau dipakai)
        runCatching {
            if (firebaseReady) FirebaseAuth.getInstance().signOut()
        }.onFailure {
            Log.w("Logout", "FirebaseAuth.signOut failed: ${it.message}", it)
        }

        if (!firebaseReady) {
            finishLogout()
            return
        }

        // 1) Unsubscribe dari topic terakhir (kalau ada)
        val doDeleteToken = {
            runCatching {
                FirebaseMessaging.getInstance().deleteToken()
                    .addOnCompleteListener {
                        finishLogout()
                    }
            }.onFailure {
                Log.w("Logout", "deleteToken failed: ${it.message}", it)
                finishLogout()
            }
        }

        if (oldTopic.isNotBlank()) {
            FirebaseMessaging.getInstance().unsubscribeFromTopic(oldTopic)
                .addOnCompleteListener { task ->
                    Log.d(
                        "Logout",
                        "unsubscribe topic=$oldTopic success=${task.isSuccessful} err=${task.exception}"
                    )
                    // bersihkan last topic
                    Preferences.setLastFcmTopic(activity, "")
                    doDeleteToken()
                }
        } else {
            doDeleteToken()
        }
    }

    private fun goLoginClearTask(activity: Activity) {
        val intent = Intent(activity, LoginActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
        }
        activity.startActivity(intent)
        activity.finish()
    }

    fun uriToBase64(context: Context, uri: Uri): String? {
        return try {
            val inputStream = context.contentResolver.openInputStream(uri)
            val bytes = inputStream?.readBytes()
            inputStream?.close()
            if (bytes != null) {
                Base64.encodeToString(bytes, Base64.DEFAULT)
            } else null
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }

}