/**
 * FormCheckbox Component
 * 
 * A reusable checkbox component that handles:
 * - Single checkbox
 * - Checkbox groups
 * - Label
 * - Controller (react-hook-form)
 * - Error handling
 * 
 * This component reduces code duplication for checkbox fields across forms.
 */

import React from 'react';
import { Control, Controller, FieldError, FieldPath, FieldValues } from 'react-hook-form';
import { Label } from '@/components/ui/label';
import { Checkbox } from '@/components/ui/checkbox';
import { cn } from '@/lib/utils';

// =============================================================================
// TYPES
// =============================================================================

export interface CheckboxOption {
  value: string | number;
  label: string;
  disabled?: boolean;
}

export interface FormCheckboxProps<
  TFieldValues extends FieldValues = FieldValues,
  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
> {
  // Form control
  control: Control<TFieldValues>;
  name: TName;
  
  // Field configuration
  label?: string;
  required?: boolean;
  
  // Checkbox configuration
  single?: boolean; // Single checkbox vs checkbox group
  options?: CheckboxOption[]; // For checkbox groups
  
  // Styling
  className?: string;
  labelClassName?: string;
  checkboxClassName?: string;
  errorClassName?: string;
  groupClassName?: string;
  
  // Layout
  layout?: 'horizontal' | 'vertical';
  columns?: number; // For grid layout
  
  // Validation
  validation?: {
    required?: boolean | string;
  };
  
  // Additional props
  disabled?: boolean;
  size?: 'sm' | 'md' | 'lg';
  
  // Custom render functions
  renderOption?: (option: CheckboxOption, checked: boolean, onChange: (checked: boolean) => void) => React.ReactElement;
}

// =============================================================================
// COMPONENT
// =============================================================================

export function FormCheckbox<
  TFieldValues extends FieldValues = FieldValues,
  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
>({
  control,
  name,
  label,
  required = false,
  single = false,
  options = [],
  className = '',
  labelClassName = '',
  checkboxClassName = '',
  errorClassName = '',
  groupClassName = '',
  layout = 'horizontal',
  columns = 1,
  validation,
  disabled = false,
  size = 'md',
  renderOption,
}: FormCheckboxProps<TFieldValues, TName>) {
  
  // =============================================================================
  // HELPER FUNCTIONS
  // =============================================================================
  
  const getCheckboxSize = (size: 'sm' | 'md' | 'lg') => {
    switch (size) {
      case 'sm':
        return 'h-4 w-4';
      case 'lg':
        return 'h-6 w-6';
      default:
        return 'h-5 w-5';
    }
  };
  
  const getGroupLayout = () => {
    if (layout === 'vertical') {
      return 'flex flex-col gap-2';
    }
    
    if (columns > 1) {
      return `grid grid-cols-${columns} gap-2`;
    }
    
    return 'flex flex-wrap gap-4';
  };
  
  // =============================================================================
  // RENDER FUNCTIONS
  // =============================================================================
  
  const renderSingleCheckbox = (field: any, fieldState: { error?: FieldError }) => (
    <div className={cn('flex items-center space-x-2', checkboxClassName)}>
      <Checkbox
        id={name}
        checked={field.value}
        onCheckedChange={field.onChange}
        disabled={disabled}
        className={getCheckboxSize(size)}
      />
      <Label
        htmlFor={name}
        className={cn(
          'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
          labelClassName
        )}
      >
        {label}
      </Label>
    </div>
  );
  
  const renderCheckboxGroup = (field: any, fieldState: { error?: FieldError }) => {
    const selectedValues = field.value || [];
    
    const handleOptionChange = (optionValue: string | number, checked: boolean) => {
      const newValues = checked
        ? [...selectedValues, optionValue]
        : selectedValues.filter((value: any) => value !== optionValue);
      field.onChange(newValues);
    };
    
    const renderDefaultOption = (option: CheckboxOption) => {
      const checked = selectedValues.includes(option.value);
      
      if (renderOption) {
        return renderOption(option, checked, (checked) => handleOptionChange(option.value, checked));
      }
      
      return (
        <div key={option.value} className="flex items-center space-x-2">
          <Checkbox
            id={`${name}-${option.value}`}
            checked={checked}
            onCheckedChange={(checked) => handleOptionChange(option.value, checked as boolean)}
            disabled={disabled || option.disabled}
            className={getCheckboxSize(size)}
          />
          <Label
            htmlFor={`${name}-${option.value}`}
            className={cn(
              'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
              labelClassName
            )}
          >
            {option.label}
          </Label>
        </div>
      );
    };
    
    return (
      <div className={cn(getGroupLayout(), groupClassName)}>
        {options.map(renderDefaultOption)}
      </div>
    );
  };
  
  // =============================================================================
  // MAIN RENDER
  // =============================================================================
  
  return (
    <div className={cn('space-y-2', className)}>
      {/* Group Label */}
      {label && !single && (
        <Label 
          className={cn(
            'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
            required && 'after:content-["*"] after:ml-0.5 after:text-destructive',
            labelClassName
          )}
        >
          {label}
        </Label>
      )}
      
      {/* Controller */}
      <Controller
        control={control}
        name={name}
        rules={{
          required: validation?.required || required,
        }}
        render={({ field, fieldState }) => (
          <div className="space-y-1">
            {single ? 
              renderSingleCheckbox(field, fieldState) : 
              renderCheckboxGroup(field, fieldState)
            }
            
            {/* Error Message */}
            {fieldState.error && (
              <p className={cn(
                'text-sm text-destructive',
                errorClassName
              )}>
                {fieldState.error.message}
              </p>
            )}
          </div>
        )}
      />
    </div>
  );
}

export default FormCheckbox; 