import { Icon } from "@iconify/react";
import {
  Autocomplete,
  Box,
  Button,
  Chip,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle,
  MenuItem,
  IconButton,
  List,
  ListItem,
  ListItemSecondaryAction,
  ListItemText,
  Skeleton,
  TextField,
  Tooltip,
  Typography,
  useMediaQuery,
  useTheme,
} from "@mui/material";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useMemo, useState } from "react";
import { useQuery as useQueryRubros } from "@tanstack/react-query";
import { getRubros } from "../../api/rubros.service";
import { useRubroStore } from "../../store/RubroStore";
import styled from "styled-components";
import { toast } from "sonner";
import {
  buscarProductos,
  createCategoria,
  deleteCategoria,
  getCategoriasTree,
  toggleCategoriaStatus,
  updateCategoria,
} from "../../api";
import api from "../../api/api.config";
import { usePermission } from "../../hooks/usePermission";
import { getErrorApi } from "../../utils/errorUtils";
import { AccesoRestringido } from "../common/AccesoRestringido";
import { EmptyState, ScreenGuia } from "../_standards";

const GUIA_PASOS = [
  {
    icon: "lucide:layers",
    color: "#3b82f6",
    titulo: "1. Crear categoría raíz",
    desc: "Definí los grupos principales de tus productos (Muebles, Electrónica, etc.).",
  },
  {
    icon: "lucide:git-branch",
    color: "#f59e0b",
    titulo: "2. Subcategorías",
    desc: "Hacé clic en + sobre una categoría para anidar subcategorías sin límite de profundidad.",
  },
  {
    icon: "lucide:package",
    color: "#22c55e",
    titulo: "3. Asignar productos",
    desc: "Desde el ícono de productos asignás artículos directamente a esa categoría.",
  },
];

const COLORS = [
  "#4ade80", "#60a5fa", "#f472b6", "#fbbf24", "#a78bfa", "#34d399",
  "#fb923c", "#38bdf8", "#f87171", "#818cf8", "#22d3ee", "#a3e635",
];

