import React, { useState, useEffect } from 'react';
import { useForm } from 'react-hook-form';
import InputTextIcon from './InputTextIcon';
import FormRenderer from './FormRenderer';
import AddFieldModal from './AddFieldModal';
import FieldTypeSelector from './FieldTypeSelector';
import { DndProvider, useDrag, useDrop } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import {
  Edit2,
  Trash2,
  PlusCircle,
  Download,
  Upload,
  GripVertical,
  TextCursorInput,
  AtSign,
  Calendar,
  ChevronDown,
  Type,
  AlignLeft,
  Save,
  ChevronUp,
  Heading1,
  Heading2,
  Heading3,
  Heading4,
  Heading5,
  Heading6,
  Code,
  Eye,
  EyeOff,
  Phone,
  Radio,
  ToggleLeft,
  CheckSquare,
  FileUp,
  PenTool,
} from 'lucide-react';
import CheckBox from '@/components/Form/CheckBox';

const FIELD_TYPES_ICON = {
  text: { icon: TextCursorInput },
  email: { icon: AtSign },
  phone: { icon: Phone },
  date: { icon: Calendar },
  select: { icon: ChevronDown },
  radio: { icon: Radio },
  checkbox: { icon: CheckSquare },
  toggle: { icon: ToggleLeft },
  file: { icon: FileUp },
  signature: { icon: PenTool },
  textarea: { icon: Type },
  paragraph: { icon: AlignLeft },
  heading1: { icon: Heading1 },
  heading2: { icon: Heading2 },
  heading3: { icon: Heading3 },
  heading4: { icon: Heading4 },
  heading5: { icon: Heading5 },
  heading6: { icon: Heading6 },
};

// Type d'item pour le drag and drop
const ItemTypes = {
  FIELD: 'field',
};

// Composant pour un champ draggable
const DraggableFieldItem = ({
  field,
  index,
  moveField,
  editField,
  deleteField,
}) => {
  const ref = React.useRef(null);

  // Configuration du drag (ce qu'on peut déplacer)
  const [{ isDragging }, drag] = useDrag({
    type: ItemTypes.FIELD,
    item: { index },
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
    }),
  });

  // Configuration du drop (où on peut déposer)
  const [, drop] = useDrop({
    accept: ItemTypes.FIELD,
    hover: (item, monitor) => {
      if (!ref.current) {
        return;
      }
      const dragIndex = item.index;
      const hoverIndex = index;

      // Ne rien faire si on survole le même élément
      if (dragIndex === hoverIndex) {
        return;
      }

      // Déterminer la position de la souris par rapport à l'élément survolé
      const hoverBoundingRect = ref.current.getBoundingClientRect();
      const hoverMiddleY =
        (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
      const clientOffset = monitor.getClientOffset();
      const hoverClientY = clientOffset.y - hoverBoundingRect.top;

      // Ne pas remplacer si on n'a pas dépassé la moitié de l'élément
      if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
        return;
      }
      if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
        return;
      }

      // Effectuer le déplacement
      moveField(dragIndex, hoverIndex);

      // Mettre à jour l'index de l'élément déplacé
      item.index = hoverIndex;
    },
  });

  // Combiner drag et drop sur le même élément de référence
  drag(drop(ref));

  return (
    <div
      ref={ref}
      className={`flex items-center justify-between bg-gray-50 p-3 rounded border border-gray-200 ${
        isDragging ? 'opacity-50' : ''
      }`}
    >
      <div className="flex items-center gap-2">
        <div className="cursor-move text-gray-400 hover:text-gray-600">
          <GripVertical size={18} />
        </div>
        {FIELD_TYPES_ICON[field.type] &&
          React.createElement(FIELD_TYPES_ICON[field.type].icon, {
            size: 18,
            className: 'text-gray-600',
          })}
        <span className="font-medium">
          {field.type === 'paragraph'
            ? 'Paragraphe'
            : field.type.startsWith('heading')
              ? `Titre ${field.type.replace('heading', '')}`
              : field.label}
        </span>
        <span className="text-sm text-gray-500">
          ({field.type}){field.required && ' *'}
        </span>
      </div>
      <div className="flex gap-1">
        <button
          onClick={() => editField(index)}
          className="p-1 text-blue-500 hover:text-blue-700"
          title="Modifier"
        >
          <Edit2 size={16} />
        </button>
        <button
          onClick={() => deleteField(index)}
          className="p-1 text-red-500 hover:text-red-700"
          title="Supprimer"
        >
          <Trash2 size={16} />
        </button>
      </div>
    </div>
  );
};

