'use client';

import * as React from 'react';
import { cn } from '@/lib/utils';

interface TabsContextValue {
  value: string;
  onValueChange: (value: string) => void;
  baseId: string;
  registerTab: (value: string) => void;
  unregisterTab: (value: string) => void;
  tabs: string[];
}

const TabsContext = React.createContext<TabsContextValue | null>(null);

function useTabs() {
  const context = React.useContext(TabsContext);
  if (!context) throw new Error('Tabs components must be used within <Tabs>');
  return context;
}

interface TabsProps extends React.HTMLAttributes<HTMLDivElement> {
  value: string;
  onValueChange: (value: string) => void;
}

let tabsCounter = 0;

function Tabs({ value, onValueChange, className, ...props }: TabsProps) {
  const [baseId] = React.useState(() => `tabs-${++tabsCounter}`);
  const [tabs, setTabs] = React.useState<string[]>([]);

  const registerTab = React.useCallback((tabValue: string) => {
    setTabs((prev) => (prev.includes(tabValue) ? prev : [...prev, tabValue]));
  }, []);

  const unregisterTab = React.useCallback((tabValue: string) => {
    setTabs((prev) => prev.filter((t) => t !== tabValue));
  }, []);

  return (
    <TabsContext.Provider value={{ value, onValueChange, baseId, registerTab, unregisterTab, tabs }}>
      <div className={cn('w-full', className)} {...props} />
    </TabsContext.Provider>
  );
}

const TabsList = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
  ({ className, ...props }, ref) => {
    const { tabs, value, onValueChange } = useTabs();

    const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
      const currentIndex = tabs.indexOf(value);
      if (currentIndex === -1) return;

      let nextIndex: number | null = null;

      switch (e.key) {
        case 'ArrowRight':
          nextIndex = (currentIndex + 1) % tabs.length;
          break;
        case 'ArrowLeft':
          nextIndex = (currentIndex - 1 + tabs.length) % tabs.length;
          break;
        case 'Home':
          nextIndex = 0;
          break;
        case 'End':
          nextIndex = tabs.length - 1;
          break;
        default:
          return;
      }

      e.preventDefault();
      const next = tabs[nextIndex];
      if (next) onValueChange(next);
    };

    return (
      <div
        ref={ref}
        role="tablist"
        onKeyDown={handleKeyDown}
        className={cn(
          'inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground',
          className,
        )}
        {...props}
      />
    );
  },
);
TabsList.displayName = 'TabsList';

interface TabsTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
  value: string;
}

const TabsTrigger = React.forwardRef<HTMLButtonElement, TabsTriggerProps>(
  ({ className, value, ...props }, ref) => {
    const { value: selectedValue, onValueChange, baseId, registerTab, unregisterTab } = useTabs();
    const isSelected = selectedValue === value;
    const internalRef = React.useRef<HTMLButtonElement | null>(null);

    React.useEffect(() => {
      registerTab(value);
      return () => unregisterTab(value);
    }, [value, registerTab, unregisterTab]);

    // Focus the newly selected tab
    React.useEffect(() => {
      if (isSelected && internalRef.current) {
        internalRef.current.focus();
      }
    }, [isSelected]);

    return (
      <button
        ref={(node) => {
          internalRef.current = node;
          if (typeof ref === 'function') ref(node);
          else if (ref) ref.current = node;
        }}
        role="tab"
        id={`${baseId}-trigger-${value}`}
        aria-selected={isSelected}
        aria-controls={`${baseId}-content-${value}`}
        tabIndex={isSelected ? 0 : -1}
        className={cn(
          'inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
          isSelected
            ? 'bg-background text-foreground shadow-sm'
            : 'hover:bg-background/50',
          className,
        )}
        onClick={() => onValueChange(value)}
        {...props}
      />
    );
  },
);
TabsTrigger.displayName = 'TabsTrigger';

interface TabsContentProps extends React.HTMLAttributes<HTMLDivElement> {
  value: string;
}

const TabsContent = React.forwardRef<HTMLDivElement, TabsContentProps>(
  ({ className, value, ...props }, ref) => {
    const { value: selectedValue, baseId } = useTabs();
    if (selectedValue !== value) return null;
    return (
      <div
        ref={ref}
        role="tabpanel"
        id={`${baseId}-content-${value}`}
        aria-labelledby={`${baseId}-trigger-${value}`}
        tabIndex={0}
        className={cn('mt-2 ring-offset-background focus-visible:outline-none', className)}
        {...props}
      />
    );
  },
);
TabsContent.displayName = 'TabsContent';

export { Tabs, TabsList, TabsTrigger, TabsContent };
