import React from 'react';
import { Control, Controller, FieldErrors, FieldValues, Path } from 'react-hook-form';
import { spacing } from '@/lib/spacing';

interface FormFieldProps<T extends FieldValues> {
  control: Control<T>;
  errors: FieldErrors<T>;
  name: Path<T>;
  label: string;
  description?: string | React.ReactNode;
  required?: boolean;
  component: React.ElementType;
  [key: string]: unknown;
}

const get = (obj: Record<string, unknown>, path: string) => {
  return path.split('.').reduce((acc, part) => acc && acc[part], obj);
};

const FormField = <T extends FieldValues>({
  control,
  errors,
  name,
  label,
  description,
  required,
  component: Component,
  ...props
}: FormFieldProps<T>) => {
  const error = get(errors, name);

  return (
    <div className={spacing.formField}>
      <label htmlFor={name} className="text-sm font-medium">
        {label}
        {required && <span className="text-destructive">*</span>}
      </label>
      {description && (
        <p id={`${name}-description`} className="text-xs text-muted-foreground">
          {description}
        </p>
      )}
      <Controller
        name={name}
        control={control}
        render={({ field }) => {
          const describedBy = [
            description ? `${name}-description` : undefined,
            error ? `${name}-error` : undefined,
          ]
            .filter(Boolean)
            .join(' ');

          return (
            <Component
              {...field}
              {...props}
              id={name}
              aria-invalid={!!error}
              aria-describedby={describedBy.length > 0 ? describedBy : undefined}
            />
          );
        }}
      />
      {error && (
        <p id={`${name}-error`} className="text-destructive text-xs mt-1">
          {String(error.message)}
        </p>
      )}
    </div>
  );
};

export default FormField;
