import { useState, useEffect, useCallback } from 'react';
import { type Category } from '../../types/Category';
import OperationManager from './OperationManager';
import { categoryService } from '../../services/categoryService';
import { attributeService } from '../../services/attributeService';
import { type AttributeDefinition } from '../../types/AttributeDefinition';
import Modal from '../../components/Modal';
import { Plus, Edit, Trash2, ChevronRight, ChevronDown, Folder, FolderOpen, Settings, LayoutList, GitMerge, Move, ArrowRightCircle } from 'lucide-react';
import clsx from 'clsx';
import { operationService } from '../../services/operationService';
import { type Operation } from '../../types/Operation';
import api from '../../services/api';

// Type helper for the tree structure
interface CategoryNode extends Category {
  children: CategoryNode[];
  level: number;
}

export default function CategoryManager() {
  const [categories, setCategories] = useState<CategoryNode[]>([]);
  const [flatCategories, setFlatCategories] = useState<Category[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [isModalOpen, setIsModalOpen] = useState(false);

  // Drag & Drop State
  const [draggedNode, setDraggedNode] = useState<CategoryNode | null>(null);
  const [dragOverNodeId, setDragOverNodeId] = useState<number | null>(null);

  // Form state
  const [editingCategory, setEditingCategory] = useState<Category | null>(null);
  const [formData, setFormData] = useState<Partial<Category>>({ name: '', slug: '', active: true, parentId: null });

  // State for operations matrix
  const [selectedCategoryOps, setSelectedCategoryOps] = useState<Operation[]>([]);
  const [allOperations, setAllOperations] = useState<Operation[]>([]);
  const [configuringCategory, setConfiguringCategory] = useState<Category | null>(null);
  const [isOpsModalOpen, setIsOpsModalOpen] = useState(false);

  // State for Attributes
  const [isAttrModalOpen, setIsAttrModalOpen] = useState(false);
  const [attributes, setAttributes] = useState<AttributeDefinition[]>([]);
  const [newAttrData, setNewAttrData] = useState({
    name: '',
    dataType: 'text',
    required: false
  });

  // State for Merge
  const [isMergeModalOpen, setIsMergeModalOpen] = useState(false);
  const [targetMergeId, setTargetMergeId] = useState<number>(0);

  // State for Move Content
  const [isMoveContentModalOpen, setIsMoveContentModalOpen] = useState(false);

  const buildTree = useCallback((cats: Category[], parentId: number | null = null, level = 0): CategoryNode[] => {
    return cats
      .filter(c => c.parentId === parentId)
      .map(c => ({
        ...c,
        level,
        children: buildTree(cats, c.id, level + 1)
      }));
  }, []);

  const loadCategories = useCallback(async () => {
    setIsLoading(true);
    try {
      const data = await categoryService.getAll();
      setFlatCategories(data);
      const tree = buildTree(data);
      setCategories(tree);
    } catch (error) {
      console.error('Error loading categories:', error);
    } finally {
      setIsLoading(false);
    }
  }, [buildTree]);

  useEffect(() => {
    loadCategories();
  }, [loadCategories]);

  // --- LÓGICA DRAG & DROP ---

  const handleDragStart = (e: React.DragEvent, node: CategoryNode) => {
    e.stopPropagation();
    e.dataTransfer.effectAllowed = 'move';
    e.dataTransfer.setData('text/plain', JSON.stringify(node));
    setTimeout(() => {
      setDraggedNode(node);
    }, 0);
  };

  const handleDragEnd = (e: React.DragEvent) => {
    e.preventDefault();
    setDraggedNode(null);
    setDragOverNodeId(null);
  };

  const isDescendant = (sourceNode: CategoryNode, targetId: number): boolean => {
    if (sourceNode.children.some(child => child.id === targetId)) return true;
    return sourceNode.children.some(child => isDescendant(child, targetId));
  };

  const handleDragOver = (e: React.DragEvent, targetId: number) => {
    e.preventDefault();
    e.stopPropagation();
    if (!draggedNode || draggedNode.id === targetId) return;
    if (isDescendant(draggedNode, targetId)) return;
    setDragOverNodeId(targetId);
  };

  const handleDragLeave = (e: React.DragEvent) => {
    e.preventDefault();
    e.stopPropagation();
  };

  const handleDrop = async (e: React.DragEvent, targetNode: CategoryNode | null) => {
    e.preventDefault();
    e.stopPropagation();
    setDragOverNodeId(null);

    if (!draggedNode) return;

    const newParentId = targetNode ? targetNode.id : null;

    if (draggedNode.parentId === newParentId) {
      setDraggedNode(null);
      return;
    }

    if (targetNode && isDescendant(draggedNode, targetNode.id)) {
      alert("Operación inválida: No puedes mover una categoría dentro de sus propios hijos.");
      setDraggedNode(null);
      return;
    }

    const actionText = targetNode ? `dentro de "${targetNode.name}"` : "al nivel Raíz";

    if (!confirm(`¿Mover "${draggedNode.name}" ${actionText}?`)) {
      setDraggedNode(null);
      return;
    }

    try {
      await categoryService.update(draggedNode.id, {
        id: draggedNode.id,
        name: draggedNode.name,
        slug: draggedNode.slug,
        active: draggedNode.active,
        parentId: newParentId
      });

      loadCategories();
    } catch (error: unknown) {
      console.error("Error detallado en Drop:", error);
      let errorMessage = "Error al mover la categoría";

      // Casteo seguro para acceder a las propiedades de Axios
      const err = error as {
        response?: { data?: string | { message?: string; title?: string } };
        message?: string
      };

      if (typeof err.response?.data === 'string') {
        errorMessage = err.response.data;
      } else if (err.response?.data) {
        errorMessage = err.response.data.message || err.response.data.title || JSON.stringify(err.response.data);
      } else if (err.message) {
        errorMessage = err.message;
      }

      alert(`❌ Operación Rechazada:\n${errorMessage}`);
    } finally {
      setDraggedNode(null);
    }
  };

  // --- FIN LÓGICA DRAG & DROP ---

  const handleCreate = (parentId: number | null = null) => {
    setEditingCategory(null);
    setFormData({ name: '', slug: '', active: true, parentId });
    setIsModalOpen(true);
  };

  const handleEdit = (category: Category) => {
    setEditingCategory(category);
    setFormData({ ...category });
    setIsModalOpen(true);
  };

  const handleDelete = async (id: number) => {
    if (!confirm('¿Está seguro de eliminar esta categoría y todas sus subcategorías?')) return;
    try {
      await categoryService.delete(id);
      loadCategories();
    } catch (error) {
      console.error('Error deleting category:', error);
      alert('Error al eliminar');
    }
  };

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    try {
      if (editingCategory) {
        await categoryService.update(editingCategory.id, formData);
      } else {
        await categoryService.create(formData);
      }
      setIsModalOpen(false);
      loadCategories();
    } catch (error: unknown) {
      console.error('Error saving category:', error);
      const err = error as { response?: { data?: string } };
      alert(err.response?.data || 'Error al guardar la categoría. Verifique las reglas.');
    }
  };

  const handleConfigureOps = async (category: Category) => {
    setConfiguringCategory(category);
    setIsOpsModalOpen(true);
    const [ops, catOps] = await Promise.all([
      operationService.getAll(),
      categoryService.getOperations(category.id)
    ]);
    setAllOperations(ops);
    setSelectedCategoryOps(catOps);
  };

  const loadAttributes = useCallback(async (categoryId: number) => {
    const attrs = await attributeService.getByCategoryId(categoryId);
    setAttributes(attrs);
  }, []);

  const handleConfigureAttributes = async (category: Category) => {
    setConfiguringCategory(category);
    setIsAttrModalOpen(true);
    loadAttributes(category.id);
  };

  const handleCreateAttribute = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!configuringCategory || !newAttrData.name) return;
    try {
      await attributeService.create({
        ...newAttrData,
        categoryId: configuringCategory.id,
        dataType: newAttrData.dataType as 'text' | 'number' | 'boolean' | 'date'
      });
      setNewAttrData({ name: '', dataType: 'text', required: false });
      loadAttributes(configuringCategory.id);
    } catch (error: unknown) {
      console.error("Error creando atributo:", error);
    }
  };

  const handleDeleteAttribute = async (id: number) => {
    if (!confirm('Eliminar atributo?')) return;
    try {
      await attributeService.delete(id);
      if (configuringCategory) loadAttributes(configuringCategory.id);
    } catch (error: unknown) {
      console.error("Error eliminando atributo:", error);
    }
  };

  const toggleOperation = async (opId: number, isChecked: boolean) => {
    if (!configuringCategory) return;
    try {
      if (isChecked) {
        await categoryService.addOperation(configuringCategory.id, opId);
        const opToAdd = allOperations.find(o => o.id === opId);
        if (opToAdd) setSelectedCategoryOps([...selectedCategoryOps, opToAdd]);
      } else {
        await categoryService.removeOperation(configuringCategory.id, opId);
        setSelectedCategoryOps(selectedCategoryOps.filter(o => o.id !== opId));
      }
    } catch (error: unknown) {
      console.error("Error actualizando operación:", error);
      alert("Error actualizando operación");
    }
  };

  const handleOpenMerge = (cat: Category) => {
    setEditingCategory(cat);
    setTargetMergeId(0);
    setIsMergeModalOpen(true);
  }

  const handleMerge = async () => {
    if (!editingCategory || !targetMergeId) return;
    if (confirm(`¿CONFIRMAR FUSIÓN?\n\nTodo el contenido de "${editingCategory.name}" pasará a la categoría destino.\n"${editingCategory.name}" será ELIMINADA permanentemente.`)) {
      try {
        await api.post('/categories/merge', { sourceId: editingCategory.id, targetId: targetMergeId });
        setIsMergeModalOpen(false);
        loadCategories();
        alert("Fusión completada.");
      } catch (error: unknown) {
        console.error("Error en la operación:", error);
        alert("Error al procesar la solicitud");
      }
    }
  }

  const handleOpenMoveContent = (cat: Category) => {
    setEditingCategory(cat);
    setTargetMergeId(0);
    setIsMoveContentModalOpen(true);
  }

  const handleMoveContent = async () => {
    if (!editingCategory || !targetMergeId) return;
    try {
      await api.post('/categories/move-content', {
        sourceId: editingCategory.id,
        targetId: targetMergeId
      });
      setIsMoveContentModalOpen(false);
      alert("Avisos movidos correctamente. Ahora puede agregar subcategorías.");
    } catch (e) {
      console.error(e);
      alert("Error al mover avisos");
    }
  }

  const isParentCategory = (id: number) => {
    return flatCategories.some(c => c.parentId === id);
  };

  const CategoryItem = ({ node }: { node: CategoryNode }) => {
    const [isExpanded, setIsExpanded] = useState(true);
    const isDragOver = dragOverNodeId === node.id;
    const isBeingDragged = draggedNode?.id === node.id;

    return (
      <div
        className={clsx("mb-1 transition-all duration-200", isBeingDragged && "opacity-40 grayscale")}
        style={{ marginLeft: `${node.level * 20}px` }}
      >
        <div
          draggable="true"
          onDragStart={(e) => handleDragStart(e, node)}
          onDragOver={(e) => handleDragOver(e, node.id)}
          onDragLeave={handleDragLeave}
          onDrop={(e) => handleDrop(e, node)}
          onDragEnd={handleDragEnd}
          className={clsx(
            "flex items-center p-2 rounded transition-all group border-b border-gray-100 cursor-grab active:cursor-grabbing select-none",
            node.level === 0 && "font-semibold bg-gray-50 border-gray-200",
            isDragOver
              ? "bg-blue-100 border-2 border-blue-500 shadow-md transform scale-[1.01] z-10"
              : "hover:bg-gray-100 border-transparent"
          )}
        >
          <div className="mr-2 text-gray-300 group-hover:text-gray-500 cursor-grab">
            <Move size={14} />
          </div>

          <button onClick={() => setIsExpanded(!isExpanded)} className={clsx("mr-2 text-gray-500", node.children.length === 0 && "opacity-0")}>
            {isExpanded ? <ChevronDown size={16} /> : <ChevronRight size={16} />}
          </button>

          <span className={clsx("mr-2", isDragOver ? "text-blue-700" : "text-blue-500")}>
            {isExpanded ? <FolderOpen size={18} /> : <Folder size={18} />}
          </span>

          <span className="flex-1 font-medium text-gray-700">{node.name}</span>

          <div className="flex gap-2 opacity-0 group-hover:opacity-100 transition-opacity">
            <button onClick={() => handleConfigureAttributes(node)} className="p-1 text-orange-600 hover:bg-orange-100 rounded" title="Atributos"><LayoutList size={16} /></button>
            <button onClick={() => handleConfigureOps(node)} className="p-1 text-purple-600 hover:bg-purple-100 rounded" title="Operaciones"><Settings size={16} /></button>
            <button onClick={() => handleOpenMoveContent(node)} className="p-1 text-teal-600 hover:bg-teal-100 rounded" title="Mover Avisos (Vaciar)"><ArrowRightCircle size={16} /></button>
            <button onClick={() => handleOpenMerge(node)} className="p-1 text-indigo-600 hover:bg-indigo-100 rounded" title="Fusionar (Merge)"><GitMerge size={16} /></button>
            <button onClick={() => handleCreate(node.id)} className="p-1 text-green-600 hover:bg-green-100 rounded" title="Subcategoría"><Plus size={16} /></button>
            <button onClick={() => handleEdit(node)} className="p-1 text-blue-600 hover:bg-blue-100 rounded" title="Editar"><Edit size={16} /></button>
            <button onClick={() => handleDelete(node.id)} className="p-1 text-red-600 hover:bg-red-100 rounded" title="Eliminar"><Trash2 size={16} /></button>
          </div>
        </div>

        {isExpanded && node.children.length > 0 && (
          <div className="border-l-2 border-gray-200 ml-5 pl-1 py-1">
            {node.children.map(child => <CategoryItem key={child.id} node={child} />)}
          </div>
        )}
      </div>
    );
  };

  return (
    <div>
      <div className="flex justify-between items-center mb-6">
        <h2 className="text-2xl font-bold text-gray-800">Estructura de Categorías</h2>
        <button
          onClick={() => handleCreate(null)}
          className="flex items-center gap-2 bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 transition"
        >
          <Plus size={20} />
          <span>Nueva Categoría Raíz</span>
        </button>
      </div>

      <OperationManager />

      <div
        className={clsx(
          "bg-white rounded shadow p-6 min-h-[500px] border-2 transition-all duration-200",
          draggedNode && dragOverNodeId === null
            ? "border-dashed border-blue-400 bg-blue-50/50"
            : "border-transparent"
        )}
        onDragOver={(e) => { e.preventDefault(); setDragOverNodeId(null); }}
        onDrop={(e) => handleDrop(e, null)}
      >
        {isLoading ? (
          <div className="text-center text-gray-500 py-10">Cargando taxonomía...</div>
        ) : categories.length === 0 ? (
          <div className="text-center text-gray-400 py-10">No hay categorías definidas. Crea la primera o arrastra aquí para mover a la raíz.</div>
        ) : (
          <div className="space-y-1">
            {categories.map(node => (
              <CategoryItem key={node.id} node={node} />
            ))}
          </div>
        )}

        {draggedNode && (
          <div className={clsx(
            "mt-8 py-8 border-2 border-dashed border-gray-300 rounded-lg flex items-center justify-center text-gray-400 pointer-events-none transition-opacity duration-300",
            draggedNode ? "opacity-100" : "opacity-0 h-0 py-0 mt-0 overflow-hidden"
          )}>
            <Move className="mr-2" /> Soltar aquí para convertir en Categoría Raíz
          </div>
        )}
      </div>

      {/* --- MODALES --- */}

      <Modal
        isOpen={isModalOpen}
        onClose={() => setIsModalOpen(false)}
        title={editingCategory ? 'Editar Categoría' : 'Nueva Categoría'}
      >
        <form onSubmit={handleSubmit} className="space-y-4">
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-1">Nombre</label>
            <input
              type="text"
              required
              value={formData.name}
              onChange={(e) => setFormData({ ...formData, name: e.target.value })}
              className="w-full border border-gray-300 rounded p-2 focus:ring-2 focus:ring-blue-500 outline-none"
            />
          </div>
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-1">Slug (URL)</label>
            <input
              type="text"
              required
              value={formData.slug}
              onChange={(e) => setFormData({ ...formData, slug: e.target.value })}
              className="w-full border border-gray-300 rounded p-2 focus:ring-2 focus:ring-blue-500 outline-none"
            />
          </div>
          <div className="flex items-center gap-2">
            <input
              type="checkbox"
              checked={formData.active}
              onChange={(e) => setFormData({ ...formData, active: e.target.checked })}
              id="activeCheck"
              className="rounded text-blue-600 focus:ring-blue-500"
            />
            <label htmlFor="activeCheck" className="text-sm font-medium text-gray-700">Activa</label>
          </div>

          <div className="pt-4 flex justify-end gap-2">
            <button
              type="button"
              onClick={() => setIsModalOpen(false)}
              className="px-4 py-2 text-gray-600 hover:bg-gray-100 rounded"
            >
              Cancelar
            </button>
            <button
              type="submit"
              className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
            >
              Guardar
            </button>
          </div>
        </form>
      </Modal>

      <Modal
        isOpen={isOpsModalOpen}
        onClose={() => setIsOpsModalOpen(false)}
        title={`Operaciones para: ${configuringCategory?.name}`}
      >
        <div>
          <p className="text-sm text-gray-500 mb-4">Seleccione las operaciones habilitadas para este rubro.</p>
          {allOperations.length === 0 && <p>No hay operaciones definidas.</p>}
          <div className="space-y-2">
            {allOperations.map(op => {
              const isSelected = selectedCategoryOps.some(so => so.id === op.id);
              return (
                <label key={op.id} className="flex items-center gap-2 p-2 rounded hover:bg-gray-50 border border-gray-200 cursor-pointer">
                  <input
                    type="checkbox"
                    checked={isSelected}
                    onChange={(e) => toggleOperation(op.id, e.target.checked)}
                    className="rounded text-blue-600 focus:ring-blue-500"
                  />
                  <span>{op.name}</span>
                </label>
              );
            })}
          </div>
          <div className="pt-4 text-right">
            <button onClick={() => setIsOpsModalOpen(false)} className="bg-blue-600 text-white px-4 py-2 rounded">Listo</button>
          </div>
        </div>
      </Modal>

      <Modal
        isOpen={isAttrModalOpen}
        onClose={() => setIsAttrModalOpen(false)}
        title={`Atributos de: ${configuringCategory?.name}`}
      >
        <div className="space-y-6">
          <div>
            <h4 className="font-semibold mb-2 text-sm text-gray-700">Atributos Actuales</h4>
            {attributes.length === 0 ? (
              <p className="text-sm text-gray-400 italic">No hay atributos definidos.</p>
            ) : (
              <div className="space-y-2">
                {attributes.map(attr => (
                  <div key={attr.id} className="flex items-center justify-between bg-gray-50 p-2 rounded border">
                    <div className="text-sm">
                      <span className="font-medium">{attr.name}</span>
                      <span className="text-gray-500 ml-2 text-xs">({attr.dataType})</span>
                      {attr.required && <span className="text-red-500 ml-1 text-xs">*Req</span>}
                    </div>
                    <button onClick={() => handleDeleteAttribute(attr.id)} className="text-red-500 hover:text-red-700">
                      <Trash2 size={16} />
                    </button>
                  </div>
                ))}
              </div>
            )}
          </div>

          <form onSubmit={handleCreateAttribute} className="border-t pt-4">
            <h4 className="font-semibold mb-3 text-sm text-gray-700">Agregar Atributo</h4>
            <div className="flex gap-2 mb-2">
              <input
                type="text"
                placeholder="Nombre (ej: Kilometraje)"
                className="flex-1 border p-2 rounded text-sm"
                value={newAttrData.name}
                onChange={e => setNewAttrData({ ...newAttrData, name: e.target.value })}
                required
              />
              <select
                className="border p-2 rounded text-sm"
                value={newAttrData.dataType}
                onChange={e => setNewAttrData({ ...newAttrData, dataType: e.target.value })}
              >
                <option value="text">Texto</option>
                <option value="number">Número</option>
                <option value="boolean">Si/No</option>
                <option value="date">Fecha</option>
              </select>
            </div>
            <div className="flex items-center justify-between">
              <label className="flex items-center gap-2 text-sm text-gray-600">
                <input
                  type="checkbox"
                  checked={newAttrData.required}
                  onChange={e => setNewAttrData({ ...newAttrData, required: e.target.checked })}
                />
                Es obligatorio
              </label>
              <button type="submit" className="bg-green-600 text-white px-3 py-1.5 rounded text-sm hover:bg-green-700 flex items-center gap-1">
                <Plus size={16} /> Agregar
              </button>
            </div>
          </form>
        </div>
      </Modal>

      <Modal isOpen={isMergeModalOpen} onClose={() => setIsMergeModalOpen(false)} title="Fusionar Categorías">
        <div className="space-y-4">
          <p className="text-sm text-gray-600 bg-yellow-50 p-3 rounded border border-yellow-200">
            Está a punto de mover todo el contenido de <strong>{editingCategory?.name}</strong> a otra categoría.
            <br />
            <span className="text-red-600 font-bold">¡La categoría original será eliminada!</span>
          </p>
          <div>
            <label className="block text-sm font-bold mb-2">Seleccione Categoría Destino:</label>
            <select
              className="w-full border p-2 rounded focus:ring-2 focus:ring-indigo-500 outline-none"
              onChange={e => setTargetMergeId(Number(e.target.value))}
              value={targetMergeId}
            >
              <option value="0">-- Seleccionar Destino --</option>
              {flatCategories
                .filter(c => c.id !== editingCategory?.id)
                .map(c => (
                  <option key={c.id} value={c.id}>{c.name}</option>
                ))}
            </select>
          </div>
          <div className="flex justify-end gap-2 pt-2">
            <button onClick={() => setIsMergeModalOpen(false)} className="px-4 py-2 text-gray-600 hover:bg-gray-100 rounded">Cancelar</button>
            <button
              onClick={handleMerge}
              disabled={!targetMergeId}
              className="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
            >
              Confirmar Fusión
            </button>
          </div>
        </div>
      </Modal>

      <Modal isOpen={isMoveContentModalOpen} onClose={() => setIsMoveContentModalOpen(false)} title="Mover Avisos (Vaciar)">
        <div className="space-y-4">
          <div className="bg-blue-50 p-3 rounded border border-blue-200 text-sm text-gray-700">
            <p className="font-bold mb-1">Mover avisos de: {editingCategory?.name}</p>
            <p>Seleccione un destino para los avisos. <br />
              <span className="text-xs text-blue-600">* Solo se permiten categorías finales (sin hijos).</span></p>
          </div>

          <div>
            <label className="block text-sm font-bold mb-2">Destino de los avisos:</label>
            <select
              className="w-full border p-2 rounded focus:ring-2 focus:ring-teal-500 outline-none"
              onChange={e => setTargetMergeId(Number(e.target.value))}
              value={targetMergeId}
            >
              <option value="0">-- Seleccionar Destino --</option>
              {flatCategories
                .filter(c =>
                  c.id !== editingCategory?.id &&
                  !isParentCategory(c.id)
                )
                .map(c => (
                  <option key={c.id} value={c.id}>{c.name}</option>
                ))}
            </select>
          </div>

          <div className="flex justify-end gap-2 pt-2">
            <button onClick={() => setIsMoveContentModalOpen(false)} className="px-4 py-2 text-gray-600 hover:bg-gray-100 rounded">Cancelar</button>
            <button
              onClick={handleMoveContent}
              disabled={!targetMergeId}
              className="bg-teal-600 hover:bg-teal-700 text-white px-4 py-2 rounded disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
            >
              Mover Avisos
            </button>
          </div>
        </div>
      </Modal>
    </div>
  );
}