// ── Styled ────────────────────────────────────────────────────────
const Wrapper = styled.div`
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
`;
const SectionBar = styled.div`
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.75rem;
  .title-block {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    .title { font-size: 1.05rem; font-weight: 700; color: ${(p) => p.theme.text}; line-height: 1.2; }
    .subtitle { font-size: 0.78rem; color: ${(p) => p.theme.textSecondary}; }
  }
`;
const PrimaryBtn = styled.button`
  padding: 0.5rem 1rem;
  border-radius: 8px;
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border: none;
  background: ${(p) => p.theme.primary};
  color: #fff;
  white-space: nowrap;
  &:hover { opacity: 0.88; }
`;
const TreeBox = styled.div`
  border: 1px solid ${(p) => p.theme.borderColor};
  border-radius: 12px;
  background: ${(p) => p.theme.bg};
  padding: 0.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
`;
const Row = styled.div`
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 0.65rem;
  border-radius: 8px;
  border: 1px solid ${(p) => (p.$level === 0 ? p.theme.borderColor : "transparent")};
  transition: background 0.12s, border-color 0.12s;
  background: ${(p) => (p.$level === 0 ? p.theme.inputBg : "transparent")};
  &:hover {
    background: ${(p) => p.theme.bgAlpha};
    border-color: ${(p) => p.theme.primary}55;
  }
`;
const Caret = styled.button`
  background: none;
  border: none;
  cursor: pointer;
  width: 1.6rem;
  height: 1.6rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  color: ${(p) => p.theme.textSecondary};
  flex-shrink: 0;
  &:hover { background: ${(p) => p.theme.bgAlpha}; color: ${(p) => p.theme.text}; }
  &:disabled { opacity: 0.25; cursor: default; }
  svg { transition: transform 0.15s; transform: ${(p) => (p.$open ? "rotate(90deg)" : "rotate(0deg)")}; }
`;
const ColorDot = styled.span`
  width: 0.75rem;
  height: 0.75rem;
  border-radius: 50%;
  background: ${(p) => p.$color || "#94a3b8"};
  flex-shrink: 0;
  box-shadow: 0 0 0 2px ${(p) => p.$color || "#94a3b8"}22;
`;
const RowTitle = styled.div`
  flex: 1;
  min-width: 0;
  font-size: 0.875rem;
  font-weight: ${(p) => (p.$level === 0 ? 700 : 500)};
  color: ${(p) => p.theme.text};
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
`;
const Badge = styled.span`
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.15rem 0.55rem;
  border-radius: 20px;
  font-size: 0.68rem;
  font-weight: 600;
  color: ${(p) => p.$color};
  background: ${(p) => p.$color}14;
  border: 1px solid ${(p) => p.$color}30;
  white-space: nowrap;
`;
const ActionIcon = styled.button`
  background: none;
  border: none;
  cursor: pointer;
  padding: 0.3rem;
  border-radius: 6px;
  display: inline-flex;
  align-items: center;
  color: ${(p) => p.$color || p.theme.textSecondary};
  font-size: 1rem;
  &:hover { background: ${(p) => p.theme.bgAlpha}; }
  &:disabled { opacity: 0.35; cursor: not-allowed; }
`;
const Toolbar = styled.div`
  display: flex;
  gap: 0.5rem;
  align-items: center;
  flex-wrap: wrap;
  input {
    background: ${(p) => p.theme.inputBg};
    border: 1px solid ${(p) => p.theme.inputBorder};
    border-radius: 8px;
    padding: 0.45rem 0.75rem 0.45rem 2rem;
    color: ${(p) => p.theme.text};
    font-size: 0.85rem;
    outline: none;
    width: 280px;
    max-width: 100%;
    font-family: inherit;
    &:focus { border-color: ${(p) => p.theme.primary}; }
  }
`;
const SearchWrap = styled.div`
  position: relative;
  display: inline-flex;
  align-items: center;
  svg { position: absolute; left: 0.55rem; opacity: 0.5; pointer-events: none; }
`;
const GhostBtn = styled.button`
  background: transparent;
  border: 1px solid ${(p) => p.theme.borderColor};
  color: ${(p) => p.theme.textSecondary};
  border-radius: 8px;
  padding: 0.4rem 0.75rem;
  font-size: 0.78rem;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  &:hover { background: ${(p) => p.theme.bgAlpha}; color: ${(p) => p.theme.text}; }
`;

// ── Tree helpers ──────────────────────────────────────────────────
const filterTree = (nodes, q) => {
  if (!q) return nodes;
  const term = q.toLowerCase();
  const walk = (list) =>
    list
      .map((n) => {
        const children = walk(n.children || []);
        const matches = (n.descripcion || "").toLowerCase().includes(term);
        if (matches || children.length) return { ...n, children };
        return null;
      })
      .filter(Boolean);
  return walk(nodes);
};
/**
 * Deja las categorías del rubro en contexto más las compartidas (sin rubro),
 * misma regla que usan productos y proveedores.
 *
 * Conserva a un padre de otro rubro si alguno de sus hijos entra, para no dejar
 * huérfanas a las hijas: el árbol tiene que seguir siendo un árbol.
 */
const filtrarPorRubro = (nodes, rubroId) => {
  if (!rubroId) return nodes;
  const walk = (list) =>
    list
      .map((n) => {
        const children = walk(n.children || []);
        const entra = !n.rubro_id || n.rubro_id === rubroId;
        if (entra || children.length) return { ...n, children };
        return null;
      })
      .filter(Boolean);
  return walk(nodes);
};

const collectIds = (nodes, set = new Set()) => {
  nodes.forEach((n) => {
    set.add(n.id);
    if (n.children?.length) collectIds(n.children, set);
  });
  return set;
};

