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

/**
 * RadioGroupProps - Propriétés du composant RadioGroup
 *
 * @interface RadioGroupProps
 * @extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'>
 */
export interface RadioGroupProps
  extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {
  /**
   * Valeur sélectionnée du groupe de boutons radio
   *
   * @example
   * ```tsx
   * <RadioGroup value={selected} onValueChange={setSelected}>
   *   <RadioGroupItem value="option1" />
   *   <RadioGroupItem value="option2" />
   * </RadioGroup>
   * ```
   */
  value?: string;

  /**
   * Fonction appelée lorsque la valeur sélectionnée change
   *
   * @param {string} value - Nouvelle valeur sélectionnée
   *
   * @example
   * ```tsx
   * <RadioGroup onValueChange={(value) => console.log('Selected:', value)}>
   *   ...
   * </RadioGroup>
   * ```
   */
  onValueChange?: (value: string) => void;

  /**
   * Si `true`, désactive tous les boutons radio du groupe
   *
   * @default false
   */
  disabled?: boolean;
}

/**
 * RadioGroup - Composant de groupe de boutons radio avec design system Kodo
 *
 * Composant pour gérer un groupe de boutons radio mutuellement exclusifs.
 * Utilise le design system Kodo avec des styles cohérents et support pour l'accessibilité.
 *
 * @example
 * ```tsx
 * // Groupe de boutons radio simple
 * <RadioGroup value={selected} onValueChange={setSelected}>
 *   <RadioGroupItem value="option1" />
 *   <RadioGroupItem value="option2" />
 *   <RadioGroupItem value="option3" />
 * </RadioGroup>
 * ```
 *
 * @example
 * ```tsx
 * // Avec labels
 * <RadioGroup value={selected} onValueChange={setSelected}>
 *   <label>
 *     <RadioGroupItem value="option1" />
 *     Option 1
 *   </label>
 *   <label>
 *     <RadioGroupItem value="option2" />
 *     Option 2
 *   </label>
 * </RadioGroup>
 * ```
 *
 * @component
 * @param {RadioGroupProps} props - Propriétés du composant
 * @returns {JSX.Element} Élément div avec role="radiogroup" contenant les boutons radio
 */

const RadioGroup = React.forwardRef<HTMLDivElement, RadioGroupProps>(
  ({ className, value, onValueChange, disabled, children, ...props }, ref) => {
    // Collect RadioGroupItem values for arrow key navigation
    const itemValues: string[] = [];
    React.Children.forEach(children, (child) => {
      if (React.isValidElement(child) && child.type === RadioGroupItem && !child.props.disabled) {
        itemValues.push(child.props.value);
      }
    });

    const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
      if (itemValues.length === 0) return;
      const currentIndex = value ? itemValues.indexOf(value) : -1;
      let nextIndex: number | undefined;

      switch (e.key) {
        case 'ArrowDown':
        case 'ArrowRight':
          nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % itemValues.length;
          break;
        case 'ArrowUp':
        case 'ArrowLeft':
          nextIndex = currentIndex === -1 ? itemValues.length - 1 : (currentIndex - 1 + itemValues.length) % itemValues.length;
          break;
        default:
          return;
      }

      e.preventDefault();
      const nextValue = itemValues[nextIndex];
      if (nextValue !== undefined) onValueChange?.(nextValue);
      // Focus the newly selected radio
      const radios = (e.currentTarget as HTMLElement).querySelectorAll<HTMLInputElement>('input[type="radio"]');
      radios[nextIndex]?.focus();
    };

    return (
      <div
        ref={ref}
        className={cn('grid gap-2', className)}
        role="radiogroup"
        onKeyDown={handleKeyDown}
        {...props}
      >
        {React.Children.map(children, (child) => {
          if (React.isValidElement(child) && child.type === RadioGroupItem) {
            const isChecked = child.props.value === value;
            const isFirstItem = child.props.value === itemValues[0];
            return React.cloneElement(child, {
              checked: isChecked,
              onCheckedChange: () => onValueChange?.(child.props.value),
              disabled: disabled || child.props.disabled,
              // Only the checked item (or first if none checked) gets tabIndex 0
              tabIndex: isChecked ? 0 : (value === undefined && isFirstItem ? 0 : -1),
            } as any);
          }
          return child;
        })}
      </div>
    );
  },
);
RadioGroup.displayName = 'RadioGroup';

/**
 * RadioGroupItemProps - Propriétés du composant RadioGroupItem
 *
 * @interface RadioGroupItemProps
 * @extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type'>
 */
export interface RadioGroupItemProps
  extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type'> {
  /**
   * Valeur unique du bouton radio (doit être unique dans le groupe)
   *
   * @example
   * ```tsx
   * <RadioGroupItem value="option1" />
   * ```
   */
  value: string;

  /**
   * État checked du bouton radio (géré automatiquement par RadioGroup)
   * @internal
   */
  checked?: boolean;

  /**
   * Fonction appelée lors du clic (gérée automatiquement par RadioGroup)
   * @internal
   */
  onCheckedChange?: () => void;

  /**
   * Tab index for keyboard navigation (managed by RadioGroup)
   * @internal
   */
  tabIndex?: number;
}

/**
 * RadioGroupItem - Bouton radio individuel
 *
 * Bouton radio à utiliser à l'intérieur d'un RadioGroup.
 * L'état checked est géré automatiquement par le RadioGroup parent.
 *
 * @component
 */

const RadioGroupItem = React.forwardRef<HTMLInputElement, RadioGroupItemProps>(
  ({ className, value, checked, onCheckedChange, disabled, tabIndex, ...props }, ref) => {
    return (
      <label
        role="radio"
        aria-checked={!!checked}
        className={cn(
          'aspect-square h-4 w-4 rounded-full border border-border text-muted-foreground',
          'ring-offset-background focus-within:outline-none focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2',
          'disabled:cursor-not-allowed disabled:opacity-50',
          'cursor-pointer relative inline-flex items-center justify-center',
          checked && 'border-primary text-primary',
          className,
        )}
      >
        <input
          ref={ref}
          type="radio"
          value={value}
          checked={checked}
          onChange={onCheckedChange}
          disabled={disabled}
          tabIndex={tabIndex}
          className="sr-only"
          {...props}
        />
        {checked && (
          <Circle className="h-2.5 w-2.5 fill-current text-current" />
        )}
      </label>
    );
  },
);
RadioGroupItem.displayName = 'RadioGroupItem';

export { RadioGroup, RadioGroupItem };
