/**
 * BFUI Component: RadioGroup.tsx
 *
 * Purpose:
 *   Provides a customizable radio group component with optional card style,
 *   supporting accessibility and theming via Chakra UI.
 *
 * AI Agent / Developer Interaction:
 *   - Agents can use this component to render radio options with labels, icons,
 *     and descriptions.
 *   - Developers should ensure props are correctly typed and handle state changes.
 *
 * Connected Systems:
 *   - Chakra UI for UI primitives and theming.
 *   - FormGroup component for consistent form layout and validation.
 *
 * TODO:
 *   - Add unit and integration tests for card style and accessibility.
 *   - Improve type safety for onChange and event handlers.
 *   - Optimize rendering performance for large option sets.
 *   - Add CLI wrappers for form generation automation if applicable.
 */

import React from 'react';
import {
  Radio,
  Stack,
  FormControl,
  FormLabel,
  FormErrorMessage,
  FormHelperText,
  useColorModeValue,
  useRadioGroup,
  Box,
} from '@chakra-ui/react';
import type { UseRadioGroupProps } from '@chakra-ui/react';
import FormGroup from './FormGroup.js';
import type { FormGroupProps } from './FormGroup.js';

export interface RadioOption {
  /**
   * Value of the radio option
   */
  value: string;

  /**
   * Label of the radio option
   */
  label: string;

  /**
   * Whether the radio option is disabled
   */
  isDisabled?: boolean;

  /**
   * Description text for the option
   */
  description?: string;

  /**
   * Icon for the option
   */
  icon?: React.ReactElement;
}

export interface RadioGroupProps {
  /**
   * Label for the radio group
   */
  label?: string;

  /**
   * Error message to display
   */
  error?: string;

  /**
   * Helper text to display below the radio group
   */
  helperText?: string;

  /**
   * Whether the radio group is required
   */
  isRequired?: boolean;

  /**
   * Options for the radio group
   */
  options: RadioOption[];

  /**
   * Direction of the radio group
   * @default 'vertical'
   */
  direction?: 'horizontal' | 'vertical';

  /**
   * Spacing between radio options
   * @default 4
   */
  spacing?: number;

  /**
   * Size of the radio buttons
   * @default 'md'
   */
  size?: 'sm' | 'md' | 'lg';

  /**
   * Whether to use a card style for options
   */
  isCard?: boolean;

  /**
   * Color scheme for the radio buttons
   */
  colorScheme?: string;

  /**
   * Props to pass to the form group
   */
  formGroupProps?: Omit<FormGroupProps, 'label' | 'isRequired' | 'isInvalid' | 'errorMessage' | 'helperText'>;

  /**
   * Value of the selected radio option
   */
  value?: string;

  /**
   * Default value of the radio group
   */
  defaultValue?: string;

  /**
   * Change handler for the radio group
   */
  onChange?: (value: string) => void;

  /**
   * Name for the radio group
   */
  name?: string;
}

/**
 * Custom radio card component
 */
const RadioCard: React.FC<{
  option: RadioOption;
  isChecked: boolean;
  isDisabled?: boolean;
  onClick: () => void;
}> = ({ option, isChecked, isDisabled = false, onClick }) => {
  const bg = useColorModeValue('white', 'gray.800');
  const borderColor = useColorModeValue('gray.200', 'gray.600');
  const checkedBg = useColorModeValue('blue.50', 'blue.900');
  const checkedBorder = 'blue.500';

  // Manage hover style conditionally without passing undefined
  const hoverProps =
    !isDisabled && !isChecked
      ? {
          _hover: {
            bg: useColorModeValue('gray.50', 'gray.700'),
            borderColor: useColorModeValue('gray.300', 'gray.500'),
          },
        }
      : {};

  return (
    <Box
      as="label"
      cursor={isDisabled ? 'not-allowed' : 'pointer'}
      borderWidth="1px"
      borderRadius="md"
      borderColor={isChecked ? checkedBorder : borderColor}
      bg={isChecked ? checkedBg : bg}
      px={5}
      py={3}
      onClick={!isDisabled ? onClick : undefined}
      opacity={isDisabled ? 0.6 : 1}
      {...hoverProps}
    >
      <Stack direction="row" align="center" spacing={4}>
        {option.icon && <Box color={isChecked ? 'blue.500' : 'gray.400'}>{option.icon}</Box>}
        <Stack spacing={0}>
          <Box fontWeight="semibold">{option.label}</Box>
          {option.description && (
            <Box fontSize="sm" color={useColorModeValue('gray.600', 'gray.400')}>
              {option.description}
            </Box>
          )}
        </Stack>
      </Stack>
    </Box>
  );
};

/**
 * RadioGroup component using Chakra UI's RadioGroup with BFUI theme customizations
 */
export const RadioGroup: React.FC<RadioGroupProps> = ({
  label,
  error,
  helperText,
  isRequired = false,
  options,
  direction = 'vertical',
  spacing = 4,
  size = 'md',
  isCard = false,
  colorScheme = 'blue',
  onChange,
  value,
  defaultValue,
  name,
  formGroupProps,
  ...rest
}) => {
  // Build hook props without undefined values
  const radioHookProps: UseRadioGroupProps = { name: name ?? '' };
  if (onChange) radioHookProps.onChange = onChange;
  if (value !== undefined) radioHookProps.value = value;
  if (defaultValue !== undefined) radioHookProps.defaultValue = defaultValue;
  const { getRootProps, getRadioProps } = useRadioGroup(radioHookProps);

  // Build FormGroup props conditionally to avoid undefined
  const groupProps = {
    ...(label !== undefined ? { label } : {}),
    isRequired,
    ...(error !== undefined ? { isInvalid: true, errorMessage: error } : {}),
    ...(helperText !== undefined ? { helperText } : {}),
    ...formGroupProps,
  };

  return (
    <FormGroup {...groupProps}>
      <FormControl>
        {label && <FormLabel>{label}</FormLabel>}
        <Stack
          {...getRootProps()}
          direction={direction === 'horizontal' ? 'row' : 'column'}
          spacing={spacing}
          {...rest}
        >
          {options.map(option => {
            const radioProps = getRadioProps({ value: option.value });
            const isChecked = radioProps.isChecked;

            if (isCard) {
              return (
                <RadioCard
                  key={option.value}
                  option={option}
                  isChecked={isChecked}
                  isDisabled={!!option.isDisabled}
                  onClick={() => {
                    if (!option.isDisabled && onChange) {
                      onChange(option.value);
                    }
                  }}
                />
              );
            }

            return (
              <Radio
                key={option.value}
                {...(radioProps as any)}
                size={size}
                colorScheme={colorScheme}
                isDisabled={!!option.isDisabled}
              >
                <Stack direction="row" align="center" spacing={2}>
                  {option.icon}
                  <Stack spacing={0}>
                    <Box>{option.label}</Box>
                    {option.description && (
                      <Box fontSize="sm" color={useColorModeValue('gray.600', 'gray.400')}>
                        {option.description}
                      </Box>
                    )}
                  </Stack>
                </Stack>
              </Radio>
            );
          })}
        </Stack>
        {error ? (
          <FormErrorMessage>{error}</FormErrorMessage>
        ) : helperText ? (
          <FormHelperText>{helperText}</FormHelperText>
        ) : null}
      </FormControl>
    </FormGroup>
  );
};

export default RadioGroup;
