'use client';

import {
  ChangeEventHandler,
  ReactNode,
  createContext,
  useContext,
} from 'react';
import { cn } from '@/lib/helper';

export interface RadioOption {
  label: string;
  value: string;
}

// DaisyUI Radio Colors
export type RadioColor =
  | 'neutral'
  | 'primary'
  | 'secondary'
  | 'accent'
  | 'success'
  | 'warning'
  | 'info'
  | 'error';

// DaisyUI Radio Sizes
export type RadioSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';

// Context untuk RadioGroup
interface RadioGroupContextValue {
  name: string;
  value?: string;
  color?: RadioColor;
  size?: RadioSize;
  disabled?: boolean;
  onChange?: ChangeEventHandler<HTMLInputElement>;
  onBlur?: (e: React.FocusEvent<HTMLInputElement>) => void;
}

const RadioGroupContext = createContext<RadioGroupContextValue | undefined>(
  undefined
);

const useRadioGroup = () => {
  const context = useContext(RadioGroupContext);
  if (!context) {
    throw new Error('RadioGroupItem must be used within RadioGroup');
  }
  return context;
};

// RadioGroup Component
export interface RadioGroupProps {
  label?: string;
  bottomLabel?: string;
  name: string;
  value?: string;
  options?: RadioOption[];
  color?: RadioColor;
  size?: RadioSize;
  className?: {
    wrapper?: string;
    label?: string;
    radioWrapper?: string;
  };
  isError?: boolean;
  errorMessage?: string;
  required?: boolean;
  disabled?: boolean;
  onChange?: ChangeEventHandler<HTMLInputElement>;
  onBlur?: (e: React.FocusEvent<HTMLInputElement>) => void;
  children?: ReactNode;
}

export const RadioGroup = ({
  label,
  bottomLabel,
  name,
  value,
  options,
  color = 'primary',
  size = 'md',
  className,
  isError,
  errorMessage,
  required = false,
  disabled = false,
  onChange,
  onBlur,
  children,
}: RadioGroupProps) => {
  const contextValue: RadioGroupContextValue = {
    name,
    value,
    color,
    size,
    disabled,
    onChange,
    onBlur,
  };

  return (
    <RadioGroupContext.Provider value={contextValue}>
      <div className={cn('w-full flex flex-col gap-2', className?.wrapper)}>
        {/* Label atas */}
        {label && (
          <label
            className={cn(
              'w-full text-sm font-normal leading-5',
              { 'text-error': isError },
              className?.label
            )}
          >
            {label}
            {required && (
              <span className='text-error ml-1' title='required'>
                *
              </span>
            )}
          </label>
        )}

        {/* Daftar opsi radio */}
        <div
          className={cn(
            'flex flex-row flex-wrap gap-4 items-center',
            className?.radioWrapper
          )}
        >
          {/* Jika options diberikan, render otomatis */}
          {options &&
            options.map((option) => (
              <RadioGroupItem
                key={option.value}
                value={option.value}
                label={option.label}
              />
            ))}

          {/* Atau gunakan children untuk custom rendering */}
          {children}
        </div>

        {/* Label bawah */}
        {!isError && bottomLabel && (
          <p className='mt-1.5 text-xs opacity-60'>{bottomLabel}</p>
        )}

        {/* Pesan error */}
        {isError && errorMessage && (
          <p className='mt-1.5 text-xs text-error'>{errorMessage}</p>
        )}
      </div>
    </RadioGroupContext.Provider>
  );
};

// RadioGroupItem Component
export interface RadioGroupItemProps {
  value: string;
  label?: string;
  className?: string;
  disabled?: boolean;
  color?: RadioColor;
  size?: RadioSize;
}

export const RadioGroupItem = ({
  value,
  label,
  className,
  disabled: itemDisabled,
  color: itemColor,
  size: itemSize,
}: RadioGroupItemProps) => {
  const {
    name,
    value: groupValue,
    color: groupColor,
    size: groupSize,
    disabled: groupDisabled,
    onChange,
    onBlur,
  } = useRadioGroup();

  const isDisabled = itemDisabled ?? groupDisabled;
  const radioColor = itemColor ?? groupColor;
  const radioSize = itemSize ?? groupSize;

  return (
    <label
      className={cn(
        'flex flex-row items-center gap-2 cursor-pointer',
        isDisabled && 'opacity-60 cursor-not-allowed',
        className
      )}
    >
      <input
        type='radio'
        name={name}
        value={value}
        checked={groupValue === value}
        onChange={onChange}
        onBlur={onBlur}
        disabled={isDisabled}
        className={cn('radio', `radio-${radioColor}`, `radio-${radioSize}`)}
      />
      {label && <span className='text-sm'>{label}</span>}
    </label>
  );
};
