package me.khodak.claudeusage

import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.GregorianCalendar
import java.util.Locale
import java.util.TimeZone
import java.util.concurrent.TimeUnit

/**
 * Anthropic peak usage window, mirroring hamed-elfayome/Claude-Usage-Tracker's PeakHoursService:
 * 5:00–11:00 AM America/Los_Angeles, Monday–Friday. Tokens burn faster during this window.
 */
object PeakHours {

    private const val PEAK_START_HOUR = 5   // 5 AM PT inclusive
    private const val PEAK_END_HOUR = 11    // 11 AM PT exclusive
    private val PT: TimeZone = TimeZone.getTimeZone("America/Los_Angeles")

    data class PeakState(
        val active: Boolean,
        val endsInLabel: String,   // e.g. "ends in 2h 14m" (only meaningful when active)
        val windowLabel: String    // e.g. "5–11 AM PT · 8 AM–2 PM your time"
    )

    fun isPeak(now: Long = System.currentTimeMillis()): Boolean {
        val cal = GregorianCalendar(PT).apply { timeInMillis = now }
        val dow = cal.get(Calendar.DAY_OF_WEEK) // Sun=1 .. Sat=7
        val weekday = dow in Calendar.MONDAY..Calendar.FRIDAY
        val hour = cal.get(Calendar.HOUR_OF_DAY)
        return weekday && hour in PEAK_START_HOUR until PEAK_END_HOUR
    }

    /** Epoch millis of 11:00 AM PT on the current PT day (peak window close). */
    fun peakEndEpoch(now: Long = System.currentTimeMillis()): Long {
        val cal = GregorianCalendar(PT).apply {
            timeInMillis = now
            set(Calendar.HOUR_OF_DAY, PEAK_END_HOUR)
            set(Calendar.MINUTE, 0)
            set(Calendar.SECOND, 0)
            set(Calendar.MILLISECOND, 0)
        }
        return cal.timeInMillis
    }

    fun state(now: Long = System.currentTimeMillis()): PeakState {
        val active = isPeak(now)
        val endsIn = if (active) {
            val rem = peakEndEpoch(now) - now
            val h = TimeUnit.MILLISECONDS.toHours(rem)
            val m = TimeUnit.MILLISECONDS.toMinutes(rem) % 60
            if (h > 0) "ends in ${h}h ${m}m" else "ends in ${m}m"
        } else ""
        return PeakState(active, endsIn, localWindowString(now))
    }

    /** "5–11 AM PT · 8 AM–2 PM your time" — peak window translated to the device timezone. */
    fun localWindowString(now: Long = System.currentTimeMillis()): String {
        val local = TimeZone.getDefault()
        if (local.id == PT.id) return "5–11 AM PT"
        val startLocal = ptHourToLocal(PEAK_START_HOUR, now, local)
        val endLocal = ptHourToLocal(PEAK_END_HOUR, now, local)
        val fmt = SimpleDateFormat("h a", Locale.US).apply { timeZone = local }
        val s = fmt.format(Date(startLocal)).replace(" ", " ")
        val e = fmt.format(Date(endLocal)).replace(" ", " ")
        return "5–11 AM PT · $s–$e your time"
    }

    private fun ptHourToLocal(ptHour: Int, now: Long, local: TimeZone): Long {
        val cal = GregorianCalendar(PT).apply {
            timeInMillis = now
            set(Calendar.HOUR_OF_DAY, ptHour)
            set(Calendar.MINUTE, 0)
            set(Calendar.SECOND, 0)
            set(Calendar.MILLISECOND, 0)
        }
        return cal.timeInMillis // absolute instant; formatting in `local` renders local wall time
    }
}
