/**
 * Sheet — slide-in panel overlay.
 *
 * Compound pattern (preferred):
 *   <Sheet open={…} onOpenChange={…}>
 *     <SheetContent side="right">
 *       <SheetHeader><SheetTitle>…</SheetTitle></SheetHeader>
 *       …body…
 *     </SheetContent>
 *   </Sheet>
 *
 * The `Sheet` component is a thin wrapper over DialogPrimitive.Root so that
 * all Radix dialog context (close, focus-trap, aria) works as expected.
 *
 * Backward-compat helper: `SheetSimple` accepts a `title` string prop and
 * renders the full panel internally (used by ProjectFormSheet).
 */
import * as React from 'react'
import * as DialogPrimitive from '@radix-ui/react-dialog'
import { X } from 'lucide-react'
import { cn } from '../lib/cn'

// ── Sheet root (compound pattern) ────────────────────────────────────────────

type SheetSide = 'left' | 'right' | 'bottom'
type SheetSize = 'sm' | 'md' | 'lg' | 'xl'

export interface SheetProps {
  open: boolean
  onOpenChange: (open: boolean) => void
  side?: SheetSide
  size?: SheetSize
  children?: React.ReactNode
}

interface SheetDefaultsValue {
  side: SheetSide
  size: SheetSize
}

const SheetDefaultsContext = React.createContext<SheetDefaultsValue>({
  side: 'right',
  size: 'md',
})

export function Sheet({ open, onOpenChange, side = 'right', size = 'md', children }: SheetProps) {
  return (
    <SheetDefaultsContext.Provider value={{ side, size }}>
      <DialogPrimitive.Root open={open} onOpenChange={onOpenChange}>
        {children}
      </DialogPrimitive.Root>
    </SheetDefaultsContext.Provider>
  )
}

// ── SheetContent ──────────────────────────────────────────────────────────────

export const sideMap: Record<SheetSide, string> = {
  left: 'inset-y-0 start-0 h-full border-e',
  right: 'inset-y-0 end-0 h-full border-s',
  bottom: 'inset-x-0 bottom-0 w-full border-t',
}

export const panelWidthMap: Record<SheetSize, string> = {
  sm: 'max-w-screen-sm',
  md: 'max-w-screen-md',
  lg: 'max-w-screen-lg',
  xl: 'max-w-screen-xl',
}

export const panelHeightMap: Record<SheetSize, string> = {
  sm: 'max-h-[40vh]',
  md: 'max-h-[56vh]',
  lg: 'max-h-[72vh]',
  xl: 'max-h-[88vh]',
}

export interface SheetContentProps extends React.HTMLAttributes<HTMLDivElement> {
  side?: SheetSide
  size?: SheetSize
  children?: React.ReactNode
}

export function SheetContent({ children, className, side, size, style, ...rest }: SheetContentProps) {
  const defaults = React.useContext(SheetDefaultsContext)
  const resolvedSide = side ?? defaults.side
  const resolvedSize = size ?? defaults.size

  return (
    <DialogPrimitive.Portal>
      <DialogPrimitive.Overlay className="fixed inset-0 z-50 bg-ink/40 motion-reduce:animate-none" />
      <DialogPrimitive.Content
        className={cn(
          'fixed z-50 flex flex-col gap-4 overflow-y-auto border-line bg-surface p-6 text-ink shadow',
          'transition-transform duration-150 motion-reduce:transition-none focus:outline-none',
          sideMap[resolvedSide],
          resolvedSide !== 'bottom' ? cn('w-full', panelWidthMap[resolvedSize]) : panelHeightMap[resolvedSize],
          className,
        )}
        style={style}
        {...(rest as React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>)}
      >
        {children}
        <DialogPrimitive.Close
          className="absolute end-4 top-4 rounded text-ink-faint hover:text-ink focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent-border"
          aria-label="Close"
        >
          <X className="h-4 w-4" aria-hidden="true" />
        </DialogPrimitive.Close>
      </DialogPrimitive.Content>
    </DialogPrimitive.Portal>
  )
}

// ── SheetHeader ───────────────────────────────────────────────────────────────

export function SheetHeader({ children, className, ...rest }: React.HTMLAttributes<HTMLDivElement>) {
  return (
    <div className={cn('flex flex-col gap-2', className)} {...rest}>
      {children}
    </div>
  )
}

// ── SheetTitle ────────────────────────────────────────────────────────────────

export function SheetTitle({ children, className, ...rest }: React.HTMLAttributes<HTMLHeadingElement>) {
  return (
    <DialogPrimitive.Title
      className={cn('text-title-2 font-medium text-ink', className)}
      {...(rest as React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>)}
    >
      {children}
    </DialogPrimitive.Title>
  )
}