// ── Row component ─────────────────────────────────────────────────
function CategoriaNode({ categoria, level, ctx }) {
  const {
    expanded, setExpanded, isMobile,
    handleOpenProductos, handleOpenCreate, handleOpenEdit,
    canCreate, canEdit, canDelete, toggleMutation, deleteMutation,
  } = ctx;
  const hasChildren = (categoria.children?.length || 0) > 0;
  const isOpen = expanded[categoria.id];

  return (
    <Box sx={{ pl: `${level * 1.25}rem` }}>
      <Row $level={level}>
        <Caret
          $open={isOpen}
          disabled={!hasChildren}
          onClick={() => hasChildren && setExpanded((e) => ({ ...e, [categoria.id]: !e[categoria.id] }))}
          title={hasChildren ? (isOpen ? "Colapsar" : "Expandir") : "Sin subcategorías"}
        >
          <Icon icon="lucide:chevron-right" width={16} />
        </Caret>
        <ColorDot $color={categoria.color || categoria.icono} />
        <RowTitle $level={level}>{categoria.descripcion}</RowTitle>

        {/* Rubro de la categoría: es lo que hace que sus productos se separen
            por sucursal. Sin chip = categoría compartida entre todos los rubros.
            Ver docs/plan-rubros-multi-sucursal.md en el backend. */}
        {categoria.rubro && (
          <Badge $color={categoria.rubro.color || "#6366f1"}>
            <Icon icon={categoria.rubro.icono || "lucide:layers"} style={{ fontSize: "0.7rem" }} />
            {categoria.rubro.descripcion}
          </Badge>
        )}
        {hasChildren && (
          <Badge $color="#3b82f6">
            <Icon icon="lucide:git-branch" style={{ fontSize: "0.7rem" }} />
            {categoria.children.length}
          </Badge>
        )}
        {!isMobile && categoria._count?.productos > 0 && (
          <Badge $color="#22c55e">
            <Icon icon="lucide:package" style={{ fontSize: "0.7rem" }} />
            {categoria._count.productos}
          </Badge>
        )}
        <Badge $color={categoria.activo ? "#22c55e" : "#94a3b8"}>
          <Icon icon={categoria.activo ? "lucide:check-circle" : "lucide:circle-off"} style={{ fontSize: "0.7rem" }} />
          {categoria.activo ? "Activo" : "Inactivo"}
        </Badge>

        <Box sx={{ display: "flex", gap: 0.25 }}>
          <ActionIcon $color="#3b82f6" title="Ver productos" onClick={() => handleOpenProductos(categoria)}>
            <Icon icon="lucide:package" />
          </ActionIcon>
          {canCreate && (
            <ActionIcon $color="#22c55e" title="Agregar subcategoría" onClick={() => handleOpenCreate(categoria)}>
              <Icon icon="lucide:plus" />
            </ActionIcon>
          )}
          {canEdit && (
            <ActionIcon $color="#f59e0b" title="Editar" onClick={() => handleOpenEdit(categoria)}>
              <Icon icon="lucide:edit-3" />
            </ActionIcon>
          )}
          {canDelete && (
            <ActionIcon
              $color={categoria.activo ? "#94a3b8" : "#22c55e"}
              title={categoria.activo ? "Desactivar" : "Activar"}
              onClick={() => toggleMutation.mutate(categoria.id)}
            >
              <Icon icon="lucide:power" />
            </ActionIcon>
          )}
          {canDelete && (
            <ActionIcon
              $color="#ef4444"
              title="Eliminar"
              onClick={() => {
                if (confirm(`¿Eliminar la categoría "${categoria.descripcion}"?`)) {
                  deleteMutation.mutate(categoria.id);
                }
              }}
            >
              <Icon icon="lucide:trash-2" />
            </ActionIcon>
          )}
        </Box>
      </Row>

      {isOpen && hasChildren && (
        <Box sx={{ borderLeft: "2px solid", borderColor: "divider", ml: 1.4, mt: 0.25 }}>
          {categoria.children.map((child) => (
            <CategoriaNode key={child.id} categoria={child} level={level + 1} ctx={ctx} />
          ))}
        </Box>
      )}
    </Box>
  );
}

