/**
 * Page-visible auto refresh with optional dynamic interval (setTimeout chain).
 */
import { onMounted, onBeforeUnmount } from 'vue'

export interface PageAutoRefreshOptions {
  /** Pause while browser tab is hidden (default true) */
  pauseWhenHidden?: boolean
  /** Run once when composable mounts (default false) */
  immediate?: boolean
}

export function usePageAutoRefresh(
  callback: () => void | Promise<void>,
  intervalMs: number | (() => number),
  options: PageAutoRefreshOptions = {},
) {
  const { pauseWhenHidden = true, immediate = false } = options
  let timer: ReturnType<typeof setTimeout> | null = null
  let disposed = false
  let inFlight = false

  function resolveInterval(): number {
    const v = typeof intervalMs === 'function' ? intervalMs() : intervalMs
    return Math.max(1000, v)
  }

  function clearTimer() {
    if (timer) {
      clearTimeout(timer)
      timer = null
    }
  }

  function scheduleNext() {
    clearTimer()
    if (disposed) return
    timer = setTimeout(() => {
      void tick()
    }, resolveInterval())
  }

  async function tick() {
    if (disposed) return
    if (pauseWhenHidden && document.visibilityState === 'hidden') {
      scheduleNext()
      return
    }
    if (inFlight) {
      scheduleNext()
      return
    }
    inFlight = true
    try {
      await callback()
    } finally {
      inFlight = false
      scheduleNext()
    }
  }

  function onVisibility() {
    if (disposed || !pauseWhenHidden) return
    if (document.visibilityState === 'visible') {
      void tick()
    }
  }

  onMounted(() => {
    if (immediate) void tick()
    else scheduleNext()
    if (pauseWhenHidden) {
      document.addEventListener('visibilitychange', onVisibility)
    }
  })

  onBeforeUnmount(() => {
    disposed = true
    clearTimer()
    if (pauseWhenHidden) {
      document.removeEventListener('visibilitychange', onVisibility)
    }
  })

  return { refresh: tick, stop: () => { disposed = true; clearTimer() } }
}
