import { ref, onUnmounted } from 'vue'

export function useTimer() {
  const remaining = ref(0)
  const isPaused = ref(false)
  let intervalId = null
  let onTickFn = null
  let onExpireFn = null
  let endsAt = 0
  let pausedAt = 0
  let lastRemaining = 0

  function start(seconds, { onTick, onExpire } = {}) {
    _clear()
    remaining.value = seconds
    lastRemaining = seconds
    isPaused.value = false
    onTickFn = onTick || null
    onExpireFn = onExpire || null
    endsAt = Date.now() + seconds * 1000
    intervalId = setInterval(_step, 250)
  }

  function _step() {
    if (isPaused.value) return

    const now = Date.now()
    const newRemaining = Math.max(0, Math.ceil((endsAt - now) / 1000))

    if (newRemaining < lastRemaining) {
      // Fire onTick for each integer second that passed (catches skipped seconds)
      for (let s = lastRemaining - 1; s >= newRemaining; s--) {
        if (s > 0) onTickFn?.(s)
      }
      lastRemaining = newRemaining
    }

    remaining.value = newRemaining

    if (newRemaining <= 0) {
      _clear()
      onExpireFn?.()
    }
  }

  function pause() {
    if (isPaused.value) return
    isPaused.value = true
    pausedAt = Date.now()
  }

  function resume() {
    if (!isPaused.value) return
    // Shift endsAt forward by the paused duration
    endsAt += Date.now() - pausedAt
    isPaused.value = false
  }

  function stop() {
    _clear()
    remaining.value = 0
    isPaused.value = false
    onTickFn = null
    onExpireFn = null
    endsAt = 0
    pausedAt = 0
    lastRemaining = 0
  }

  function _clear() {
    if (intervalId) {
      clearInterval(intervalId)
      intervalId = null
    }
  }

  // Recompute remaining immediately when the tab becomes visible
  function _onVisibilityChange() {
    if (!document.hidden && !isPaused.value && intervalId) {
      _step()
    }
  }

  document.addEventListener('visibilitychange', _onVisibilityChange)

  onUnmounted(() => {
    _clear()
    document.removeEventListener('visibilitychange', _onVisibilityChange)
  })

  return { remaining, isPaused, start, pause, resume, stop }
}