// ── Main ──────────────────────────────────────────────────────────
export function CategoriasTab() {
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.down("md"));
  const queryClient = useQueryClient();
  const { can } = usePermission("INVENTARIO");
  const canRead = can("INV_CAT_CATEGORIA_VER");
  const canCreate = can("INV_CAT_CATEGORIA_CREAR");
  const canEdit = can("INV_CAT_CATEGORIA_EDITAR");
  const canDelete = can("INV_CAT_CATEGORIA_ELIMINAR");

  const [formDialogOpen, setFormDialogOpen] = useState(false);
  const [formMode, setFormMode] = useState("create");
  const [selectedCategoria, setSelectedCategoria] = useState(null);
  const [parentCategoria, setParentCategoria] = useState(null);
  const [formData, setFormData] = useState({ descripcion: "", color: "#4ade80", rubro_id: "" });

  // Rubros activos. El rubro de la categoría es lo que hace que los productos
  // queden separados por rubro: el producto lo hereda de acá y no se etiqueta uno
  // por uno. Ver docs/plan-rubros-multi-sucursal.md en el backend.
  const { data: rubrosData } = useQueryRubros({
    queryKey: ["rubros-activos"],
    queryFn: () => getRubros(true),
    staleTime: 5 * 60 * 1000,
  });
  const rubros = Array.isArray(rubrosData) ? rubrosData : rubrosData?.data || [];
  const [expanded, setExpanded] = useState({});
  const [search, setSearch] = useState("");
  const [productosDialogOpen, setProductosDialogOpen] = useState(false);
  const [categoriaProductos, setCategoriaProductos] = useState(null);
  const [searchProducto, setSearchProducto] = useState("");

  const { data: tree = [], isLoading, error: categoriasError } = useQuery({
    queryKey: ["categorias-tree"],
    queryFn: getCategoriasTree,
    retry: (failureCount, error) => {
      if (error.response?.status === 403) return false;
      return failureCount < 3;
    },
  });

  const errorModulo = getErrorApi(categoriasError);

  // El árbol sigue el rubro elegido en el header, igual que el catálogo y los
  // proveedores. Ver docs/plan-rubros-multi-sucursal.md en el backend.
  const rubroId = useRubroStore((state) => state.rubroId);
  const filteredTree = useMemo(
    () => filterTree(filtrarPorRubro(tree, rubroId), search),
    [tree, search, rubroId],
  );

  const invalidateAll = () => {
    queryClient.invalidateQueries({ queryKey: ["categorias-tree"] });
    queryClient.invalidateQueries({ queryKey: ["categorias"] });
  };

  const createMutation = useMutation({
    mutationFn: createCategoria,
    onSuccess: () => {
      toast.success("Categoría creada");
      invalidateAll();
      handleCloseForm();
    },
    onError: (error) => toast.error(error.response?.data?.message || "Error al crear categoría"),
  });

  const updateMutation = useMutation({
    mutationFn: ({ id, data }) => updateCategoria(id, data),
    onSuccess: () => {
      toast.success("Categoría actualizada");
      invalidateAll();
      handleCloseForm();
    },
    onError: (error) => toast.error(error.response?.data?.message || "Error al actualizar"),
  });

  const toggleMutation = useMutation({
    mutationFn: toggleCategoriaStatus,
    onSuccess: () => {
      toast.success("Estado actualizado");
      invalidateAll();
    },
    onError: (error) => toast.error(error.response?.data?.message || "Error al cambiar estado"),
  });

  const deleteMutation = useMutation({
    mutationFn: deleteCategoria,
    onSuccess: () => {
      toast.success("Categoría eliminada");
      invalidateAll();
    },
    onError: (error) => toast.error(error.response?.data?.message || "Error al eliminar"),
  });

  const handleOpenCreate = (parent = null) => {
    setFormMode("create");
    setParentCategoria(parent);
    // La subcategoría arranca con el rubro del padre: lo natural es que lo herede.
    setFormData({ descripcion: "", color: "#4ade80", rubro_id: parent?.rubro_id || "" });
    setFormDialogOpen(true);
  };

  const handleOpenEdit = (categoria) => {
    setFormMode("edit");
    setSelectedCategoria(categoria);
    setFormData({
      descripcion: categoria.descripcion || "",
      color: categoria.color || "#4ade80",
      rubro_id: categoria.rubro_id || "",
    });
    setFormDialogOpen(true);
  };

  const handleCloseForm = () => {
    setFormDialogOpen(false);
    setSelectedCategoria(null);
    setParentCategoria(null);
  };

  const handleSubmit = () => {
    if (!formData.descripcion.trim()) {
      toast.error("La descripción es requerida");
      return;
    }
    if (formMode === "create") {
      createMutation.mutate({
        descripcion: formData.descripcion.trim(),
        padre_id: parentCategoria?.id || null,
        color: formData.color,
        rubro_id: formData.rubro_id || null,
      });
    } else {
      updateMutation.mutate({
        id: selectedCategoria.id,
        data: {
          descripcion: formData.descripcion.trim(),
          color: formData.color,
          rubro_id: formData.rubro_id || null,
        },
      });
    }
  };

  const expandAll = () => setExpanded(Object.fromEntries([...collectIds(tree)].map((id) => [id, true])));
  const collapseAll = () => setExpanded({});

  const { data: productosSearch = [], isFetching: searchingProductos } = useQuery({
    queryKey: ["productos-search", searchProducto],
    queryFn: () => buscarProductos(searchProducto),
    enabled: searchProducto.length >= 2,
  });

  const { data: productosCategoria = [], refetch: refetchProductosCategoria } = useQuery({
    queryKey: ["productos-categoria", categoriaProductos?.id],
    queryFn: async () => {
      if (!categoriaProductos?.id) return [];
      const response = await api.get(`/productos?categoria_id=${categoriaProductos.id}&limit=100`);
      return response.data?.data || [];
    },
    enabled: !!categoriaProductos?.id && productosDialogOpen,
  });

  const asignarProductoMutation = useMutation({
    mutationFn: async ({ productoId, categoriaId }) =>
      api.put(`/productos/${productoId}`, { categoria_id: categoriaId }),
    onSuccess: () => {
      toast.success("Producto asignado");
      refetchProductosCategoria();
      queryClient.invalidateQueries({ queryKey: ["productos"] });
    },
    onError: (error) => toast.error(error.response?.data?.message || "Error al asignar producto"),
  });

  const quitarProductoMutation = useMutation({
    mutationFn: async (productoId) => api.put(`/productos/${productoId}`, { categoria_id: null }),
    onSuccess: () => {
      toast.success("Producto quitado");
      refetchProductosCategoria();
      queryClient.invalidateQueries({ queryKey: ["productos"] });
    },
    onError: (error) => toast.error(error.response?.data?.message || "Error al quitar producto"),
  });

  const handleOpenProductos = (categoria) => {
    setCategoriaProductos(categoria);
    setProductosDialogOpen(true);
    setSearchProducto("");
  };

  const handleCloseProductos = () => {
    setProductosDialogOpen(false);
    setCategoriaProductos(null);
  };

  const ctx = {
    expanded, setExpanded, isMobile,
    handleOpenProductos, handleOpenCreate, handleOpenEdit,
    canCreate, canEdit, canDelete, toggleMutation, deleteMutation,
  };

  if (!canRead) {
    return <AccesoRestringido mensaje="No tienes permisos para ver las categorías." />;
  }
  if (errorModulo) {
    return <AccesoRestringido titulo="Módulo no disponible" mensaje={errorModulo} />;
  }

  const totalRoots = tree.length;
  const totalVisible = filteredTree.length;

  return (
    <Wrapper>
      <ScreenGuia
        titulo="¿Cómo funcionan las Categorías?"
        intro="Organizá tus productos en una jerarquía. Las categorías raíz agrupan grandes familias; las subcategorías refinan."
        pasos={GUIA_PASOS}
      />

      <SectionBar>
        <div className="title-block">
          <Icon icon="lucide:layers" width={22} />
          <div>
            <div className="title">Categorías</div>
            <div className="subtitle">
              {search
                ? `${totalVisible} resultado${totalVisible === 1 ? "" : "s"} de ${totalRoots} raíces`
                : totalVisible === totalRoots
                  ? `${totalRoots} categoría${totalRoots === 1 ? "" : "s"} raíz`
                  : // Con un rubro activo se esconden las de otros rubros: se
                    // dice cuántas, para que nadie crea que se perdieron.
                    `${totalVisible} de ${totalRoots} categorías raíz · el resto es de otro rubro`}
            </div>
          </div>
        </div>
        {canCreate && (
          <PrimaryBtn onClick={() => handleOpenCreate()}>
            <Icon icon="lucide:plus" /> Nueva Categoría
          </PrimaryBtn>
        )}
      </SectionBar>

      <Toolbar>
        <SearchWrap>
          <Icon icon="lucide:search" width={16} />
          <input
            placeholder="Buscar categoría..."
            value={search}
            onChange={(e) => setSearch(e.target.value)}
          />
        </SearchWrap>
        <GhostBtn onClick={expandAll} disabled={!tree.length}>
          <Icon icon="lucide:chevrons-down" /> Expandir todo
        </GhostBtn>
        <GhostBtn onClick={collapseAll} disabled={!Object.keys(expanded).length}>
          <Icon icon="lucide:chevrons-up" /> Colapsar todo
        </GhostBtn>
      </Toolbar>

      {isLoading ? (
        <TreeBox>
          {[...Array(6)].map((_, i) => (
            <Skeleton key={i} variant="rectangular" height={44} sx={{ mb: 0.5, borderRadius: 1 }} />
          ))}
        </TreeBox>
      ) : filteredTree.length === 0 ? (
        search ? (
          <EmptyState
            icon="lucide:search-x"
            title="Sin coincidencias"
            description={`Ninguna categoría coincide con "${search}".`}
          />
        ) : totalRoots > 0 ? (
          <EmptyState
            icon="lucide:layers"
            title="Ninguna categoría de este rubro"
            description={`Hay ${totalRoots} categoría${totalRoots === 1 ? "" : "s"} cargada${totalRoots === 1 ? "" : "s"}, pero pertenecen a otro rubro. Cambiá a "Todos los rubros" en el panel lateral para verlas.`}
            ctaLabel={canCreate ? "Nueva Categoría" : undefined}
            ctaIcon="lucide:plus"
            onCta={canCreate ? () => handleOpenCreate() : undefined}
          />
        ) : (
          <EmptyState
            icon="lucide:layers"
            title="Aún no hay categorías"
            description="Creá tu primera categoría raíz para empezar a organizar productos."
            ctaLabel={canCreate ? "Nueva Categoría" : undefined}
            ctaIcon="lucide:plus"
            onCta={canCreate ? () => handleOpenCreate() : undefined}
          />
        )
      ) : (
        <TreeBox>
          {filteredTree.map((categoria) => (
            <CategoriaNode key={categoria.id} categoria={categoria} level={0} ctx={ctx} />
          ))}
        </TreeBox>
      )}

      {/* Dialog crear/editar */}
      <Dialog
        open={formDialogOpen}
        onClose={handleCloseForm}
        maxWidth="xs"
        fullWidth
        fullScreen={isMobile}
        PaperProps={{ sx: { borderRadius: 2 } }}
      >
        <DialogTitle sx={{ display: "flex", alignItems: "center", gap: 1.25 }}>
          <Box
            sx={{
              width: "2.2rem", height: "2.2rem", borderRadius: "10px",
              bgcolor: "action.hover", display: "flex", alignItems: "center", justifyContent: "center",
              color: "primary.main", flexShrink: 0,
            }}
          >
            <Icon icon={formMode === "create" ? "lucide:layers" : "lucide:edit-3"} width={20} />
          </Box>
          <Box sx={{ flex: 1, minWidth: 0 }}>
            <Typography variant="subtitle1" fontWeight={700} lineHeight={1.2}>
              {formMode === "create"
                ? parentCategoria
                  ? "Nueva subcategoría"
                  : "Nueva Categoría"
                : "Editar Categoría"}
            </Typography>
            {parentCategoria && (
              <Typography variant="caption" color="text.secondary">
                Dentro de: <strong>{parentCategoria.descripcion}</strong>
              </Typography>
            )}
          </Box>
          <IconButton onClick={handleCloseForm} size="small">
            <Icon icon="lucide:x" width={18} />
          </IconButton>
        </DialogTitle>
        <DialogContent dividers>
          <TextField
            fullWidth
            size="small"
            label="Descripción"
            placeholder="Ej: Electrónica"
            value={formData.descripcion}
            onChange={(e) => setFormData((prev) => ({ ...prev, descripcion: e.target.value }))}
            sx={{ mt: 1 }}
            autoFocus
          />
          {/* Sólo si la empresa usa rubros. Ver docs/plan-rubros-multi-sucursal.md. */}
          {rubros.length > 0 && (
            <TextField
              select
              fullWidth
              size="small"
              label="Rubro"
              value={formData.rubro_id}
              onChange={(e) => setFormData((prev) => ({ ...prev, rubro_id: e.target.value }))}
              helperText={
                formData.rubro_id
                  ? "Los productos de esta categoría se verán sólo en este rubro."
                  : "Sin rubro: los productos de esta categoría se ven en todos los rubros."
              }
              sx={{ mt: 2.5 }}
            >
              <MenuItem value="">Sin rubro (compartida)</MenuItem>
              {rubros.map((rubro) => (
                <MenuItem key={rubro.id} value={rubro.id}>
                  {rubro.descripcion}
                </MenuItem>
              ))}
            </TextField>
          )}

          <Box sx={{ mt: 2.5 }}>
            <Typography variant="caption" color="text.secondary" sx={{ fontWeight: 700, letterSpacing: 0.5, textTransform: "uppercase" }}>
              Color de identificación
            </Typography>
            <Box sx={{ display: "flex", gap: 1, flexWrap: "wrap", mt: 1 }}>
              {COLORS.map((color) => (
                <Box
                  key={color}
                  onClick={() => setFormData((prev) => ({ ...prev, color }))}
                  sx={{
                    width: 30, height: 30, borderRadius: "50%", backgroundColor: color, cursor: "pointer",
                    border: formData.color === color ? "3px solid #fff" : "2px solid transparent",
                    boxShadow: formData.color === color ? `0 0 0 2px ${color}` : "none",
                    transition: "all 0.15s",
                    "&:hover": { transform: "scale(1.1)" },
                  }}
                />
              ))}
            </Box>
            <Box sx={{ mt: 1.5, display: "flex", alignItems: "center", gap: 1 }}>
              <Typography variant="caption" color="text.secondary">Personalizado:</Typography>
              <input
                type="color"
                value={formData.color}
                onChange={(e) => setFormData((prev) => ({ ...prev, color: e.target.value }))}
                style={{ width: 40, height: 30, border: "none", cursor: "pointer", background: "transparent" }}
              />
              <Chip label={formData.color} size="small" sx={{ bgcolor: formData.color, color: "#fff", fontWeight: 600 }} />
            </Box>
          </Box>
        </DialogContent>
        <DialogActions sx={{ p: 2 }}>
          <Button onClick={handleCloseForm} startIcon={<Icon icon="lucide:x" width={16} />}>Cancelar</Button>
          <Button
            variant="contained"
            onClick={handleSubmit}
            disabled={createMutation.isPending || updateMutation.isPending}
            startIcon={<Icon icon={formMode === "create" ? "lucide:plus" : "lucide:save"} width={16} />}
          >
            {createMutation.isPending || updateMutation.isPending
              ? "Guardando..."
              : formMode === "create" ? "Crear" : "Guardar"}
          </Button>
        </DialogActions>
      </Dialog>

      {/* Dialog productos */}
      <Dialog
        open={productosDialogOpen}
        onClose={handleCloseProductos}
        maxWidth="md"
        fullWidth
        fullScreen={isMobile}
        PaperProps={{ sx: { borderRadius: 2 } }}
      >
        <DialogTitle sx={{ display: "flex", alignItems: "center", gap: 1.25 }}>
          <Box
            sx={{
              width: "2.2rem", height: "2.2rem", borderRadius: "10px",
              bgcolor: "action.hover", display: "flex", alignItems: "center", justifyContent: "center",
              color: "primary.main", flexShrink: 0,
            }}
          >
            <Icon icon="lucide:package" width={20} />
          </Box>
          <Box sx={{ flex: 1, minWidth: 0 }}>
            <Typography variant="subtitle1" fontWeight={700} lineHeight={1.2}>
              Productos de {categoriaProductos?.descripcion}
            </Typography>
            <Typography variant="caption" color="text.secondary">
              {productosCategoria.length} producto{productosCategoria.length === 1 ? "" : "s"} asignado{productosCategoria.length === 1 ? "" : "s"}
            </Typography>
          </Box>
          <IconButton onClick={handleCloseProductos} size="small">
            <Icon icon="lucide:x" width={18} />
          </IconButton>
        </DialogTitle>
        <DialogContent dividers>
          <Box sx={{ mb: 2 }}>
            <Typography variant="caption" color="text.secondary" sx={{ fontWeight: 700, letterSpacing: 0.5, textTransform: "uppercase" }}>
              Agregar producto
            </Typography>
            <Autocomplete
              size="small"
              sx={{ mt: 1 }}
              options={productosSearch.filter((p) => p.categoria_id !== categoriaProductos?.id)}
              getOptionLabel={(option) => `${option.cod_producto || ""} - ${option.descripcion}`}
              loading={searchingProductos}
              inputValue={searchProducto}
              onInputChange={(_, value) => setSearchProducto(value)}
              onChange={(_, producto) => {
                if (producto && categoriaProductos) {
                  asignarProductoMutation.mutate({ productoId: producto.id, categoriaId: categoriaProductos.id });
                  setSearchProducto("");
                }
              }}
              renderInput={(params) => (
                <TextField
                  {...params}
                  placeholder="Escribí al menos 2 caracteres..."
                  InputProps={{
                    ...params.InputProps,
                    startAdornment: <Icon icon="lucide:search" width={16} style={{ marginLeft: 6, opacity: 0.5 }} />,
                  }}
                />
              )}
              noOptionsText={searchProducto.length < 2 ? "Escribí para buscar" : "Sin resultados"}
            />
          </Box>

          {productosCategoria.length === 0 ? (
            <EmptyState
              icon="lucide:package-x"
              title="Sin productos en esta categoría"
              description="Buscá un producto arriba para asignarlo."
              compact
            />
          ) : (
            <List dense sx={{ maxHeight: 400, overflow: "auto" }}>
              {productosCategoria.map((producto) => (
                <ListItem
                  key={producto.id}
                  sx={{
                    bgcolor: "background.paper",
                    mb: 0.5, borderRadius: 1.5,
                    border: "1px solid", borderColor: "divider",
                  }}
                >
                  <ListItemText
                    primary={producto.descripcion}
                    secondary={
                      <Box sx={{ display: "flex", gap: 0.75, mt: 0.5, flexWrap: "wrap" }}>
                        {producto.cod_producto && (
                          <Chip label={producto.cod_producto} size="small" variant="outlined" />
                        )}
                        <Chip
                          label={`${Number(producto.precio || 0).toLocaleString("es-PY")} Gs.`}
                          size="small"
                          color="primary"
                          variant="outlined"
                        />
                      </Box>
                    }
                  />
                  <ListItemSecondaryAction>
                    <Tooltip title="Quitar de esta categoría">
                      <IconButton edge="end" size="small" color="error" onClick={() => quitarProductoMutation.mutate(producto.id)}>
                        <Icon icon="lucide:minus-circle" width={18} />
                      </IconButton>
                    </Tooltip>
                  </ListItemSecondaryAction>
                </ListItem>
              ))}
            </List>
          )}
        </DialogContent>
        <DialogActions sx={{ p: 2 }}>
          <Button onClick={handleCloseProductos} variant="contained" startIcon={<Icon icon="lucide:check" width={16} />}>
            Listo
          </Button>
        </DialogActions>
      </Dialog>
    </Wrapper>
  );
}
