'use client'

import { type ReactNode } from 'react'
import { cn } from './utils'

export interface QueryBoundaryProps {
  isLoading?: boolean
  isError?: boolean
  error?: Error | string | null
  isEmpty?: boolean
  loadingMessage?: string
  errorMessage?: string
  emptyMessage?: string
  emptyIcon?: ReactNode
  className?: string
  children: ReactNode
}

function Spinner() {
  return (
    <svg
      className="h-5 w-5 animate-spin text-foreground-tertiary"
      viewBox="0 0 24 24"
      fill="none"
      aria-hidden="true"
    >
      <circle
        cx="12"
        cy="12"
        r="10"
        stroke="currentColor"
        strokeWidth="3"
        strokeDasharray="31.42 31.42"
        strokeLinecap="round"
      />
    </svg>
  )
}

export function QueryBoundary({
  isLoading,
  isError,
  error,
  isEmpty,
  loadingMessage = 'Loading...',
  errorMessage,
  emptyMessage = 'No data available',
  emptyIcon,
  className,
  children,
}: QueryBoundaryProps) {
  if (isLoading) {
    return (
      <div
        className={cn(
          'flex min-h-[220px] flex-col items-center justify-center gap-3 text-foreground-tertiary',
          className
        )}
      >
        <Spinner />
        <p className="text-sm">{loadingMessage}</p>
      </div>
    )
  }

  if (isError) {
    const msg =
      errorMessage ??
      (error instanceof Error ? error.message : String(error ?? 'An error occurred'))
    return (
      <div
        role="alert"
        aria-live="polite"
        className={cn(
          'rounded-lg border border-accent-rose/25 bg-accent-rose/5 px-4 py-3 text-sm text-accent-rose',
          className
        )}
      >
        {msg}
      </div>
    )
  }

  if (isEmpty) {
    return (
      <div
        className={cn(
          'flex min-h-[220px] flex-col items-center justify-center gap-2 text-foreground-tertiary',
          className
        )}
      >
        {emptyIcon && <div className="text-foreground-muted [&>svg]:size-10">{emptyIcon}</div>}
        <p className="text-sm">{emptyMessage}</p>
      </div>
    )
  }

  return <>{children}</>
}
