// shadcn Tabs — CSS-only with the :target trick OR a tiny client
// state hook. V1 ships a controlled component using React state;
// island-eligible. Apps wanting zero-JS tabs use the :target form
// (anchor-based) which we don't ship as a primitive yet.

import {
  createContext, useContext, useState,
  type HTMLAttributes, type ReactNode,
} from 'react'
import { cn } from '../cn'

interface TabsContextValue {
  readonly value: string
  readonly setValue: (v: string) => void
}
const TabsContext = createContext<TabsContextValue | null>(null)

interface TabsProps extends HTMLAttributes<HTMLDivElement> {
  readonly defaultValue: string
  readonly value?: string
  readonly onValueChange?: (v: string) => void
}

export const Tabs = ({
  defaultValue, value, onValueChange, className, children, ...props
}: TabsProps): ReactNode => {
  const [uncontrolled, setUncontrolled] = useState(defaultValue)
  const current = value ?? uncontrolled
  const setValue = (v: string): void => {
    if (value === undefined) setUncontrolled(v)
    onValueChange?.(v)
  }
  return (
    <TabsContext.Provider value={{ value: current, setValue }}>
      <div data-slot="tabs" className={cn('flex flex-col gap-2', className)} {...props}>
        {children}
      </div>
    </TabsContext.Provider>
  )
}

export const TabsList = ({ className, ...props }: HTMLAttributes<HTMLDivElement>): ReactNode => (
  <div
    data-slot="tabs-list"
    role="tablist"
    className={cn(
      'inline-flex h-9 w-fit items-center justify-center rounded-lg bg-muted text-muted-foreground p-1',
      className,
    )}
    {...props}
  />
)

interface TabsTriggerProps extends HTMLAttributes<HTMLButtonElement> {
  readonly value: string
}

export const TabsTrigger = ({ value, className, children, ...props }: TabsTriggerProps): ReactNode => {
  const ctx = useContext(TabsContext)
  if (!ctx) throw new Error('TabsTrigger must be inside <Tabs>')
  const active = ctx.value === value
  return (
    <button
      data-slot="tabs-trigger"
      role="tab"
      type="button"
      aria-selected={active}
      onClick={() => ctx.setValue(value)}
      className={cn(
        'inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium transition-all',
        'focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50',
        active
          ? 'bg-background text-foreground shadow-sm'
          : 'hover:text-foreground',
        className,
      )}
      {...props}
    >
      {children}
    </button>
  )
}

interface TabsContentProps extends HTMLAttributes<HTMLDivElement> {
  readonly value: string
}

export const TabsContent = ({ value, className, children, ...props }: TabsContentProps): ReactNode => {
  const ctx = useContext(TabsContext)
  if (!ctx) throw new Error('TabsContent must be inside <Tabs>')
  if (ctx.value !== value) return null
  return (
    <div
      data-slot="tabs-content"
      role="tabpanel"
      className={cn('flex-1 outline-none', className)}
      {...props}
    >
      {children}
    </div>
  )
}
