import { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { AlertCircle, Info, X } from 'lucide-react'
import { cn } from '@/lib/utils'
import { useAuthSessionExpiry } from '@/hooks/useAuthSessionExpiry'
import { authApi } from '@/api/auth'
import { useAuthStore } from '@/store/authStore'

/**
 * Top-of-app notice that fires when the session is within 5 minutes of
 * idle OR absolute expiry. Behavior differs by which window is closer
 * (per docs/plans/2026-05-13-session-expiration-policy.md §4.8):
 *
 * - Idle: warning-amber tone, "Stay signed in" button hits /auth/refresh.
 * - Absolute: info-cyan tone, no action — re-auth is required.
 *
 * Persists until the user dismisses, refreshes, or the window expires.
 */
export function SessionExpiryToast() {
  const { warning, reason, idleExpiresAt, absoluteExpiresAt } = useAuthSessionExpiry()
  const setTokens = useAuthStore((s) => s.setTokens)
  const navigate = useNavigate()
  const [busy, setBusy] = useState(false)
  const [dismissed, setDismissed] = useState(false)

  if (warning !== 'soon' || dismissed) return null

  const handleStay = async () => {
    setBusy(true)
    try {
      const refreshed = await authApi.refresh()
      localStorage.setItem('access_token', refreshed.access_token)
      localStorage.setItem('refresh_token', refreshed.refresh_token)
      setTokens(refreshed)
      setDismissed(true)
    } catch {
      // The axios interceptor handles the redirect on session_expired_*;
      // if we land here, something else went wrong — just close the toast.
      setDismissed(true)
    } finally {
      setBusy(false)
    }
  }

  const handleSignInNow = () => navigate('/login')

  // ── Format the deadline for the absolute case ──
  const deadline = reason === 'idle' ? idleExpiresAt : absoluteExpiresAt
  const deadlineLabel = deadline
    ? deadline.toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' })
    : ''

  const isIdle = reason === 'idle'
  const Icon = isIdle ? AlertCircle : Info

  return (
    <div
      role="status"
      aria-live="polite"
      className={cn(
        'fixed top-4 right-4 z-50 max-w-md rounded-lg border p-4 shadow-lg',
        'flex items-start gap-3',
        isIdle
          ? 'bg-warning-dim border-warning/30 text-warning'
          : 'bg-info-dim border-info/30 text-info',
      )}
    >
      <Icon size={18} className="mt-0.5 shrink-0" />
      <div className="flex-1 min-w-0">
        <p className="text-sm font-medium">
          {isIdle
            ? 'Your session times out in 5 minutes.'
            : `Your session ends at ${deadlineLabel} for security.`}
        </p>
        <p className="mt-0.5 text-xs opacity-90">
          {isIdle
            ? 'Click to stay signed in.'
            : "You'll need to sign in again."}
        </p>
        <div className="mt-2 flex items-center gap-2">
          {isIdle ? (
            <button
              type="button"
              onClick={handleStay}
              disabled={busy}
              className={cn(
                'rounded-md px-3 py-1.5 text-xs font-medium',
                'bg-warning/20 text-warning border border-warning/40 hover:bg-warning/30',
                'disabled:opacity-50',
              )}
            >
              {busy ? 'Refreshing…' : 'Stay signed in'}
            </button>
          ) : (
            <button
              type="button"
              onClick={handleSignInNow}
              className={cn(
                'rounded-md px-3 py-1.5 text-xs font-medium',
                'bg-info/20 text-info border border-info/40 hover:bg-info/30',
              )}
            >
              Sign in now
            </button>
          )}
          <button
            type="button"
            onClick={() => setDismissed(true)}
            className="text-xs opacity-70 hover:opacity-100"
          >
            Dismiss
          </button>
        </div>
      </div>
      <button
        type="button"
        onClick={() => setDismissed(true)}
        aria-label="Dismiss"
        className="shrink-0 opacity-70 hover:opacity-100"
      >
        <X size={14} />
      </button>
    </div>
  )
}
