import React from 'react';
import { useForm, Controller, FieldValues, Path } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { Loader2, AlertCircle, CheckCircle2 } from 'lucide-react';
import { z } from 'zod';
import { cn } from '@/lib/utils';
import PrimaryButton from '@/components/PrimaryButton';
import PrimaryButton_v2 from '../PrimaryButton_v2';

// Types
type FieldType = 'text' | 'email' | 'password' | 'number' | 'date' | 'tel' | 'url' | 'select' | 'textarea' | 'checkbox' | 'custom';

interface SelectOption {
  value: string | number;
  label: string;
}

interface BaseField<T extends FieldValues = FieldValues> {
  name: Path<T>;
  label: string;
  type?: FieldType;
  placeholder?: string;
  required?: boolean;
  help?: string;
  fullWidth?: boolean;
  rows?: number;
  options?: SelectOption[];
  value?: any;
  onChange?: (value: any) => void;
  renderCustom?: (props: {
    value: any;
    onChange: (value: any) => void;
    error?: string;
  }) => React.ReactNode;
}

interface SectionField {
  type: 'section';
  title: string;
  description?: string;
  name?: string;
}

type Field<T extends FieldValues = FieldValues> = BaseField<T> | SectionField;

interface SmartFormProps<T extends FieldValues = FieldValues> {
  schema: z.ZodSchema<T>;
  defaultValues?: Partial<T>;
  onSubmit: (data: T) => void | Promise<void>;
  fields: Field<T>[];
  loading?: boolean;
  submitLabel?: string;
  cancelLabel?: string;
  onCancel?: () => void;
}

