/**
 * FormField Component
 * 
 * A reusable form field component that handles the common pattern of:
 * - Label
 * - Controller (react-hook-form)
 * - Input/Select/Textarea
 * - Error handling
 * 
 * This component reduces code duplication across all form components.
 */

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

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

export interface FormFieldProps<
  TFieldValues extends FieldValues = FieldValues,
  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
> {
  // Form control
  control: Control<TFieldValues>;
  name: TName;
  
  // Field configuration
  label?: string;
  placeholder?: string;
  type?: 'text' | 'email' | 'password' | 'number' | 'tel' | 'url';
  required?: boolean;
  
  // Field type
  fieldType?: 'input' | 'textarea' | 'select';
  
  // Styling
  className?: string;
  labelClassName?: string;
  inputClassName?: string;
  errorClassName?: string;
  
  // Validation
  validation?: {
    required?: boolean | string;
    minLength?: { value: number; message: string };
    maxLength?: { value: number; message: string };
    pattern?: { value: RegExp; message: string };
  };
  
  // Additional props
  disabled?: boolean;
  readOnly?: boolean;
  autoComplete?: string;
  size?: 'sm' | 'md' | 'lg';
  
  // Custom render function
  render?: (props: {
    field: any;
    fieldState: { error?: FieldError };
  }) => React.ReactElement;
}

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

export function FormField<
  TFieldValues extends FieldValues = FieldValues,
  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
>({
  control,
  name,
  label,
  placeholder,
  type = 'text',
  required = false,
  fieldType = 'input',
  className = '',
  labelClassName = '',
  inputClassName = '',
  errorClassName = '',
  validation,
  disabled = false,
  readOnly = false,
  autoComplete,
  size = 'md',
  render,
}: FormFieldProps<TFieldValues, TName>) {
  
  // =============================================================================
  // HELPER FUNCTIONS
  // =============================================================================
  
  const getInputSize = (size: 'sm' | 'md' | 'lg') => {
    switch (size) {
      case 'sm':
        return 'h-8 text-sm';
      case 'lg':
        return 'h-12 text-base';
      default:
        return 'h-10 text-sm';
    }
  };
  
  const getTextareaSize = (size: 'sm' | 'md' | 'lg') => {
    switch (size) {
      case 'sm':
        return 'min-h-[80px] text-sm';
      case 'lg':
        return 'min-h-[120px] text-base';
      default:
        return 'min-h-[100px] text-sm';
    }
  };
  
  // =============================================================================
  // RENDER FUNCTIONS
  // =============================================================================
  
  const renderInput = (field: any, fieldState: { error?: FieldError }) => {
    const inputProps = {
      ...field,
      type,
      placeholder,
      disabled,
      readOnly,
      autoComplete,
      className: cn(
        'w-full transition-colors',
        getInputSize(size),
        fieldState.error && 'border-destructive focus:border-destructive',
        inputClassName
      ),
    };
    
    return <Input {...inputProps} />;
  };
  
  const renderTextarea = (field: any, fieldState: { error?: FieldError }) => {
    const textareaProps = {
      ...field,
      placeholder,
      disabled,
      readOnly,
      autoComplete,
      className: cn(
        'w-full resize-none transition-colors',
        getTextareaSize(size),
        fieldState.error && 'border-destructive focus:border-destructive',
        inputClassName
      ),
    };
    
    return <Textarea {...textareaProps} />;
  };
  
  const renderField = (field: any, fieldState: { error?: FieldError }) => {
    if (render) {
      return render({ field, fieldState });
    }
    
    switch (fieldType) {
      case 'textarea':
        return renderTextarea(field, fieldState);
      case 'select':
        // Select component will be handled by FormSelect component
        return renderInput(field, fieldState);
      default:
        return renderInput(field, fieldState);
    }
  };
  
  // =============================================================================
  // MAIN RENDER
  // =============================================================================
  
  return (
    <div className={cn('space-y-2', className)}>
      {/* Label */}
      {label && (
        <Label 
          htmlFor={name} 
          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,
          minLength: validation?.minLength,
          maxLength: validation?.maxLength,
          pattern: validation?.pattern,
        }}
        render={({ field, fieldState }) => (
          <div className="space-y-1">
            {renderField(field, fieldState)}
            
            {/* Error Message */}
            {fieldState.error && (
              <p className={cn(
                'text-sm text-destructive',
                errorClassName
              )}>
                {fieldState.error.message}
              </p>
            )}
          </div>
        )}
      />
    </div>
  );
}

export default FormField; 