// useLastState — v0.23.0 / roadmap item #29: server-side sign-in state
// resume. Two responsibilities, kept in one small hook so App.jsx's
// surface stays minimal:
//
//   1. Debounce-post the authenticated user's current route to
//      `PUT /api/me/last-state` on every route change (~1s debounce so
//      a fast click-through doesn't spray the endpoint). Anonymous
//      users: no-op. Best-effort: a failed POST never disrupts nav.
//
//   2. On the first authenticated load, read the stored `last_route`
//      (handed back on `/api/auth/me`) and `navigate()` to it ONCE.
//      Stale routes (a withdrawn RFC, a slug the user lost rights to)
//      are not special-cased here: navigating lands on whatever that
//      route renders today, and the existing routing already falls
//      through to the catalog/empty-state for a missing RFC. Keeping
//      this dumb is deliberate (see SPEC §6.2 + the #29 scope note).
//
// Ordering with #21 Part C (Amplitude identify): App.jsx fires
// `identify` in its own effect when `me.user.id` first appears. This
// hook's resume redirect is gated on `identifyReady` — App.jsx flips it
// true only after the identify effect has run — so the redirect always
// happens AFTER identify, preserving the identify-then-track ordering
// the roadmap calls out.
import { useEffect, useRef } from 'react'
import { putLastState } from '../api'

// ~1s debounce on the route-change POST. A frontend constant, not a
// server knob — the backend takes whatever lands.
const DEBOUNCE_MS = 1000

// Routes we never want to resume *to* — auth/landing surfaces that
// would be nonsensical or hostile to drop a returning user onto. We
// still record them (cheap, and the user may legitimately be sitting on
// /docs), but the resume redirect skips them and falls through to the
// default landing. Anything not listed resumes normally.
const NON_RESUMABLE_PREFIXES = ['/login', '/welcome', '/invites/', '/invitations/']

function isResumable(route) {
  if (!route || typeof route !== 'string') return false
  if (route === '/') return false // "/" is already the default landing
  return !NON_RESUMABLE_PREFIXES.some(p => route.startsWith(p))
}

/**
 * @param {object}   opts
 * @param {boolean}  opts.authenticated  whether a viewer is signed in
 * @param {string}   opts.pathname       current location.pathname
 * @param {boolean}  opts.identifyReady   App flips true after identify fires
 * @param {string|null} opts.lastRoute    stored route from /api/auth/me
 * @param {function} opts.navigate        react-router navigate()
 */
export function useLastState({ authenticated, pathname, identifyReady, lastRoute, navigate }) {
  // ── 1. Debounced route-change POST ────────────────────────────────
  const timerRef = useRef(null)
  useEffect(() => {
    if (!authenticated) return undefined
    if (timerRef.current) clearTimeout(timerRef.current)
    timerRef.current = setTimeout(() => {
      // Best-effort — swallow failures so an offline/401 POST never
      // surfaces as a navigation error.
      putLastState(pathname).catch(() => {})
    }, DEBOUNCE_MS)
    return () => {
      if (timerRef.current) clearTimeout(timerRef.current)
    }
  }, [authenticated, pathname])

  // ── 2. One-time resume redirect ───────────────────────────────────
  // Fires once, after identify is ready, when there's a resumable
  // stored route AND the user is currently sitting on the default
  // landing ("/"). We only redirect from "/" so we never yank a user
  // who deep-linked somewhere specific (or refreshed mid-RFC) back to
  // their last route.
  const resumedRef = useRef(false)
  useEffect(() => {
    if (resumedRef.current) return
    if (!authenticated || !identifyReady) return
    // Only resume when the app booted on the default landing — a hard
    // sign-in nav lands on "/", which is exactly the case we want.
    if (pathname !== '/') {
      resumedRef.current = true // user deep-linked; don't resume later either
      return
    }
    if (isResumable(lastRoute)) {
      resumedRef.current = true
      navigate(lastRoute, { replace: true })
    } else {
      resumedRef.current = true // nothing to resume to; keep default landing
    }
  }, [authenticated, identifyReady, lastRoute, pathname, navigate])
}
