import React from 'react';
import { Label } from '../ui/label';
import { Input } from '../ui/input';
import { Textarea } from '../ui/textarea';
import { Checkbox } from '../ui/checkbox';
import { RadioGroup, RadioGroupItem } from '../ui/radio-group';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '../ui/select';

/**
 * DynamicFormField - Renders form fields based on schema configuration
 *
 * Supports field types:
 * - text, email, phone, password: Input fields
 * - date: Date picker input
 * - textarea: Multi-line text input
 * - checkbox: Single checkbox
 * - radio: Radio button group
 * - dropdown: Select dropdown
 * - multiselect: Checkbox group for multiple selections
 * - address_group: Group of address-related fields
 * - file_upload: File upload input
 */
const DynamicFormField = ({
  field,
  value,
  onChange,
  errors = [],
  formData = {},
}) => {
  const {
    id,
    type,
    label,
    required,
    placeholder,
    options = [],
    rows = 4,
    validation = {},
  } = field;

  const hasError = errors.length > 0;
  const errorMessage = errors[0];

  const formatPhoneNumber = (rawValue) => {
    const digits = String(rawValue || '').replace(/\D/g, '').slice(0, 10);
    if (digits.length <= 3) return digits;
    if (digits.length <= 6) {
      return `(${digits.slice(0, 3)}) ${digits.slice(3)}`;
    }
    return `(${digits.slice(0, 3)}) ${digits.slice(3, 6)}-${digits.slice(6)}`;
  };

  // Common input className
  const inputClassName = `h-14 rounded-xl border-2 ${
    hasError
      ? 'border-red-500 focus:border-red-500'
      : 'border-[var(--neutral-800)] focus:border-brand-purple'
  }`;

  // Handle change for different field types
  const handleInputChange = (e) => {
    const { value: newValue, type: inputType, checked } = e.target;
    if (inputType === 'checkbox') {
      onChange(id, checked);
      return;
    }
    if (type === 'phone') {
      onChange(id, formatPhoneNumber(newValue));
      return;
    } else {
      onChange(id, newValue);
    }
  };

  const handleSelectChange = (newValue) => {
    onChange(id, newValue);
  };

  const handleCheckboxChange = (checked) => {
    onChange(id, checked);
  };

  const handleMultiselectChange = (optionValue) => {
    const currentValues = Array.isArray(value) ? value : [];
    const newValues = currentValues.includes(optionValue)
      ? currentValues.filter((v) => v !== optionValue)
      : [...currentValues, optionValue];
    onChange(id, newValues);
  };

  // Render error message
  const renderError = () => {
    if (!hasError) return null;
    return (
      <p className="text-sm text-red-500 mt-1">{errorMessage}</p>
    );
  };

  // Render label
  const renderLabel = () => (
    <Label htmlFor={id} className={hasError ? 'text-red-500' : ''}>
      {label} {required && '*'}
    </Label>
  );

  // Render based on field type
  switch (type) {
    case 'text':
    case 'email':
    case 'phone':
      return (
        <div className="space-y-2">
          {renderLabel()}
          <Input
            id={id}
            name={id}
            type={type === 'phone' ? 'tel' : type}
            required={required}
            value={value || ''}
            onChange={handleInputChange}
            placeholder={placeholder}
            inputMode={type === 'phone' ? 'numeric' : undefined}
            maxLength={type === 'phone' ? 14 : undefined}
            className={inputClassName}
            data-testid={`field-${id}`}
          />
          {renderError()}
        </div>
      );

    case 'password':
      return (
        <div className="space-y-2">
          {renderLabel()}
          <Input
            id={id}
            name={id}
            type="password"
            required={required}
            value={value || ''}
            onChange={handleInputChange}
            placeholder={placeholder}
            minLength={validation.minLength}
            className={inputClassName}
            data-testid={`field-${id}`}
          />
          {renderError()}
        </div>
      );

    case 'date':
      return (
        <div className="space-y-2">
          {renderLabel()}
          <Input
            id={id}
            name={id}
            type="date"
            required={required}
            value={value || ''}
            onChange={handleInputChange}
            className={inputClassName}
            data-testid={`field-${id}`}
          />
          {renderError()}
        </div>
      );

    case 'textarea':
      return (
        <div className="space-y-2">
          {renderLabel()}
          <Textarea
            id={id}
            name={id}
            required={required}
            value={value || ''}
            onChange={handleInputChange}
            placeholder={placeholder}
            rows={rows}
            className={`rounded-xl border-2 ${
              hasError
                ? 'border-red-500 focus:border-red-500'
                : 'border-[var(--neutral-800)] focus:border-brand-purple'
            }`}
            data-testid={`field-${id}`}
          />
          {renderError()}
        </div>
      );

    case 'checkbox':
      return (
        <div className="flex items-center space-x-2">
          <Checkbox
            id={id}
            name={id}
            checked={value || false}
            onCheckedChange={handleCheckboxChange}
            data-testid={`field-${id}`}
          />
          <Label
            htmlFor={id}
            className={`text-base cursor-pointer ${hasError ? 'text-red-500' : ''}`}
          >
            {label} {required && '*'}
          </Label>
          {renderError()}
        </div>
      );

    case 'radio':
      return (
        <div className="space-y-2">
          {renderLabel()}
          <RadioGroup
            value={value || ''}
            onValueChange={handleSelectChange}
            className="space-y-2"
          >
            {options.map((option) => (
              <div key={option.value} className="flex items-center space-x-2">
                <RadioGroupItem
                  value={option.value}
                  id={`${id}-${option.value}`}
                  data-testid={`field-${id}-${option.value}`}
                />
                <Label
                  htmlFor={`${id}-${option.value}`}
                  className="text-base cursor-pointer"
                >
                  {option.label}
                </Label>
              </div>
            ))}
          </RadioGroup>
          {renderError()}
        </div>
      );

    case 'dropdown':
      return (
        <div className="space-y-2">
          {renderLabel()}
          <Select value={value || ''} onValueChange={handleSelectChange}>
            <SelectTrigger
              className={`h-14 rounded-xl border-2 ${
                hasError
                  ? 'border-red-500'
                  : 'border-[var(--neutral-800)] focus:border-brand-purple'
              }`}
              data-testid={`field-${id}`}
            >
              <SelectValue placeholder={placeholder || 'Select an option'} />
            </SelectTrigger>
            <SelectContent>
              {options.map((option) => (
                <SelectItem key={option.value} value={option.value}>
                  {option.label}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
          {renderError()}
        </div>
      );

    case 'multiselect':
      const selectedValues = Array.isArray(value) ? value : [];
      return (
        <div className="space-y-2">
          {renderLabel()}
          <div className="space-y-3">
            {options.map((option) => (
              <div key={option.value} className="flex items-center space-x-2">
                <Checkbox
                  id={`${id}-${option.value}`}
                  checked={selectedValues.includes(option.value)}
                  onCheckedChange={() => handleMultiselectChange(option.value)}
                  data-testid={`field-${id}-${option.value}`}
                />
                <Label
                  htmlFor={`${id}-${option.value}`}
                  className="text-base cursor-pointer"
                >
                  {option.label}
                </Label>
              </div>
            ))}
          </div>
          {renderError()}
        </div>
      );

    case 'address_group':
      // Address group renders multiple related fields
      return (
        <div className="space-y-4">
          {renderLabel()}
          <div className="space-y-4">
            <Input
              id={`${id}_address`}
              name={`${id}_address`}
              placeholder="Street Address"
              value={formData[`${id}_address`] || ''}
              onChange={(e) => onChange(`${id}_address`, e.target.value)}
              className={inputClassName}
              required={required}
            />
            <div className="grid md:grid-cols-3 gap-4">
              <Input
                id={`${id}_city`}
                name={`${id}_city`}
                placeholder="City"
                value={formData[`${id}_city`] || ''}
                onChange={(e) => onChange(`${id}_city`, e.target.value)}
                className={inputClassName}
                required={required}
              />
              <Input
                id={`${id}_state`}
                name={`${id}_state`}
                placeholder="State"
                value={formData[`${id}_state`] || ''}
                onChange={(e) => onChange(`${id}_state`, e.target.value)}
                className={inputClassName}
                required={required}
              />
              <Input
                id={`${id}_zipcode`}
                name={`${id}_zipcode`}
                placeholder="Zipcode"
                value={formData[`${id}_zipcode`] || ''}
                onChange={(e) => onChange(`${id}_zipcode`, e.target.value)}
                className={inputClassName}
                required={required}
              />
            </div>
          </div>
          {renderError()}
        </div>
      );

    case 'file_upload':
      return (
        <div className="space-y-2">
          {renderLabel()}
          <Input
            id={id}
            name={id}
            type="file"
            accept={field.allowed_types?.join(',')}
            onChange={(e) => {
              const file = e.target.files?.[0];
              onChange(id, file);
            }}
            className={`h-14 rounded-xl border-2 pt-3 ${
              hasError
                ? 'border-red-500'
                : 'border-[var(--neutral-800)] focus:border-brand-purple'
            }`}
            data-testid={`field-${id}`}
          />
          {field.max_size_mb && (
            <p className="text-sm text-muted-foreground">
              Max file size: {field.max_size_mb}MB
            </p>
          )}
          {renderError()}
        </div>
      );

    default:
      console.warn(`Unknown field type: ${type}`);
      return (
        <div className="space-y-2">
          {renderLabel()}
          <Input
            id={id}
            name={id}
            value={value || ''}
            onChange={handleInputChange}
            placeholder={placeholder}
            className={inputClassName}
            data-testid={`field-${id}`}
          />
          {renderError()}
        </div>
      );
  }
};

/**
 * Get width class based on field width configuration
 */
export const getWidthClass = (width) => {
  switch (width) {
    case 'half':
      return 'md:col-span-1';
    case 'third':
      return 'md:col-span-1';
    case 'two-thirds':
      return 'md:col-span-2';
    case 'full':
    default:
      return 'md:col-span-2';
  }
};

/**
 * Get grid columns class based on field widths in a row
 */
export const getGridClass = (fields) => {
  const hasThird = fields.some((f) => f.width === 'third');
  if (hasThird) {
    return 'grid md:grid-cols-3 gap-4';
  }
  return 'grid md:grid-cols-2 gap-4';
};

export default DynamicFormField;
