package me.khodak.claudeusage

import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import me.khodak.claudeusage.data.PreferencesManager
import me.khodak.claudeusage.data.UsageData

/**
 * Fires exactly two alerts per metric — one at 90% and one at 100% — and no more.
 *
 * Uses hysteresis, not the API's reset timestamp: each level fires once when usage first
 * crosses it, and only re-arms after usage drops back below that level (i.e. a new window /
 * usage reset). That keeps it quiet even if the reset time drifts between fetches. Only the
 * background worker calls this — never the in-app refresh loop — so you're not pinged while
 * you're already looking at the app.
 */
object Notifier {

    private const val CHANNEL_ID = "usage_alerts"
    private val LEVELS = intArrayOf(90, 100)

    fun checkAndNotify(context: Context, prefs: PreferencesManager, data: UsageData) {
        if (!prefs.isNotifyEnabled()) return
        val mgr = NotificationManagerCompat.from(context)
        if (!mgr.areNotificationsEnabled()) return  // OS-level or runtime permission off
        ensureChannel(context)

        evaluate(context, mgr, prefs, "session", data.fiveHourUtilization, "5-hour session")
        evaluate(context, mgr, prefs, "weekly", data.weeklyUtilization, "weekly")
    }

    private fun evaluate(
        context: Context,
        mgr: NotificationManagerCompat,
        prefs: PreferencesManager,
        metric: String,
        utilization: Float,
        label: String
    ) {
        if (utilization < 0f) return
        val util = utilization.toInt()
        for ((i, level) in LEVELS.withIndex()) {
            val key = "${metric}_$level"
            if (util >= level) {
                if (!prefs.wasNotified(key)) {
                    fire(context, mgr, notifId(metric, i), level, label, util)
                    prefs.setNotified(key, true)
                }
            } else if (prefs.wasNotified(key)) {
                prefs.setNotified(key, false)  // dropped below the line → re-arm for next window
            }
        }
    }

    private fun fire(
        context: Context,
        mgr: NotificationManagerCompat,
        notifId: Int,
        level: Int,
        label: String,
        util: Int
    ) {
        val title: String
        val body: String
        if (level >= 100) {
            title = "${label.replaceFirstChar { it.uppercase() }} limit reached"
            body = "You've hit 100% of your $label limit."
        } else {
            title = "${label.replaceFirstChar { it.uppercase() }} at $util%"
            body = "You're at $level% of your $label limit."
        }
        val notif = NotificationCompat.Builder(context, CHANNEL_ID)
            .setSmallIcon(R.drawable.ic_claude_burst)
            .setContentTitle(title)
            .setContentText(body)
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setAutoCancel(true)
            .setContentIntent(openAppIntent(context))
            .build()
        try {
            mgr.notify(notifId, notif)
        } catch (_: SecurityException) {
            // Notifications revoked between the check and post — nothing to do.
        }
    }

    // Stable id per (metric, level) so re-posts replace rather than stack.
    private fun notifId(metric: String, levelIndex: Int) =
        2000 + (if (metric == "weekly") 10 else 0) + levelIndex

    private fun ensureChannel(context: Context) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
        val mgr = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        if (mgr.getNotificationChannel(CHANNEL_ID) != null) return
        mgr.createNotificationChannel(
            NotificationChannel(
                CHANNEL_ID, "Usage alerts", NotificationManager.IMPORTANCE_DEFAULT
            ).apply { description = "Alerts at 90% and 100% of your Claude usage limits" }
        )
    }

    private fun openAppIntent(context: Context): PendingIntent {
        val intent = Intent(context, MainActivity::class.java)
            .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
        return PendingIntent.getActivity(
            context, 0, intent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )
    }
}
