import { HTMLAttributes, ReactNode, useState } from 'react';
import { cn } from '@/lib/helper';

export interface TabItem {
  id: string;
  label: ReactNode;
  content?: ReactNode;
  disabled?: boolean;
  hide?: boolean;
}

export interface TabsProps
  extends Omit<HTMLAttributes<HTMLDivElement>, 'className'> {
  tabs: TabItem[];
  variant?: 'bordered' | 'lifted' | 'boxed';
  size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
  placement?: 'top' | 'bottom';
  /** Tab yang aktif secara default (uncontrolled mode) */
  defaultActiveId?: string;
  /** Tab yang aktif (controlled mode, dikontrol parent) */
  activeTabId?: string;
  className?:
    | string
    | {
        container?: string;
        wrapper?: string;
        tab?: string;
        content?: string;
        tabHeaderWrapper?: string;
      };
  onTabChange?: (tabId: string) => void;
  sideContent?: ReactNode;
}

const Tabs = ({
  tabs,
  variant,
  size = 'md',
  placement = 'top',
  defaultActiveId,
  activeTabId: controlledActiveId,
  className,
  onTabChange,
  sideContent,
  ...props
}: TabsProps) => {
  // State internal hanya dipakai kalau `activeTabId` (controlled) tidak diset
  const [uncontrolledActiveId, setUncontrolledActiveId] = useState(
    defaultActiveId || tabs[0]?.id || ''
  );

  const isControlled = controlledActiveId !== undefined;
  const activeTabId = isControlled ? controlledActiveId : uncontrolledActiveId;

  const handleTabChange = (tabId: string) => {
    if (tabId === activeTabId) return;
    if (!isControlled) setUncontrolledActiveId(tabId);
    onTabChange?.(tabId);
  };

  const {
    container: containerClassName,
    wrapper: wrapperClassName,
    tab: tabClassName,
    content: contentClassName,
    tabHeaderWrapper: tabHeaderWrapperClassName,
  } = typeof className === 'object'
    ? className
    : { wrapper: className, tab: undefined };

  const getTabsClasses = () => {
    const variantClasses: Record<string, string> = {
      bordered: 'tabs-bordered',
      lifted: 'tabs-lift',
      boxed: 'tabs-box',
    };

    const sizeClasses: Record<string, string> = {
      xs: 'tabs-xs',
      sm: 'tabs-sm',
      md: '',
      lg: 'tabs-lg',
      xl: 'tabs-xl',
    };

    const placementClasses: Record<string, string> = {
      top: '',
      bottom: 'tabs-bottom',
    };

    return cn(
      'tabs',
      variant && variantClasses[variant],
      sizeClasses[size],
      placementClasses[placement],
      wrapperClassName
    );
  };

  const getTabClasses = (isActive: boolean, isDisabled?: boolean) =>
    cn(
      'tab',
      {
        'tab-active': isActive,
        'tab-disabled': isDisabled,
      },
      tabClassName
    );

  const getSideContentClasses = () => {
    return cn('flex flex-row', tabHeaderWrapperClassName);
  };

  const activeContent = tabs.find((tab) => tab.id === activeTabId)?.content;

  return (
    <div
      {...props}
      className={cn(
        'w-full',
        typeof className === 'string' ? className : containerClassName
      )}
    >
      <div className={getSideContentClasses()}>
        <div role='tablist' className={getTabsClasses()}>
          {tabs.map(({ id, label, disabled, hide }) =>
            hide ? null : (
              <button
                key={id}
                role='tab'
                className={getTabClasses(id === activeTabId, disabled)}
                onClick={() => !disabled && handleTabChange(id)}
                disabled={disabled}
              >
                {label}
              </button>
            )
          )}
        </div>
        {sideContent && sideContent}
      </div>

      {activeContent && (
        <div className={cn('mt-4', contentClassName)}>{activeContent}</div>
      )}
    </div>
  );
};

export default Tabs;
