import { useCallback, useEffect, useRef, useState } from 'react'
import { api, type DocUpdate } from '../api/client'

export type SaveStatus = 'idle' | 'pending' | 'saving' | 'saved' | 'error'

const DEBOUNCE_MS = 1500
const SAVED_FADE_MS = 3000

// useAutoSave debounces document saves. Call schedule() on every edit; it fires
// PUT /api/docs/:id 1.5s after the last change. status drives the StatusBar:
// pending → saving → saved (fades to idle after 3s).
export function useAutoSave(docId: string | null) {
  const [status, setStatus] = useState<SaveStatus>('idle')

  const debounceRef = useRef<ReturnType<typeof setTimeout>>(undefined)
  const fadeRef = useRef<ReturnType<typeof setTimeout>>(undefined)
  const pendingRef = useRef<DocUpdate | null>(null)
  // Latest doc id, read inside the timer so a doc switch doesn't save to the old one.
  const docIdRef = useRef(docId)
  docIdRef.current = docId

  const flush = useCallback(async () => {
    const id = docIdRef.current
    const body = pendingRef.current
    pendingRef.current = null
    if (!id || !body) return

    setStatus('saving')
    try {
      await api.updateDoc(id, body)
      setStatus('saved')
      clearTimeout(fadeRef.current)
      fadeRef.current = setTimeout(() => setStatus('idle'), SAVED_FADE_MS)
    } catch (err) {
      console.error('auto-save failed', err)
      setStatus('error')
    }
  }, [])

  const schedule = useCallback(
    (update: DocUpdate) => {
      pendingRef.current = { ...pendingRef.current, ...update }
      setStatus('pending')
      clearTimeout(fadeRef.current)
      clearTimeout(debounceRef.current)
      debounceRef.current = setTimeout(flush, DEBOUNCE_MS)
    },
    [flush],
  )

  // Save any pending edits immediately (e.g. before switching documents).
  const saveNow = useCallback(() => {
    clearTimeout(debounceRef.current)
    return flush()
  }, [flush])

  useEffect(
    () => () => {
      clearTimeout(debounceRef.current)
      clearTimeout(fadeRef.current)
    },
    [],
  )

  return { status, schedule, saveNow }
}