function FormDynamique<T extends FieldValues = FieldValues>({ 
  schema, 
  defaultValues, 
  onSubmit, 
  fields, 
  loading = false, 
  submitLabel = "Enregistrer",
  cancelLabel = "Annuler",
  onCancel 
}: SmartFormProps<T>) {
  const {
    register,
    handleSubmit,
    formState: { errors, isDirty, isValid },
    watch,
    control
  } = useForm<T>({
    resolver: zodResolver(schema),
    defaultValues: defaultValues as any,
    mode: "onChange"
  });

  return (
    <form onSubmit={handleSubmit(onSubmit)} className="space-y-6">
      <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
        {fields.map((field, index) => {
          if (field.type === 'section') {
            return (
              <div key={field.title || index} className="col-span-1 md:col-span-2 pt-4 pb-2 border-b border-gray-200 dark:border-gray-800">
                <h3 className="text-lg font-medium text-gray-900 dark:text-white">{field.title}</h3>
                {field.description && <p className="text-sm text-gray-500 dark:text-gray-400">{field.description}</p>}
              </div>
            );
          }

          const baseField = field as BaseField<T>;
          const fieldName = baseField.name;
          const isError = errors[fieldName];
          const value = watch(fieldName);
          const isSuccess = !isError && value && baseField.type !== 'checkbox' && baseField.type !== 'textarea';

          // Si le field a value et onChange personnalisés (custom component)
          if (baseField.type === 'custom' && baseField.renderCustom) {
            return (
              <div 
                key={String(fieldName)} 
                className={cn(
                  "space-y-1.5 relative", 
                  baseField.fullWidth && "col-span-1 md:col-span-2"
                )}
              >
                <label className="flex items-center gap-1 text-sm font-medium text-gray-700 dark:text-gray-300">
                  {baseField.label}
                  {baseField.required && <span className="text-red-500">*</span>}
                </label>
                
                <Controller
                  name={fieldName}
                  control={control}
                  render={({ field: controllerField, fieldState }) => (
                    <>
                      {baseField.renderCustom!({
                        value: baseField.value !== undefined ? baseField.value : controllerField.value,
                        onChange: baseField.onChange || controllerField.onChange,
                        error: fieldState.error?.message
                      })}
                    </>
                  )}
                />

                {isError ? (
                  <p className="text-xs text-red-500 animate-in slide-in-from-top-1">
                    {(isError as any).message}
                  </p>
                ) : baseField.help ? (
                  <p className="text-xs text-gray-500 dark:text-gray-400">{baseField.help}</p>
                ) : null}
              </div>
            );
          }

          return (
            <div 
              key={String(fieldName)} 
              className={cn(
                "space-y-1.5 relative", 
                baseField.fullWidth && "col-span-1 md:col-span-2"
              )}
            >
              <label className="flex items-center gap-1 text-sm font-medium text-gray-700 dark:text-gray-300">
                {baseField.label}
                {baseField.required && <span className="text-red-500">*</span>}
              </label>
              
              <div className="relative">
                {baseField.type === 'select' ? (
                  <Controller
                    name={fieldName}
                    control={control}
                    render={({ field: controllerField }) => (
                      <select
                        {...controllerField}
                        value={baseField.value !== undefined ? baseField.value : controllerField.value}
                        onChange={(e) => {
                          const newValue = e.target.value;
                          if (baseField.onChange) {
                            baseField.onChange(newValue);
                          }
                          controllerField.onChange(newValue);
                        }}
                        className={cn(
                          "w-full px-3 py-2 bg-white dark:bg-gray-950 border rounded-xl text-sm shadow-sm transition-all focus:outline-none focus:ring-2",
                          isError 
                            ? "border-red-300 focus:border-red-500 focus:ring-red-200" 
                            : "border-gray-200 dark:border-gray-800 focus:border-[#941403] focus:ring-red-100/50"
                        )}
                      >
                        <option value="">Sélectionner...</option>
                        {baseField.options?.map(opt => (
                          <option key={opt.value} value={opt.value}>{opt.label}</option>
                        ))}
                      </select>
                    )}
                  />
                ) : baseField.type === 'textarea' ? (
                  <Controller
                    name={fieldName}
                    control={control}
                    render={({ field: controllerField }) => (
                      <textarea
                        {...controllerField}
                        value={baseField.value !== undefined ? baseField.value : controllerField.value}
                        onChange={(e) => {
                          const newValue = e.target.value;
                          if (baseField.onChange) {
                            baseField.onChange(newValue);
                          }
                          controllerField.onChange(newValue);
                        }}
                        rows={baseField.rows || 3}
                        className={cn(
                          "w-full px-3 py-2 bg-white dark:bg-gray-950 border rounded-xl text-sm shadow-sm transition-all focus:outline-none focus:ring-2 resize-none",
                          isError 
                            ? "border-red-300 focus:border-red-500 focus:ring-red-200" 
                            : "border-gray-200 dark:border-gray-800 focus:border-[#941403] focus:ring-red-100/50"
                        )}
                      />
                    )}
                  />
                ) : (
                  <Controller
                    name={fieldName}
                    control={control}
                    render={({ field: controllerField }) => (
                      <input
                        type={baseField.type || 'text'}
                        {...controllerField}
                        value={baseField.value !== undefined ? baseField.value : controllerField.value}
                        onChange={(e) => {
                          const newValue = e.target.value;
                          if (baseField.onChange) {
                            baseField.onChange(newValue);
                          }
                          controllerField.onChange(newValue);
                        }}
                        placeholder={baseField.placeholder}
                        className={cn(
                          "w-full px-3 py-2 bg-white dark:bg-gray-950 border rounded-xl text-sm shadow-sm transition-all focus:outline-none focus:ring-2",
                          isError 
                            ? "border-red-300 focus:border-red-500 focus:ring-red-200 pr-10" 
                            : isSuccess 
                              ? "border-green-300 focus:border-green-500 focus:ring-green-200 pr-10"
                              : "border-gray-200 dark:border-gray-800 focus:border-[#941403] focus:ring-red-100/50"
                        )}
                      />
                    )}
                  />
                )}

                {/* Icons validation indicators */}
                {baseField.type !== 'select' && baseField.type !== 'textarea' && (
                  <div className="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none">
                    {isError && <AlertCircle className="w-4 h-4 text-red-500" />}
                    {isSuccess && <CheckCircle2 className="w-4 h-4 text-green-500" />}
                  </div>
                )}
              </div>

              {/* Helper Text or Error Message */}
              {isError ? (
                <p className="text-xs text-red-500 animate-in slide-in-from-top-1">
                  {(isError as any).message}
                </p>
              ) : baseField.help ? (
                <p className="text-xs text-gray-500 dark:text-gray-400">{baseField.help}</p>
              ) : null}
            </div>
          );
        })}
      </div>

      <div className="flex items-center justify-end gap-3 pt-6 border-t border-gray-200 dark:border-gray-800">
        {onCancel && (
          <button
            type="button"
            onClick={onCancel}
            className="px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-xl transition-colors"
          >
            {cancelLabel}
          </button>
        )}
        <PrimaryButton_v2
          type="submit"
          loading={loading}
          disabled={!isDirty || !isValid}
        >
          {submitLabel}
        </PrimaryButton_v2>
      </div>
    </form>
  );
}

export default FormDynamique;