export default function FormTemplateBuilder({
  onSave,
  initialData,
  groups,
  isEditing,
  masterFile = null,
  onMasterFileUpload,
}) {
  const [formConfig, setFormConfig] = useState({
    id: initialData?.id || 0,
    title: initialData?.name || 'Nouveau formulaire',
    submitLabel: 'Envoyer',
    fields: initialData?.formMasterData?.fields || [],
  });

  const [selectedGroups, setSelectedGroups] = useState(
    initialData?.groups?.map((g) =>
      typeof g === 'object' && g !== null ? g.id : g
    ) || []
  );

  const [showAddFieldModal, setShowAddFieldModal] = useState(false);
  const [showFieldTypeSelector, setShowFieldTypeSelector] = useState(false);
  const [selectedFieldType, setSelectedFieldType] = useState(null);
  const [editingIndex, setEditingIndex] = useState(-1);
  const [saving, setSaving] = useState(false);
  const [saveMessage, setSaveMessage] = useState({ type: '', text: '' });
  const [showScrollButton, setShowScrollButton] = useState(false);
  const [showJsonSection, setShowJsonSection] = useState(false);

  const { reset: resetField } = useForm();

  // Initialiser les données du formulaire quand initialData change
  useEffect(() => {
    if (initialData) {
      setFormConfig({
        id: initialData.id || 0,
        title: initialData.name || 'Nouveau formulaire',
        submitLabel: 'Envoyer',
        fields: initialData.formMasterData?.fields || [],
      });
      setSelectedGroups(
        initialData.groups?.map((g) =>
          typeof g === 'object' && g !== null ? g.id : g
        ) || []
      );
    }
  }, [initialData]);

  // Gérer l'affichage du bouton de défilement
  useEffect(() => {
    const handleScroll = () => {
      // Afficher le bouton quand on descend d'au moins 300px
      setShowScrollButton(window.scrollY > 300);
    };

    // Ajouter l'écouteur d'événement
    window.addEventListener('scroll', handleScroll);

    // Nettoyage de l'écouteur lors du démontage du composant
    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  }, []);

  // Fonction pour remonter en haut de la page
  const scrollToTop = () => {
    window.scrollTo({
      top: 0,
      behavior: 'smooth',
    });
  };

  // Générer un ID unique pour les champs
  const generateFieldId = (label) => {
    return label
      .toLowerCase()
      .replace(/[àáâãäå]/g, 'a')
      .replace(/[èéêë]/g, 'e')
      .replace(/[ìíîï]/g, 'i')
      .replace(/[òóôõö]/g, 'o')
      .replace(/[ùúûü]/g, 'u')
      .replace(/[ç]/g, 'c')
      .replace(/[^a-z0-9]/g, '_')
      .replace(/_+/g, '_')
      .replace(/^_|_$/g, '');
  };

  // Ajouter ou modifier un champ
  const handleFieldSubmit = (data, currentField, editIndex) => {
    const isHeadingType = data.type.startsWith('heading');
    const isContentTypeOnly = data.type === 'paragraph' || isHeadingType;
    const effectiveMasterFile = masterFile || currentField?.masterFileToUpload;

    if (currentField?.masterFileToUpload && onMasterFileUpload) {
      onMasterFileUpload(currentField.masterFileToUpload);
    }

    // Un champ fichier nécessite un document source déjà uploadé.
    if (data.type === 'file' && !effectiveMasterFile) {
      setSaveMessage({
        type: 'error',
        text:
          'Veuillez d\'abord uploader le document du formulaire avant d\'ajouter un champ fichier.',
      });
      return;
    }

    const fieldData = {
      ...data,
      id: isContentTypeOnly
        ? undefined
        : generateFieldId(data.label || 'field'),
      options: ['select', 'radio'].includes(data.type)
        ? Array.isArray(currentField.options)
          ? currentField.options
          : []
        : undefined,
      icon: data.icon || currentField.icon || undefined,
      placeholder: data.placeholder || undefined,
      text: isContentTypeOnly ? data.text : undefined,
      checked: ['checkbox', 'toggle'].includes(data.type)
        ? currentField.checked
        : undefined,
      horizontal:
        data.type === 'checkbox' ? currentField.horizontal : undefined,
      acceptTypes: data.type === 'file' ? currentField.acceptTypes : undefined,
      maxSize: data.type === 'file' ? currentField.maxSize : undefined,
      validation: ['phone', 'email', 'text'].includes(data.type)
        ? currentField.validation
        : undefined,
    };

    // Nettoyer les propriétés undefined
    Object.keys(fieldData).forEach((key) => {
      if (fieldData[key] === undefined || fieldData[key] === '') {
        delete fieldData[key];
      }
    });

    const newFields = [...formConfig.fields];

    if (editIndex >= 0) {
      newFields[editIndex] = fieldData;
    } else {
      newFields.push(fieldData);
    }

    setFormConfig({ ...formConfig, fields: newFields });
    setEditingIndex(-1);
  }; // Modifier un champ existant
  const editField = (index) => {
    setEditingIndex(index);
    setShowAddFieldModal(true);
  };

  // Supprimer un champ
  const deleteField = (index) => {
    const newFields = formConfig.fields.filter((_, i) => i !== index);
    setFormConfig({ ...formConfig, fields: newFields });
  };

  // Déplacer un champ
  const moveField = (dragIndex, hoverIndex) => {
    const newFields = [...formConfig.fields];
    const draggedField = newFields[dragIndex];

    // Supprimer l'élément déplacé
    newFields.splice(dragIndex, 1);

    // Insérer l'élément à sa nouvelle position
    newFields.splice(hoverIndex, 0, draggedField);

    setFormConfig({ ...formConfig, fields: newFields });
  };

  // Exporter le JSON
  const exportJson = () => {
    const jsonString = JSON.stringify(formConfig, null, 2);
    const blob = new Blob([jsonString], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `formulaire_${formConfig.title.replace(/\s+/g, '_').toLowerCase()}.json`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  };

  // Importer un JSON
  const importJson = (event) => {
    const file = event.target.files[0];
    if (file) {
      const reader = new FileReader();
      reader.onload = (e) => {
        try {
          const imported = JSON.parse(e.target.result);
          setFormConfig(imported);
        } catch (error) {
          alert('Erreur lors de l&apos;importation du fichier JSON');
        }
      };
      reader.readAsText(file);
    }
  };

  // Sauvegarder le formulaire (pour le backend)
  const saveFormTemplate = async () => {
    // Validation basique
    if (!formConfig.title.trim()) {
      setSaveMessage({
        type: 'error',
        text: 'Le titre du formulaire est requis',
      });
      return;
    }

    if (formConfig.fields.length === 0) {
      setSaveMessage({
        type: 'error',
        text: 'Ajoutez au moins un champ au formulaire',
      });
      return;
    }

    if (selectedGroups.length === 0) {
      setSaveMessage({
        type: 'error',
        text: "Sélectionnez au moins un groupe d'inscription",
      });
      return;
    }

    setSaving(true);
    setSaveMessage({ type: '', text: '' });

    try {
      const dataToSave = {
        name: formConfig.title,
        group_ids: selectedGroups,
        formMasterData: formConfig,
      };

      if (isEditing && initialData) {
        dataToSave.id = initialData.id;
      }

      if (onSave) {
        onSave(dataToSave);
      }

      setSaveMessage({
        type: 'success',
        text: 'Formulaire enregistré avec succès',
      });
    } catch (error) {
      setSaveMessage({
        type: 'error',
        text:
          error.message || "Une erreur est survenue lors de l'enregistrement",
      });
    } finally {
      setSaving(false);
    }
  };

  // Fonction pour gérer la sélection d'un type de champ
  const handleFieldTypeSelect = (fieldType) => {
    setSelectedFieldType(fieldType);
    setShowFieldTypeSelector(false);
    setShowAddFieldModal(true);
  };

  return (
    <DndProvider backend={HTML5Backend}>
      <div className="max-w-6xl mx-auto p-6">
        <div className="grid grid-cols-1 lg:grid-cols-5 gap-6">
          {/* Panel de configuration */}
          <div
            className={
              showJsonSection
                ? 'lg:col-span-3 space-y-6'
                : 'lg:col-span-5 space-y-6'
            }
          >
            <div className="bg-white p-6 rounded-lg shadow">
              <h2 className="font-headline text-xl font-bold mb-6">
                Configuration du formulaire
              </h2>

              {/* Configuration générale */}
              <div className="space-y-4 mb-6">
                <div className="flex justify-between items-center">
                  <h3 className="font-headline text-lg font-semibold mr-4">
                    Paramètres généraux
                  </h3>
                  <div className="flex gap-2">
                    <button
                      onClick={() => setShowJsonSection(!showJsonSection)}
                      className="px-4 py-2 rounded-md inline-flex items-center gap-2 bg-gray-500 hover:bg-gray-600 text-white"
                      title={
                        showJsonSection ? 'Masquer le JSON' : 'Afficher le JSON'
                      }
                    >
                      {showJsonSection ? (
                        <EyeOff size={18} />
                      ) : (
                        <Eye size={18} />
                      )}
                      <span>
                        {showJsonSection ? 'Masquer JSON' : 'Afficher JSON'}
                      </span>
                    </button>
                    <button
                      onClick={saveFormTemplate}
                      disabled={saving}
                      className={`px-4 py-2 rounded-md inline-flex items-center gap-2 ${
                        saving
                          ? 'bg-gray-400 cursor-not-allowed'
                          : 'bg-blue-500 hover:bg-blue-600 text-white'
                      }`}
                      title="Enregistrer le formulaire"
                    >
                      <Save size={18} />
                      <span>
                        {saving ? 'Enregistrement...' : 'Enregistrer'}
                      </span>
                    </button>
                  </div>
                </div>

                {saveMessage.text && (
                  <div
                    className={`p-3 rounded ${
                      saveMessage.type === 'error'
                        ? 'bg-red-100 text-red-700'
                        : 'bg-primary/10 text-secondary'
                    }`}
                  >
                    {saveMessage.text}
                  </div>
                )}

                <InputTextIcon
                  label="Titre du formulaire"
                  name="title"
                  value={formConfig.title}
                  onChange={(e) =>
                    setFormConfig({ ...formConfig, title: e.target.value })
                  }
                  required
                />

                <InputTextIcon
                  label="Texte du bouton de soumission du formulaire"
                  name="submitLabel"
                  value={formConfig.submitLabel}
                  onChange={(e) =>
                    setFormConfig({
                      ...formConfig,
                      submitLabel: e.target.value,
                    })
                  }
                />

                {/* Sélecteur de groupes */}
                <div className="space-y-2">
                  <label className="block text-sm font-medium text-gray-700">
                    Groupes d&apos;inscription{' '}
                    <span className="text-red-500">*</span>
                  </label>
                  <div className="flex flex-wrap gap-4 max-h-32 overflow-y-auto border rounded-md p-2">
                    {groups && groups.length > 0 ? (
                      groups.map((group) => (
                        <CheckBox
                          key={group.id}
                          item={{ id: group.id }}
                          formData={{
                            groups: selectedGroups
                          }}
                          handleChange={() => {
                            let group_ids = selectedGroups;
                            if (group_ids.includes(group.id)) {
                              group_ids = group_ids.filter((id) => id !== group.id);
                            } else {
                              group_ids = [...group_ids, group.id];
                            }
                            setSelectedGroups(group_ids);
                          }}
                          fieldName="groups"
                          itemLabelFunc={() => group.name}
                        />
                      ))
                    ) : (
                      <p className="text-gray-500 text-sm">
                        Aucun groupe disponible
                      </p>
                    )}
                  </div>
                </div>
              </div>

              {/* Liste des champs */}
              <div className="space-y-4">
                <div className="flex justify-between items-center">
                  <h3 className="font-headline text-lg font-semibold mr-4">
                    Champs du formulaire ({formConfig.fields.length})
                  </h3>
                  <button
                    onClick={() => {
                      setEditingIndex(-1);
                      setSelectedFieldType(null);
                      setShowFieldTypeSelector(true);
                    }}
                    className="p-2 bg-primary text-white rounded hover:bg-secondary transition-colors"
                    title="Ajouter un champ"
                  >
                    <PlusCircle size={18} />
                  </button>
                </div>

                {formConfig.fields.length === 0 ? (
                  <div className="text-center py-8 border-2 border-dashed border-gray-300 rounded-lg">
                    <p className="text-gray-500 italic mb-4">
                      Aucun champ ajouté
                    </p>
                    <button
                      onClick={() => {
                        setEditingIndex(-1);
                        setSelectedFieldType(null);
                        setShowFieldTypeSelector(true);
                      }}
                      className="px-4 py-2 bg-primary text-white rounded hover:bg-secondary transition-colors inline-flex items-center gap-2"
                    >
                      <PlusCircle size={18} />
                      <span>Ajouter mon premier champ</span>
                    </button>
                  </div>
                ) : (
                  <div className="space-y-2">
                    {formConfig.fields.map((field, index) => (
                      <DraggableFieldItem
                        key={index}
                        field={field}
                        index={index}
                        moveField={moveField}
                        editField={editField}
                        deleteField={deleteField}
                      />
                    ))}
                  </div>
                )}
              </div>

              {/* Actions */}
              <div className="mt-6">
                {/* Les actions ont été déplacées dans la section JSON généré */}
              </div>
            </div>
          </div>

          {/* JSON généré */}
          {showJsonSection && (
            <div className="lg:col-span-2">
              <div className="bg-white p-6 rounded-lg shadow h-full">
                <div className="flex justify-between items-center mb-4">
                  <h3 className="font-headline text-lg font-semibold mr-4">JSON généré</h3>
                  <div className="flex gap-2">
                    <button
                      onClick={exportJson}
                      className="p-2 bg-purple-500 text-white rounded-md hover:bg-purple-600 transition-colors"
                      title="Exporter JSON"
                    >
                      <Download size={18} />
                    </button>
                    <label
                      className="p-2 bg-orange-500 text-white rounded-md hover:bg-orange-600 cursor-pointer transition-colors"
                      title="Importer JSON"
                    >
                      <Upload size={18} />
                      <input
                        type="file"
                        accept=".json"
                        onChange={importJson}
                        className="hidden"
                      />
                    </label>
                  </div>
                </div>
                <pre className="bg-gray-100 p-4 rounded text-sm overflow-auto max-h-96">
                  {JSON.stringify(formConfig, null, 2)}
                </pre>
              </div>
            </div>
          )}
        </div>

        {/* Aperçu */}
        <div className="mt-6">
          <div className="bg-white p-6 rounded-lg shadow">
            <h3 className="font-headline text-lg font-semibold mb-4">Aperçu du formulaire</h3>
            <div className="border-2 border-dashed border-gray-300 p-6 rounded">
              {formConfig.fields.length > 0 ? (
                <FormRenderer formConfig={formConfig} masterFile={masterFile} />
              ) : (
                <p className="text-gray-500 italic text-center">
                  Ajoutez des champs pour voir l&apos;aperçu
                </p>
              )}
            </div>
          </div>
        </div>

        {/* Modal d'ajout/modification de champ */}
        <AddFieldModal
          isOpen={showAddFieldModal}
          onClose={() => setShowAddFieldModal(false)}
          onSubmit={handleFieldSubmit}
          hasMasterFile={Boolean(masterFile)}
          onMasterFileUpload={onMasterFileUpload}
          editingField={
            editingIndex >= 0
              ? formConfig.fields[editingIndex]
              : selectedFieldType
                ? { type: selectedFieldType.value || selectedFieldType }
                : null
          }
          editingIndex={editingIndex}
        />

        {/* Sélecteur de type de champ */}
        <FieldTypeSelector
          isOpen={showFieldTypeSelector}
          onClose={() => setShowFieldTypeSelector(false)}
          onSelect={handleFieldTypeSelect}
        />

        {/* Bouton flottant pour remonter en haut */}
        {showScrollButton && (
          <div className="fixed bottom-6 right-6 z-10">
            <button
              onClick={scrollToTop}
              className="p-4 rounded-full shadow-lg flex items-center justify-center bg-gray-500 hover:bg-gray-600 text-white transition-all duration-300"
              title="Remonter en haut de la page"
            >
              <ChevronUp size={24} />
            </button>
          </div>
        )}
      </div>
    </DndProvider>
  );
}
