import { useState, useRef } from 'react'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import toast from 'react-hot-toast'
import client from '../../api/client'
import { ConfirmModal } from '../../ui/Modal'
import ProductFormModal from './ProductFormModal'

// ── Icons ─────────────────────────────────────────────────────────────────────
function Icon({ name, size = 14, className = '' }) {
  const paths = {
    chevronRight: <path d="M9 6l6 6-6 6" />,
    chevronDown:  <path d="M6 9l6 6 6-6" />,
    edit:         <><path d="M12 20h9" /><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z" /></>,
    trash:        <><path d="M3 6h18" /><path d="M8 6V4h8v2M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" /></>,
    plus:         <><path d="M12 5v14" /><path d="M5 12h14" /></>,
    grip:         <><circle cx="9" cy="6" r="1" /><circle cx="15" cy="6" r="1" /><circle cx="9" cy="12" r="1" /><circle cx="15" cy="12" r="1" /><circle cx="9" cy="18" r="1" /><circle cx="15" cy="18" r="1" /></>,
    search:       <><circle cx="11" cy="11" r="7" /><path d="M21 21l-4.3-4.3" /></>,
    x:            <><path d="M18 6L6 18" /><path d="M6 6l12 12" /></>,
    image:        <><rect x="3" y="3" width="18" height="18" rx="2" /><circle cx="8.5" cy="8.5" r="1.5" /><path d="M21 15l-5-5L5 21" /></>,
    grid:         <><rect x="3" y="3" width="7" height="7" rx="1" /><rect x="14" y="3" width="7" height="7" rx="1" /><rect x="3" y="14" width="7" height="7" rx="1" /><rect x="14" y="14" width="7" height="7" rx="1" /></>,
    list:         <><line x1="8" y1="6" x2="21" y2="6" /><line x1="8" y1="12" x2="21" y2="12" /><line x1="8" y1="18" x2="21" y2="18" /><circle cx="3.5" cy="6" r="1" /><circle cx="3.5" cy="12" r="1" /><circle cx="3.5" cy="18" r="1" /></>,
    filter:       <path d="M3 4h18l-7 9v6l-4 2v-8L3 4z" />,
    archive:      <><path d="M21 8v13H3V8" /><path d="M1 3h22v5H1z" /><path d="M10 12h4" /></>,
    check:        <path d="M20 6L9 17l-5-5" />,
    eye:          <><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" /><circle cx="12" cy="12" r="3" /></>,
    eyeOff:       <><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24" /><line x1="1" y1="1" x2="23" y2="23" /></>,
    folder:       <path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />,
    chevronsDown: <><path d="M7 6l5 5 5-5" /><path d="M7 13l5 5 5-5" /></>,
    move:         <><path d="M5 9l-3 3 3 3M9 5l3-3 3 3M15 19l-3 3-3-3M19 9l3 3-3 3M2 12h20M12 2v20" /></>,
    arrowRight:   <><path d="M5 12h14" /><path d="M12 5l7 7-7 7" /></>,
  }
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor"
      strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}>
      {paths[name]}
    </svg>
  )
}

// ── Helpers ───────────────────────────────────────────────────────────────────
const EMPTY_PRODUCT = {
  name: '', category_id: '', base_price: '', is_available: true, lifecycle_status: 'active',
  description: '', quick_options: [], options: [], ingredients: [], preference_sets: [],
  is_service_item: false,
}

function catColor(cat) { return cat?.color || '#94a3b8' }

function PhotoThumb({ product, size = 44 }) {
  if (product.image_url) {
    return (
      <img
        src={product.image_url}
        alt={product.name}
        style={{ width: size, height: size }}
        className="rounded-lg object-cover shrink-0 border border-gray-100"
      />
    )
  }
  const h = [...(product.name || '?')].reduce((a, c) => a + c.charCodeAt(0), 0) % 360
  return (
    <div
      style={{ width: size, height: size, background: `linear-gradient(135deg, hsl(${h},55%,72%), hsl(${(h+30)%360},55%,62%))` }}
      className="rounded-lg shrink-0 flex items-center justify-center text-white font-semibold text-sm select-none"
    >
      {(product.name || '?').trim()[0].toUpperCase()}
    </div>
  )
}

// ── Drop indicator line ───────────────────────────────────────────────────────
function DropLine() {
  return (
    <div style={{
      height: 2,
      background: '#3b82f6',
      borderRadius: 2,
      margin: '2px 0',
      boxShadow: '0 0 0 2px rgba(59,130,246,0.25)',
      pointerEvents: 'none',
    }} />
  )
}

// ── Category Panel ────────────────────────────────────────────────────────────
function CategoryPanel({ categories, products, selectedCat, onSelect, onEdit, onDelete, onAdd, onReorder, onReorderSub, onToggleExpanded, onReparent }) {
  const [query, setQuery] = useState('')
  const [expanded, setExpanded] = useState(() => new Set(categories.filter(c => !c.parent_id).map(c => c.id)))
  const dragId = useRef(null)
  const [dropTarget, setDropTarget] = useState(null) // { id, level, parentId }
  const [reparentCat, setReparentCat] = useState(null) // category being reparented

  function toggle(id) {
    setExpanded(prev => { const n = new Set(prev); n.has(id) ? n.delete(id) : n.add(id); return n })
  }

  function countFor(catId) {
    const cat = categories.find(c => c.id === catId)
    if (!cat) return 0
    if (!cat.parent_id) {
      const childIds = categories.filter(c => c.parent_id === catId).map(c => c.id)
      return products.filter(p => p.lifecycle_status !== 'archived' && (p.category_id === catId || childIds.includes(p.category_id))).length
    }
    return products.filter(p => p.lifecycle_status !== 'archived' && p.category_id === catId).length
  }

  const topLevel = categories
    .filter(c => !c.parent_id)
    .sort((a, b) => a.sort_order - b.sort_order)
    .filter(c => !query.trim() || c.name.toLowerCase().includes(query.toLowerCase()) ||
      categories.filter(sc => sc.parent_id === c.id).some(sc => sc.name.toLowerCase().includes(query.toLowerCase())))

  const totalActive = products.filter(p => p.lifecycle_status !== 'archived').length
  const totalArchived = products.filter(p => p.lifecycle_status === 'archived').length
  const uncategorized = products.filter(p => p.lifecycle_status !== 'archived' && !p.category_id).length

  function onDragStart(id, level, parentId) {
    return e => {
      dragId.current = { id, level, parentId }
      e.dataTransfer.effectAllowed = 'move'
    }
  }
  function onDragOver(id, level, parentId) {
    return e => {
      e.preventDefault()
      e.dataTransfer.dropEffect = 'move'
      if (!dragId.current || dragId.current.id === id) return
      setDropTarget({ id, level, parentId })
    }
  }
  function onDragLeave() {
    setDropTarget(null)
  }
  function onDrop(targetId, level, parentId) {
    return e => {
      e.preventDefault()
      setDropTarget(null)
      if (!dragId.current || dragId.current.id === targetId) { dragId.current = null; return }
      if (dragId.current.level === 'top' && level === 'top') {
        onReorder(dragId.current.id, targetId)
      } else if (dragId.current.level === 'sub' && level === 'sub' && dragId.current.parentId === parentId) {
        onReorderSub(dragId.current.id, targetId, parentId)
      }
      dragId.current = null
    }
  }

  return (
    <aside style={{ width: 400, minWidth: 400, borderRight: '1px solid #e5e7eb', display: 'flex', flexDirection: 'column', minHeight: 0, overflow: 'hidden' }}>
      {/* Header */}
      <div style={{ padding: '14px 24px 8px', display: 'flex', alignItems: 'center', justifyContent: 'space-between', flexShrink: 0 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 7, fontSize: 13, fontWeight: 600, color: '#374151' }}>
          <Icon name="folder" size={14} />
          Κατηγορίες
        </div>
        <button onClick={() => onAdd(null)} title="Νέα κατηγορία"
          style={{ border: '1px solid #e5e7eb', background: '#fff', width: 26, height: 26, borderRadius: 6, display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#374151', cursor: 'pointer' }}>
          <Icon name="plus" size={13} />
        </button>
      </div>

      {/* Search */}
      <div style={{ margin: '0 24px 8px', position: 'relative', display: 'flex', alignItems: 'center', background: '#fff', border: '1px solid #e5e7eb', borderRadius: 8, padding: '0 10px' }}>
        <Icon name="search" size={13} className="text-gray-400 shrink-0" />
        <input
          value={query} onChange={e => setQuery(e.target.value)}
          placeholder="Αναζήτηση κατηγορίας…"
          style={{ flex: 1, border: 0, background: 'transparent', padding: '7px 6px', fontSize: 13, outline: 'none', color: '#111827' }}
        />
        {query && (
          <button onClick={() => setQuery('')} style={{ border: 0, background: 'transparent', cursor: 'pointer', color: '#9ca3af', display: 'flex', padding: 2 }}>
            <Icon name="x" size={12} />
          </button>
        )}
      </div>

      {/* Tree */}
      <div style={{ flex: 1, overflowY: 'auto', padding: '4px 24px' }}>
        {/* Service items — permanent, always first */}
        <CatRow
          label="Service"
          count={products.filter(p => p.is_service_item && p.lifecycle_status !== 'archived').length}
          isSelected={selectedCat === '__service__'}
          onClick={() => onSelect('__service__')}
          dotColor="#f59e0b"
          isService
        />
        {/* All */}
        <CatRow
          label="Όλα τα προϊόντα" count={totalActive}
          isSelected={selectedCat === null}
          onClick={() => onSelect(null)}
          dotColor="linear-gradient(135deg,#10b981,#0ea5e9)"
          dotIsGradient
        />

        {topLevel.map((cat, idx) => {
          const subs = categories.filter(c => c.parent_id === cat.id).sort((a, b) => a.sort_order - b.sort_order)
          const isOpen = expanded.has(cat.id) || !!query.trim()
          const isDropHere = dropTarget?.id === cat.id && dropTarget?.level === 'top'
          return (
            <div key={cat.id}>
              <div
                draggable
                onDragStart={onDragStart(cat.id, 'top', null)}
                onDragOver={onDragOver(cat.id, 'top', null)}
                onDragLeave={onDragLeave}
                onDrop={onDrop(cat.id, 'top', null)}
              >
                <CatRow
                  label={cat.name}
                  count={countFor(cat.id)}
                  isSelected={selectedCat === cat.id}
                  onClick={() => onSelect(cat.id)}
                  dotColor={catColor(cat)}
                  isParent={subs.length > 0}
                  isOpen={isOpen}
                  onToggle={() => toggle(cat.id)}
                  onEdit={() => onEdit(cat)}
                  onDelete={() => onDelete(cat)}
                  onAddChild={() => onAdd(cat.id)}
                  onReparent={() => setReparentCat(cat)}
                  showDrag
                />
              </div>

              {isOpen && subs.map((sub) => {
                const isSubDropHere = dropTarget?.id === sub.id && dropTarget?.level === 'sub' && dropTarget?.parentId === cat.id
                return (
                  <div key={sub.id}>
                    <div
                      draggable
                      onDragStart={onDragStart(sub.id, 'sub', cat.id)}
                      onDragOver={onDragOver(sub.id, 'sub', cat.id)}
                      onDragLeave={onDragLeave}
                      onDrop={onDrop(sub.id, 'sub', cat.id)}
                    >
                      <CatRow
                        label={sub.name}
                        count={countFor(sub.id)}
                        isSelected={selectedCat === sub.id}
                        onClick={() => onSelect(sub.id)}
                        dotColor={catColor(sub)}
                        depth={1}
                        onEdit={() => onEdit(sub)}
                        onDelete={() => onDelete(sub)}
                        onReparent={() => setReparentCat(sub)}
                        showDrag
                      />
                    </div>
                    {isSubDropHere && <div style={{ paddingLeft: 16 }}><DropLine /></div>}
                  </div>
                )
              })}
              {isDropHere && <DropLine />}
            </div>
          )
        })}
      </div>

      {/* Footer */}
      <div style={{ borderTop: '1px solid #e5e7eb', padding: '6px 24px', flexShrink: 0 }}>
        <CatFooterRow
          icon="filter" label="Χωρίς κατηγορία" count={uncategorized}
          isSelected={selectedCat === '__uncategorized__'}
          onClick={() => onSelect('__uncategorized__')}
        />
        <CatFooterRow
          icon="archive" label="Αρχειοθετημένα" count={totalArchived}
          isSelected={selectedCat === '__archived__'}
          onClick={() => onSelect('__archived__')}
        />
      </div>

      {reparentCat && (
        <ReparentModal
          cat={reparentCat}
          categories={categories}
          onClose={() => setReparentCat(null)}
          onConfirm={newParentId => {
            onReparent(reparentCat.id, newParentId)
            setReparentCat(null)
          }}
        />
      )}
    </aside>
  )
}

function CatRow({ label, count, isSelected, onClick, dotColor, dotIsGradient, isParent, isOpen, onToggle, onEdit, onDelete, onAddChild, onReparent, depth = 0, showDrag, isService }) {
  const bg = isSelected ? '#eff6ff' : 'transparent'
  const accent = isSelected ? '#3b82f6' : 'transparent'
  return (
    <div
      onClick={onClick}
      style={{
        display: 'flex', alignItems: 'center', gap: 5,
        paddingLeft: depth * 16, paddingRight: 0,
        paddingTop: 6, paddingBottom: 6,
        borderRadius: 8, cursor: 'pointer',
        background: bg, position: 'relative',
        marginBottom: 1,
        borderLeft: `3px solid ${accent}`,
      }}
      className="group hover:bg-gray-100"
    >
      {/* Drag handle */}
      {showDrag && (
        <span style={{ color: '#d1d5db', cursor: 'grab', display: 'flex', flexShrink: 0 }}>
          <Icon name="grip" size={13} />
        </span>
      )}

      {/* Caret for parents */}
      {isParent ? (
        <button
          onClick={e => { e.stopPropagation(); onToggle?.() }}
          style={{ border: 0, background: 'transparent', color: '#9ca3af', display: 'flex', cursor: 'pointer', padding: 1, flexShrink: 0 }}
        >
          <Icon name={isOpen ? 'chevronDown' : 'chevronRight'} size={13} />
        </button>
      ) : (
        <span style={{ width: 15, flexShrink: 0 }} />
      )}

      {/* Color dot or service icon */}
      {isService ? (
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#f59e0b" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0 }}>
          <path d="M3 11l19-9-9 19-2-8-8-2z"/>
        </svg>
      ) : (
        <span style={{
          width: 8, height: 8, borderRadius: '50%', flexShrink: 0,
          ...(dotIsGradient ? { background: dotColor } : { backgroundColor: dotColor }),
        }} />
      )}

      {/* Name */}
      <span style={{ flex: 1, fontSize: 13.5, fontWeight: isSelected ? 600 : 500, color: isService ? '#b45309' : '#111827', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', minWidth: 0 }}>
        {label}
      </span>

      {/* Actions — hidden, show on hover */}
      {(onEdit || onDelete || onAddChild || onReparent) && (
        <div
          style={{ display: 'flex', gap: 1, flexShrink: 0, transition: 'opacity 120ms' }}
          className="opacity-0 group-hover:opacity-100"
          onClick={e => e.stopPropagation()}
        >
          {onAddChild && (
            <CatActionBtn title="Νέα υποκατηγορία" onClick={onAddChild}>
              <Icon name="plus" size={12} />
            </CatActionBtn>
          )}
          {onReparent && (
            <CatActionBtn title="Μετακίνηση κατηγορίας" onClick={onReparent}>
              <Icon name="arrowRight" size={12} />
            </CatActionBtn>
          )}
          {onEdit && (
            <CatActionBtn title="Επεξεργασία" onClick={onEdit}>
              <Icon name="edit" size={12} />
            </CatActionBtn>
          )}
          {onDelete && (
            <CatActionBtn title="Διαγραφή" onClick={onDelete} danger>
              <Icon name="trash" size={12} />
            </CatActionBtn>
          )}
        </div>
      )}

      {/* Count — far right, always visible */}
      <span style={{ fontSize: 11, color: '#9ca3af', background: '#e5e7eb', padding: '1px 6px', borderRadius: 999, fontVariantNumeric: 'tabular-nums', flexShrink: 0 }}>
        {count}
      </span>
    </div>
  )
}

function CatActionBtn({ onClick, title, danger, children }) {
  return (
    <button
      onClick={onClick} title={title}
      style={{ border: 0, background: 'transparent', width: 22, height: 22, borderRadius: 5, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', color: danger ? '#ef4444' : '#6b7280' }}
      className={danger ? 'hover:bg-red-50' : 'hover:bg-gray-200'}
    >
      {children}
    </button>
  )
}

function ReparentModal({ cat, categories, onClose, onConfirm }) {
  // Build options: top-level categories (excluding self and its own children),
  // plus a special "— Make top-level —" option.
  const selfIds = new Set([cat.id, ...categories.filter(c => c.parent_id === cat.id).map(c => c.id)])
  const options = categories
    .filter(c => !c.parent_id && !selfIds.has(c.id))
    .sort((a, b) => a.sort_order - b.sort_order)

  const [target, setTarget] = useState('__top__')

  return (
    <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.4)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 60, padding: 16 }}>
      <div style={{ background: '#fff', borderRadius: 16, boxShadow: '0 20px 60px rgba(0,0,0,0.15)', width: '100%', maxWidth: 360, padding: 24 }}>
        <h2 style={{ margin: '0 0 4px', fontWeight: 700, fontSize: 16, color: '#111827' }}>Μετακίνηση κατηγορίας</h2>
        <p style={{ margin: '0 0 16px', fontSize: 12, color: '#9ca3af' }}>
          Κατηγορία: <strong style={{ color: '#374151' }}>{cat.name}</strong>
        </p>
        <label style={{ fontSize: 12, fontWeight: 600, color: '#6b7280', display: 'block', marginBottom: 6 }}>
          Νέα θέση
        </label>
        <select
          value={target}
          onChange={e => setTarget(e.target.value)}
          style={{ width: '100%', border: '1px solid #e5e7eb', borderRadius: 8, padding: '8px 10px', fontSize: 13, outline: 'none', color: '#111827', marginBottom: 20 }}
        >
          <option value="__top__">— Κορυφαίο επίπεδο (ανεξάρτητη) —</option>
          {options.map(c => (
            <option key={c.id} value={String(c.id)}>{c.name}</option>
          ))}
        </select>
        <div style={{ display: 'flex', gap: 8 }}>
          <button onClick={onClose}
            style={{ flex: 1, padding: '9px 0', border: '1px solid #e5e7eb', background: '#fff', borderRadius: 8, fontSize: 14, cursor: 'pointer', color: '#374151' }}>
            Άκυρο
          </button>
          <button
            onClick={() => onConfirm(target === '__top__' ? null : parseInt(target, 10))}
            style={{ flex: 1, padding: '9px 0', border: 'none', background: '#111827', color: '#fff', borderRadius: 8, fontSize: 14, fontWeight: 600, cursor: 'pointer' }}>
            Μετακίνηση
          </button>
        </div>
      </div>
    </div>
  )
}

function CatFooterRow({ icon, label, count, isSelected, onClick }) {
  return (
    <button
      onClick={onClick}
      style={{
        display: 'flex', alignItems: 'center', gap: 8,
        width: '100%', border: 0, background: isSelected ? '#e5e7eb' : 'transparent',
        borderRadius: 8, padding: '7px 10px', cursor: 'pointer', color: '#6b7280', fontSize: 13, textAlign: 'left',
      }}
      className="hover:bg-gray-100"
    >
      <Icon name={icon} size={13} />
      <span style={{ flex: 1 }}>{label}</span>
      <span style={{ fontSize: 11, color: '#9ca3af' }}>{count}</span>
    </button>
  )
}

// ── Products Panel Header ─────────────────────────────────────────────────────
function ProductsHeader({ title, visibleCount, totalCount, search, setSearch, view, setView, priceMin, setPriceMin, priceMax, setPriceMax, dataQualityFilter, setDataQualityFilter, showUnavailable, setShowUnavailable, showArchived, setShowArchived, onNew }) {
  const [filtersOpen, setFiltersOpen] = useState(false)
  const hasFilter = priceMin !== '' || priceMax !== '' || dataQualityFilter !== 'all' || showUnavailable || showArchived

  function clearFilters() {
    setZoneFilter('all')
    setPriceMin('')
    setPriceMax('')
    setDataQualityFilter('all')
    setShowUnavailable(false)
    setShowArchived(false)
  }

  // Shared height token: all toolbar controls are h-8 (32px)
  const H = 36
  const btnBase = {
    display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
    height: H, borderRadius: 6, fontSize: 12, fontWeight: 500, cursor: 'pointer',
    gap: 5, whiteSpace: 'nowrap', flexShrink: 0,
  }
  const btnSecondary = { ...btnBase, padding: '0 10px', background: '#fff', border: '1px solid #e2e8f0', color: '#334155' }
  const btnPrimary   = { ...btnBase, padding: '0 10px', background: '#0ea5e9', border: 'none', color: '#fff' }
  const btnActive    = { ...btnBase, padding: '0 10px', background: '#0f172a', border: 'none', color: '#fff' }

  return (
    <div style={{ borderBottom: '1px solid #e5e7eb', padding: '0 24px', height: 60, display: 'flex', alignItems: 'center', gap: 8, flexShrink: 0, position: 'relative' }}>
      {/* Title + count */}
      <span style={{ fontSize: 13, fontWeight: 600, color: '#111827', whiteSpace: 'nowrap', flexShrink: 0 }}>
        {title}
      </span>
      <span style={{ fontSize: 11, color: '#94a3b8', background: '#f1f5f9', padding: '1px 7px', borderRadius: 999, flexShrink: 0 }}>
        {visibleCount}/{totalCount}
      </span>

      {/* Search — fills remaining space */}
      <div style={{ flex: 1, display: 'flex', alignItems: 'center', gap: 6, height: H, background: '#fff', border: '1px solid #e2e8f0', borderRadius: 6, padding: '0 10px', minWidth: 0 }}>
        <Icon name="search" size={13} className="text-gray-400 shrink-0" />
        <input
          value={search} onChange={e => setSearch(e.target.value)}
          placeholder="Αναζήτηση…"
          style={{ flex: 1, border: 0, background: 'transparent', outline: 'none', fontSize: 12, color: '#111827', minWidth: 0 }}
        />
        {search && (
          <button onClick={() => setSearch('')} style={{ border: 0, background: 'transparent', cursor: 'pointer', color: '#94a3b8', display: 'flex', padding: 0, flexShrink: 0 }}>
            <Icon name="x" size={11} />
          </button>
        )}
      </div>

      {/* Filters toggle */}
      <button
        onClick={() => setFiltersOpen(v => !v)}
        style={filtersOpen ? btnActive : { ...btnSecondary, color: hasFilter ? '#0ea5e9' : '#334155', borderColor: hasFilter ? '#bae6fd' : '#e2e8f0' }}
      >
        <Icon name="filter" size={12} />
        Φίλτρα
        {hasFilter && <span style={{ width: 5, height: 5, borderRadius: '50%', background: filtersOpen ? '#fff' : '#0ea5e9', flexShrink: 0 }} />}
      </button>

      {/* View toggle */}
      <div style={{ display: 'flex', height: H, border: '1px solid #e2e8f0', borderRadius: 6, overflow: 'hidden', flexShrink: 0 }}>
        {[['list', 'list', 'Λίστα'], ['grid', 'grid', 'Πλέγμα']].map(([v, icon, label]) => (
          <button key={v} onClick={() => setView(v)} title={label}
            style={{
              border: 0, borderRight: v === 'list' ? '1px solid #e2e8f0' : 'none',
              background: view === v ? '#0f172a' : 'transparent',
              color: view === v ? '#fff' : '#64748b',
              width: 32, cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}>
            <Icon name={icon} size={13} />
          </button>
        ))}
      </div>

      {/* New product */}
      <button onClick={onNew} style={btnPrimary}>
        <Icon name="plus" size={12} />
        Νέο προϊόν
      </button>

      {filtersOpen && (
        <div style={{
          position: 'absolute', top: 60, left: 24, right: 24, zIndex: 20,
          padding: '14px 16px', background: '#fff', border: '1px solid #e5e7eb',
          borderRadius: 10, boxShadow: '0 4px 12px rgba(0,0,0,0.08)',
          display: 'flex', flexWrap: 'wrap', gap: 20, alignItems: 'flex-end',
        }}>
          <FilterGroup label="Τιμή €">
            <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
              <input type="number" placeholder="από" value={priceMin} onChange={e => setPriceMin(e.target.value)}
                style={{ width: 72, padding: '6px 8px', border: '1px solid #e5e7eb', borderRadius: 6, background: '#fff', outline: 'none', fontSize: 12 }} />
              <span style={{ color: '#9ca3af' }}>—</span>
              <input type="number" placeholder="έως" value={priceMax} onChange={e => setPriceMax(e.target.value)}
                style={{ width: 72, padding: '6px 8px', border: '1px solid #e5e7eb', borderRadius: 6, background: '#fff', outline: 'none', fontSize: 12 }} />
            </div>
          </FilterGroup>
          <FilterGroup label="Ποιότητα δεδομένων">
            <SegControl value={dataQualityFilter} onChange={setDataQualityFilter}
              options={[{ v: 'all', l: 'Όλα' }, { v: 'no-photo', l: 'Χωρίς φωτό' }, { v: 'no-cat', l: 'Χωρίς κατηγορία' }]} />
          </FilterGroup>
          <FilterGroup label="Εμφάνιση">
            <div style={{ display: 'flex', gap: 6 }}>
              <ToggleBtn label="Μη διαθέσιμα" active={showUnavailable} onChange={setShowUnavailable} />
              <ToggleBtn label="Αρχειοθετημένα" active={showArchived} onChange={setShowArchived} />
            </div>
          </FilterGroup>
          <div style={{ marginLeft: 'auto', alignSelf: 'flex-end' }}>
            {hasFilter && (
              <button onClick={clearFilters}
                style={{ display: 'flex', alignItems: 'center', gap: 5, padding: '5px 10px', background: 'transparent', border: '1px solid #fca5a5', color: '#ef4444', borderRadius: 6, fontSize: 12, fontWeight: 500, cursor: 'pointer' }}>
                <Icon name="x" size={11} />
                Καθαρισμός
              </button>
            )}
          </div>
        </div>
      )}
    </div>
  )
}

function FilterGroup({ label, children }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
      <span style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.05em', textTransform: 'uppercase', color: '#9ca3af' }}>{label}</span>
      {children}
    </div>
  )
}

function SegControl({ value, onChange, options }) {
  return (
    <div style={{ display: 'flex', background: '#f3f4f6', border: '1px solid #e5e7eb', borderRadius: 8, padding: 2 }}>
      {options.map(({ v, l }) => (
        <button key={v} onClick={() => onChange(v)}
          style={{ border: 0, background: value === v ? '#fff' : 'transparent', borderRadius: 5, padding: '5px 10px', cursor: 'pointer', color: value === v ? '#111827' : '#6b7280', fontSize: 13, fontWeight: 500, boxShadow: value === v ? '0 1px 2px rgba(0,0,0,0.07)' : 'none' }}>
          {l}
        </button>
      ))}
    </div>
  )
}

function ToggleBtn({ label, active, onChange }) {
  return (
    <button
      onClick={() => onChange(!active)}
      style={{
        padding: '5px 12px', border: `1px solid ${active ? '#111827' : '#e5e7eb'}`,
        background: active ? '#111827' : '#fff',
        color: active ? '#fff' : '#6b7280',
        borderRadius: 7, fontSize: 13, fontWeight: 500, cursor: 'pointer',
      }}
    >
      {label}
    </button>
  )
}

// ── Sub-category chips bar ────────────────────────────────────────────────────
function SubCatBar({ parentCat, subCats, products, subCatFilter, setSubCatFilter }) {
  if (!parentCat || subCats.length === 0) return null
  const allCount = products.filter(p => p.lifecycle_status !== 'archived' && (p.category_id === parentCat.id || subCats.some(s => s.id === p.category_id))).length
  const ownCount = products.filter(p => p.lifecycle_status !== 'archived' && p.category_id === parentCat.id).length

  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, padding: '10px 24px', borderBottom: '1px solid #e5e7eb', flexShrink: 0 }}>
      {[
        { key: null, label: 'Όλα', count: allCount, color: catColor(parentCat) },
        { key: '__own__', label: parentCat.name, count: ownCount, color: catColor(parentCat) },
        ...subCats.map(s => ({ key: s.id, label: s.name, count: products.filter(p => p.lifecycle_status !== 'archived' && p.category_id === s.id).length, color: catColor(s) })),
      ].map(({ key, label, count, color }) => {
        const active = subCatFilter === key
        return (
          <button key={String(key)} onClick={() => setSubCatFilter(key)}
            style={{
              display: 'flex', alignItems: 'center', gap: 6, padding: '5px 10px',
              background: active ? color : '#fff',
              border: `1px solid ${active ? color : '#e5e7eb'}`,
              borderRadius: 999, fontSize: 12.5, fontWeight: 500,
              color: active ? '#fff' : '#374151', cursor: 'pointer',
            }}>
            <span style={{ width: 7, height: 7, borderRadius: '50%', background: active ? 'rgba(255,255,255,0.7)' : color, flexShrink: 0 }} />
            {label}
            <span style={{ fontSize: 11, background: active ? 'rgba(255,255,255,0.2)' : '#e5e7eb', padding: '1px 5px', borderRadius: 999 }}>{count}</span>
          </button>
        )
      })}
    </div>
  )
}

// ── Bulk bar ──────────────────────────────────────────────────────────────────
function BulkBar({ count, onClear, onAvail, onUnavail, onArchive, onSetPrepZone, onMoveToCategory }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', margin: '12px 24px 0', padding: '10px 14px', background: '#111827', color: '#fff', borderRadius: 10, flexShrink: 0 }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
        <button onClick={onClear} style={{ border: 0, background: 'rgba(255,255,255,0.1)', width: 26, height: 26, borderRadius: 6, color: '#fff', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          <Icon name="x" size={13} />
        </button>
        <span style={{ fontSize: 13, fontWeight: 500 }}>{count} επιλεγμένα</span>
      </div>
      <div style={{ display: 'flex', gap: 4, flexWrap: 'wrap' }}>
        {[
          { label: 'Διαθέσιμα', icon: 'eye', action: onAvail },
          { label: 'Μη διαθέσιμα', icon: 'eyeOff', action: onUnavail },
          { label: 'Αρχειοθέτηση', icon: 'archive', action: onArchive },
        ].map(({ label, icon, action }) => (
          <button key={label} onClick={action}
            style={{ border: 0, background: 'transparent', color: 'rgba(255,255,255,0.85)', padding: '6px 10px', borderRadius: 6, fontSize: 13, fontWeight: 500, cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 6 }}
            className="hover:bg-white/10"
          >
            <Icon name={icon} size={13} />
            {label}
          </button>
        ))}
        <div style={{ width: 1, background: 'rgba(255,255,255,0.15)', margin: '4px 2px' }} />
        <button onClick={onSetPrepZone}
          style={{ border: '1px solid rgba(255,255,255,0.2)', background: 'transparent', color: 'rgba(255,255,255,0.85)', padding: '6px 10px', borderRadius: 6, fontSize: 13, fontWeight: 500, cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 6 }}
          className="hover:bg-white/10"
        >
          <Icon name="folder" size={13} />
          Ζώνη Προετοιμασίας
        </button>
        <button onClick={onMoveToCategory}
          style={{ border: '1px solid rgba(255,255,255,0.2)', background: 'transparent', color: 'rgba(255,255,255,0.85)', padding: '6px 10px', borderRadius: 6, fontSize: 13, fontWeight: 500, cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 6 }}
          className="hover:bg-white/10"
        >
          <Icon name="move" size={13} />
          Μετακίνηση
        </button>
      </div>
    </div>
  )
}

// ── Bulk: Set Prep Zone modal ───────────────────────────────────────────────
function BulkSetPrepZoneModal({ count, prepZones, onClose, onConfirm }) {
  const [selectedIds, setSelectedIds] = useState([])
  const toggle = (id) => setSelectedIds(prev => prev.includes(id) ? prev.filter(x => x !== id) : [...prev, id])
  return (
    <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.45)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 60, padding: 16 }}>
      <div style={{ background: '#fff', borderRadius: 16, boxShadow: '0 20px 60px rgba(0,0,0,0.18)', width: '100%', maxWidth: 420, padding: 24 }}>
        <h2 style={{ margin: '0 0 4px', fontWeight: 700, fontSize: 16, color: '#111827' }}>Ζώνες Προετοιμασίας</h2>
        <p style={{ margin: '0 0 18px', fontSize: 13, color: '#6b7280' }}>
          Θα οριστεί σε <strong style={{ color: '#111827' }}>{count}</strong> προϊόντα.
        </p>
        {prepZones.length === 0 ? (
          <p style={{ fontSize: 13, color: '#ef4444', marginBottom: 18 }}>Δεν βρέθηκαν ζώνες προετοιμασίας.</p>
        ) : (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginBottom: 20 }}>
            {prepZones.map(z => {
              const on = selectedIds.includes(z.id)
              return (
                <label key={z.id} onClick={() => toggle(z.id)} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 12px', border: `1.5px solid ${on ? '#3b82f6' : '#e5e7eb'}`, borderRadius: 10, cursor: 'pointer', background: on ? '#eff6ff' : '#fff' }}>
                  <span style={{ width: 16, height: 16, borderRadius: 4, border: `2px solid ${on ? '#3b82f6' : '#d1d5db'}`, background: on ? '#3b82f6' : '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
                    {on && <span style={{ width: 8, height: 8, background: '#fff', borderRadius: 2, display: 'block' }} />}
                  </span>
                  <div>
                    <span style={{ fontSize: 14, fontWeight: 500, color: '#111827' }}>{z.name}</span>
                    {z.description && <span style={{ fontSize: 12, color: '#6b7280', marginLeft: 8 }}>{z.description}</span>}
                  </div>
                </label>
              )
            })}
          </div>
        )}
        <div style={{ display: 'flex', gap: 10 }}>
          <button onClick={onClose} style={{ flex: 1, padding: '9px 0', border: '1px solid #e5e7eb', background: '#fff', borderRadius: 8, fontSize: 14, cursor: 'pointer', color: '#374151' }}>Άκυρο</button>
          <button
            onClick={() => onConfirm(selectedIds)}
            disabled={!selectedIds.length}
            style={{ flex: 1, padding: '9px 0', border: 'none', background: selectedIds.length ? '#111827' : '#d1d5db', color: '#fff', borderRadius: 8, fontSize: 14, fontWeight: 600, cursor: selectedIds.length ? 'pointer' : 'not-allowed' }}
          >
            Εφαρμογή
          </button>
        </div>
      </div>
    </div>
  )
}

// ── Bulk: Move to Category modal ───────────────────────────────────────────────
function BulkMoveToCategoryModal({ count, categories, onClose, onConfirm }) {
  const topLevel = categories.filter(c => !c.parent_id).sort((a, b) => a.sort_order - b.sort_order)
  const [selectedId, setSelectedId] = useState('')
  return (
    <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.45)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 60, padding: 16 }}>
      <div style={{ background: '#fff', borderRadius: 16, boxShadow: '0 20px 60px rgba(0,0,0,0.18)', width: '100%', maxWidth: 400, padding: 24 }}>
        <h2 style={{ margin: '0 0 4px', fontWeight: 700, fontSize: 16, color: '#111827' }}>Μετακίνηση σε κατηγορία</h2>
        <p style={{ margin: '0 0 18px', fontSize: 13, color: '#6b7280' }}>
          Θα μετακινηθούν <strong style={{ color: '#111827' }}>{count}</strong> προϊόντα.
        </p>
        <div style={{ maxHeight: 280, overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: 4, marginBottom: 20 }}>
          {topLevel.map(cat => {
            const subs = categories.filter(c => c.parent_id === cat.id).sort((a, b) => a.sort_order - b.sort_order)
            return (
              <div key={cat.id}>
                <label style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '9px 12px', border: `1.5px solid ${selectedId === cat.id ? cat.color || '#3b82f6' : '#e5e7eb'}`, borderRadius: 9, cursor: 'pointer', background: selectedId === cat.id ? '#f8faff' : '#fff' }}>
                  <input type="radio" name="cat" value={cat.id} checked={selectedId === cat.id} onChange={() => setSelectedId(cat.id)} style={{ display: 'none' }} />
                  <span style={{ width: 10, height: 10, borderRadius: '50%', background: cat.color || '#94a3b8', flexShrink: 0 }} />
                  <span style={{ fontSize: 13.5, fontWeight: 600, color: '#111827', flex: 1 }}>{cat.name}</span>
                  {selectedId === cat.id && <Icon name="check" size={14} className="text-blue-500" />}
                </label>
                {subs.map(sub => (
                  <label key={sub.id} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '8px 12px 8px 28px', border: `1.5px solid ${selectedId === sub.id ? sub.color || '#3b82f6' : '#e5e7eb'}`, borderRadius: 8, cursor: 'pointer', background: selectedId === sub.id ? '#f8faff' : '#fff', marginTop: 3 }}>
                    <input type="radio" name="cat" value={sub.id} checked={selectedId === sub.id} onChange={() => setSelectedId(sub.id)} style={{ display: 'none' }} />
                    <span style={{ width: 7, height: 7, borderRadius: '50%', background: sub.color || '#94a3b8', flexShrink: 0 }} />
                    <span style={{ fontSize: 13, fontWeight: 500, color: '#374151', flex: 1 }}>{sub.name}</span>
                    {selectedId === sub.id && <Icon name="check" size={13} className="text-blue-500" />}
                  </label>
                ))}
              </div>
            )
          })}
        </div>
        <div style={{ display: 'flex', gap: 10 }}>
          <button onClick={onClose} style={{ flex: 1, padding: '9px 0', border: '1px solid #e5e7eb', background: '#fff', borderRadius: 8, fontSize: 14, cursor: 'pointer', color: '#374151' }}>Άκυρο</button>
          <button
            onClick={() => onConfirm(selectedId)}
            disabled={!selectedId}
            style={{ flex: 1, padding: '9px 0', border: 'none', background: selectedId ? '#111827' : '#d1d5db', color: '#fff', borderRadius: 8, fontSize: 14, fontWeight: 600, cursor: selectedId ? 'pointer' : 'not-allowed' }}
          >
            Μετακίνηση
          </button>
        </div>
      </div>
    </div>
  )
}

// ── Product Row (list view) ───────────────────────────────────────────────────
function ProductRow({ p, cat, parentCat, selected, onToggleSelect, onEdit, onArchive, onToggleAvail, anySelected, dragging, dropBefore, dropAfter, onDragStart, onDragOver, onDragLeave, onDrop }) {
  const displayCat = cat || parentCat
  const isArchived = p.lifecycle_status === 'archived'

  return (
    <>
      {dropBefore && <DropLine />}
      <div
        draggable
        onDragStart={onDragStart}
        onDragOver={onDragOver}
        onDragLeave={onDragLeave}
        onDrop={onDrop}
        style={{
          display: 'grid',
          gridTemplateColumns: '18px 24px 44px 1fr auto auto',
          alignItems: 'center',
          gap: 12,
          padding: '8px 12px 8px 8px',
          borderRadius: 8,
          background: selected ? '#eff6ff' : dragging ? '#f0f9ff' : 'transparent',
          position: 'relative',
          borderLeft: selected ? '3px solid #3b82f6' : '3px solid transparent',
          cursor: 'default',
          opacity: dragging ? 0.5 : 1,
        }}
        className="group hover:bg-gray-50"
      >
        {/* Drag grip */}
        <span style={{ color: '#d1d5db', cursor: 'grab', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          <Icon name="grip" size={14} />
        </span>

        {/* Checkbox */}
        <label style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' }} onClick={e => e.stopPropagation()}>
          <input type="checkbox" checked={selected} onChange={() => onToggleSelect(p.id)} style={{ display: 'none' }} />
          <span style={{
            width: 16, height: 16, border: `1.5px solid ${selected ? '#3b82f6' : '#d1d5db'}`,
            borderRadius: 4, background: selected ? '#3b82f6' : '#fff',
            display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
          }}>
            {selected && <Icon name="check" size={10} className="text-white" />}
          </span>
        </label>

        {/* Photo */}
        <PhotoThumb product={p} size={44} />

        {/* Name + meta */}
        <div style={{ minWidth: 0 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 7, minWidth: 0, marginBottom: 3 }}>
            <span style={{ fontWeight: 500, fontSize: 14, color: '#111827', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
              {p.name}
            </span>
            {isArchived && (
              <span style={{ fontSize: 10.5, fontWeight: 600, textTransform: 'uppercase', background: '#f3f4f6', color: '#6b7280', padding: '1px 6px', borderRadius: 4, flexShrink: 0 }}>
                Αρχείο
              </span>
            )}
            {p.is_service_item && !isArchived && (
              <span style={{ fontSize: 10.5, fontWeight: 600, textTransform: 'uppercase', background: '#fef3c7', color: '#b45309', padding: '1px 6px', borderRadius: 4, flexShrink: 0 }}>
                Service
              </span>
            )}
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 12, color: '#6b7280' }}>
            {displayCat && (
              <span style={{ display: 'flex', alignItems: 'center', gap: 4, background: '#f3f4f6', padding: '1px 7px 1px 5px', borderRadius: 999 }}>
                <span style={{ width: 6, height: 6, borderRadius: '50%', background: catColor(displayCat), flexShrink: 0 }} />
                {displayCat.name}
              </span>
            )}
            {p.prep_zone_names?.map(name => (
              <span key={name} style={{ background: '#eff6ff', color: '#1d4ed8', padding: '1px 6px', borderRadius: 4, fontSize: 11 }}>
                {name}
              </span>
            ))}
          </div>
        </div>

        {/* Price + cost/margin */}
        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 2, marginRight: 4, flexShrink: 0 }}>
          <span style={{ fontVariantNumeric: 'tabular-nums', fontWeight: 600, fontSize: 14, color: '#111827', whiteSpace: 'nowrap' }}>
            €{parseFloat(p.base_price).toFixed(2)}
          </span>
          {(() => {
            const effectiveCost = p.cost_breakdown?.length
              ? p.cost_breakdown.reduce((s, e) => s + (e.amount || 0), 0)
              : (p.cost_simple ?? null)
            if (effectiveCost === null) return null
            const price = parseFloat(p.base_price)
            const isError = effectiveCost > price
            const margin = price > 0 ? ((price - effectiveCost) / price * 100) : null
            return (
              <span style={{
                fontSize: 11, fontWeight: 500, whiteSpace: 'nowrap',
                color: isError ? '#ef4444' : '#16a34a',
              }}>
                {isError ? '⚠ κόστος > τιμή' : margin !== null ? `${margin.toFixed(0)}% margin` : null}
              </span>
            )
          })()}
        </div>

        {/* Actions */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 5, flexShrink: 0 }}>
          {/* Availability toggle pill */}
          {!isArchived && (
            <button
              onClick={e => { e.stopPropagation(); onToggleAvail(p) }}
              style={{
                display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 5, padding: '4px 10px',
                minWidth: 120,
                background: p.is_available ? '#f0fdf4' : '#fafafa',
                border: `1px solid ${p.is_available ? '#86efac' : '#e5e7eb'}`,
                borderRadius: 999, fontSize: 11.5, fontWeight: 500,
                color: p.is_available ? '#15803d' : '#6b7280', cursor: 'pointer',
              }}
            >
              <span style={{ width: 7, height: 7, borderRadius: '50%', background: p.is_available ? '#22c55e' : '#9ca3af', flexShrink: 0, display: 'block' }} />
              {p.is_available ? 'Διαθέσιμο' : 'Μη διαθέσιμο'}
            </button>
          )}

          {/* Edit — pill style */}
          <button onClick={e => { e.stopPropagation(); onEdit(p) }}
            style={{
              display: 'flex', alignItems: 'center', gap: 5, padding: '4px 10px',
              background: '#f3f4f6', border: '1px solid #e5e7eb',
              borderRadius: 999, fontSize: 11.5, fontWeight: 500, color: '#374151',
              cursor: 'pointer',
            }}
            className="hover:bg-gray-200"
            title="Επεξεργασία">
            <Icon name="edit" size={13} />
            Επεξεργασία
          </button>

          {/* Delete — icon only, same height as Edit pill */}
          <button onClick={e => { e.stopPropagation(); onArchive(p) }}
            style={{
              display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '0 10px',
              height: 27,
              background: '#fff5f5', border: '1px solid #fecaca',
              borderRadius: 999, fontSize: 11.5, fontWeight: 500, color: '#ef4444',
              cursor: 'pointer',
            }}
            className="hover:bg-red-100"
            title="Διαγραφή">
            <Icon name="trash" size={13} />
          </button>
        </div>
      </div>
      {dropAfter && <DropLine />}
    </>
  )
}

// ── Product Card (grid view) ──────────────────────────────────────────────────
function ProductCard({ p, cat, parentCat, selected, onToggleSelect, onEdit, onArchive, onToggleAvail }) {
  const displayCat = cat || parentCat
  const isArchived = p.lifecycle_status === 'archived'

  return (
    <div style={{
      background: '#fff', border: `1px solid ${selected ? '#3b82f6' : '#e5e7eb'}`,
      borderRadius: 12, overflow: 'hidden', display: 'flex', flexDirection: 'column',
      position: 'relative', boxShadow: selected ? '0 0 0 3px rgba(59,130,246,0.15)' : 'none',
    }}
      className="group hover:border-gray-300 hover:shadow-sm transition-all"
    >
      {/* Photo area */}
      <div style={{ height: 140, position: 'relative', background: '#f3f4f6', display: 'flex', alignItems: 'center', justifyContent: 'center', overflow: 'hidden' }}>
        {p.image_url
          ? <img src={p.image_url} alt={p.name} style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
          : (() => {
              const h = [...(p.name || '?')].reduce((a, c) => a + c.charCodeAt(0), 0) % 360
              return (
                <div style={{ width: '100%', height: '100%', background: `linear-gradient(135deg,hsl(${h},55%,72%),hsl(${(h+30)%360},55%,62%))`, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                  <span style={{ fontSize: 40, fontWeight: 700, color: 'rgba(255,255,255,0.9)' }}>{(p.name || '?').trim()[0].toUpperCase()}</span>
                </div>
              )
            })()
        }

        {/* Top-left: checkbox + edit + archive */}
        <div style={{ position: 'absolute', top: 8, left: 8, display: 'flex', gap: 4, opacity: 0 }} className="group-hover:opacity-100 transition-opacity">
          <label style={{ background: 'rgba(255,255,255,0.92)', backdropFilter: 'blur(4px)', borderRadius: 6, padding: 4, cursor: 'pointer', display: 'flex' }} onClick={e => e.stopPropagation()}>
            <input type="checkbox" checked={selected} onChange={() => onToggleSelect(p.id)} style={{ display: 'none' }} />
            <span style={{ width: 16, height: 16, border: `1.5px solid ${selected ? '#3b82f6' : '#9ca3af'}`, borderRadius: 4, background: selected ? '#3b82f6' : '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              {selected && <Icon name="check" size={10} className="text-white" />}
            </span>
          </label>
          <button onClick={e => { e.stopPropagation(); onEdit(p) }} title="Επεξεργασία"
            style={{ background: 'rgba(255,255,255,0.92)', backdropFilter: 'blur(4px)', border: 0, borderRadius: 6, padding: 4, cursor: 'pointer', color: '#374151', display: 'flex' }}>
            <Icon name="edit" size={14} />
          </button>
          <button onClick={e => { e.stopPropagation(); onArchive(p) }} title="Διαγραφή"
            style={{ background: 'rgba(255,255,255,0.92)', backdropFilter: 'blur(4px)', border: 0, borderRadius: 6, padding: 4, cursor: 'pointer', color: '#ef4444', display: 'flex' }}>
            <Icon name="trash" size={14} />
          </button>
        </div>

        {/* Availability dot top-right */}
        {!isArchived && (
          <button onClick={e => { e.stopPropagation(); onToggleAvail(p) }} title={p.is_available ? 'Διαθέσιμο' : 'Μη διαθέσιμο'}
            style={{ position: 'absolute', top: 8, right: 8, background: 'rgba(255,255,255,0.92)', backdropFilter: 'blur(4px)', border: 0, borderRadius: '50%', padding: 6, cursor: 'pointer', display: 'flex' }}>
            <span style={{ width: 8, height: 8, borderRadius: '50%', background: p.is_available ? '#22c55e' : '#9ca3af' }} />
          </button>
        )}

        {/* Archived badge */}
        {isArchived && (
          <div style={{ position: 'absolute', bottom: 8, left: 8 }}>
            <span style={{ fontSize: 10, fontWeight: 700, textTransform: 'uppercase', background: 'rgba(0,0,0,0.6)', color: '#fff', padding: '2px 6px', borderRadius: 4 }}>Αρχείο</span>
          </div>
        )}
      </div>

      {/* Body */}
      <div style={{ padding: '12px 14px', display: 'flex', flexDirection: 'column', gap: 6, flex: 1 }}>
        <div style={{ fontWeight: 600, fontSize: 14, color: '#111827', letterSpacing: '-0.005em' }}>{p.name}</div>
        {displayCat && (
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4, background: '#f3f4f6', padding: '1px 7px 1px 5px', borderRadius: 999, fontSize: 11.5, color: '#374151', width: 'fit-content' }}>
            <span style={{ width: 6, height: 6, borderRadius: '50%', background: catColor(displayCat) }} />
            {displayCat.name}
          </span>
        )}
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginTop: 4 }}>
          <span style={{ fontVariantNumeric: 'tabular-nums', fontWeight: 700, fontSize: 15, color: '#111827' }}>
            €{parseFloat(p.base_price).toFixed(2)}
          </span>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4 }}>
            {p.prep_zone_names?.map(name => (
              <span key={name} style={{ background: '#eff6ff', color: '#1d4ed8', padding: '1px 6px', borderRadius: 4, fontSize: 11 }}>
                {name}
              </span>
            ))}
          </div>
        </div>
      </div>
    </div>
  )
}

// ── Group header (draggable category separator in list view) ──────────────────
function GroupHeader({ cat, count, isOpen, onToggle, onDragStart, onDragOver, onDragLeave, onDrop, showToggle, dropIndicator }) {
  return (
    <>
      {dropIndicator && <DropLine />}
      <div
        draggable
        onDragStart={onDragStart}
        onDragOver={onDragOver}
        onDragLeave={onDragLeave}
        onDrop={onDrop}
        style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '8px 4px', cursor: 'grab', userSelect: 'none' }}
        title="Σύρετε για αναδιάταξη κατηγορίας"
      >
        <span style={{ color: '#d1d5db', display: 'flex' }}><Icon name="grip" size={13} /></span>
        {cat && <span style={{ width: 8, height: 8, borderRadius: '50%', background: catColor(cat), flexShrink: 0 }} />}
        <span style={{ fontSize: 11.5, fontWeight: 700, letterSpacing: '0.04em', textTransform: 'uppercase', color: '#9ca3af' }}>
          {cat?.name || 'Χωρίς κατηγορία'}
        </span>
        <span style={{ fontSize: 10.5, background: '#e5e7eb', color: '#9ca3af', padding: '1px 6px', borderRadius: 999 }}>{count}</span>
        {showToggle && (
          <button
            onClick={e => { e.stopPropagation(); onToggle?.() }}
            style={{ border: 0, background: 'transparent', cursor: 'pointer', color: '#9ca3af', display: 'flex', padding: 2, marginLeft: 2 }}
            title={isOpen ? 'Σύμπτυξη' : 'Ανάπτυξη'}
          >
            <Icon name={isOpen ? 'chevronDown' : 'chevronRight'} size={13} />
          </button>
        )}
      </div>
    </>
  )
}

// ── Main ProductsTab ──────────────────────────────────────────────────────────
export default function ProductsTab() {
  const qc = useQueryClient()
  const [selectedCat, setSelectedCat] = useState(null)
  const [subCatFilter, setSubCatFilter] = useState(null)
  const [editProduct, setEditProduct] = useState(null)
  const [editCat, setEditCat] = useState(null)
  const [confirmDelete, setConfirmDelete] = useState(null)
  const [search, setSearch] = useState('')
  const [view, setView] = useState('list')
  const [priceMin, setPriceMin] = useState('')
  const [priceMax, setPriceMax] = useState('')
  const [dataQualityFilter, setDataQualityFilter] = useState('all')
  const [showUnavailable, setShowUnavailable] = useState(false)
  const [showArchived, setShowArchived] = useState(false)
  const [selected, setSelected] = useState(new Set())
  const [collapsedGroups, setCollapsedGroups] = useState(new Set())
  // local override of group display order (array of group keys), reset when scope changes
  const [localGroupOrder, setLocalGroupOrder] = useState(null)
  const [bulkPrepZoneModal, setBulkPrepZoneModal] = useState(false)
  const [bulkMoveCatModal, setBulkMoveCatModal] = useState(false)

  // drag state for group headers
  const groupDragId = useRef(null)
  const [groupDropTarget, setGroupDropTarget] = useState(null)

  // drag state for products within a group
  const productDragRef = useRef(null) // { productId, groupKey }
  const [productDropTarget, setProductDropTarget] = useState(null) // { productId, groupKey, after: bool }

  const { data: categories = [] } = useQuery({
    queryKey: ['categories'],
    queryFn: () => client.get('/api/products/categories').then(r => r.data),
  })
  const { data: allProducts = [] } = useQuery({
    queryKey: ['products-all'],
    queryFn: () => client.get('/api/products/?all=true').then(r => r.data),
  })
  const { data: statusData } = useQuery({
    queryKey: ['system-status'],
    queryFn: () => client.get('/api/system/status').then(r => r.data),
    staleTime: 60_000,
  })
  const printers = statusData?.printers ?? []

  const { data: prepZones = [] } = useQuery({
    queryKey: ['prep-zones'],
    queryFn: () => client.get('/api/prep-zones').then(r => r.data),
  })

  const products = allProducts.map(p => ({
    ...p,
    prep_zone_names: (p.prep_zone_ids || []).map(id => prepZones.find(z => z.id === id)?.name).filter(Boolean),
  }))

  const invalidate = () => {
    qc.invalidateQueries({ queryKey: ['products-all'] })
    qc.invalidateQueries({ queryKey: ['categories'] })
  }

  // ── Mutations ──
  const saveCat = useMutation({
    mutationFn: b => editCat?.id ? client.put(`/api/products/categories/${editCat.id}`, b) : client.post('/api/products/categories', b),
    onSuccess: () => { toast.success('Κατηγορία αποθηκεύτηκε'); setEditCat(null); invalidate() },
    onError: () => toast.error('Σφάλμα'),
  })
  const deleteCat = useMutation({
    mutationFn: id => client.delete(`/api/products/categories/${id}`),
    onSuccess: () => { toast.success('Διαγράφηκε'); setConfirmDelete(null); invalidate() },
    onError: () => toast.error('Σφάλμα'),
  })
  const reorderCats = useMutation({
    mutationFn: items => client.put('/api/products/categories/reorder', items),
    onSuccess: () => invalidate(),
  })
  const reorderSubcats = useMutation({
    mutationFn: items => client.put('/api/products/categories/reorder-subcategories', items),
    onSuccess: () => invalidate(),
  })
  const reparentCatMutation = useMutation({
    mutationFn: ({ id, parent_id }) => client.put(`/api/products/categories/${id}/reparent`, { parent_id }),
    onSuccess: () => { toast.success('Η κατηγορία μετακινήθηκε'); invalidate() },
    onError: () => toast.error('Σφάλμα μετακίνησης'),
  })
  const saveProduct = useMutation({
    mutationFn: b => editProduct?.id ? client.put(`/api/products/${editProduct.id}`, b) : client.post('/api/products/', b),
    onSuccess: () => { toast.success('Αποθηκεύτηκε'); setEditProduct(null); invalidate() },
    onError: () => toast.error('Σφάλμα'),
  })
  const reorderProducts = useMutation({
    mutationFn: items => client.put('/api/products/reorder', items),
    onSuccess: () => invalidate(),
    onError: () => toast.error('Σφάλμα αναδιάταξης'),
  })
  const toggleAvail = useMutation({
    mutationFn: ({ id, is_available }) => client.put(`/api/products/${id}`, { is_available }),
    onSuccess: () => invalidate(),
    onError: () => toast.error('Σφάλμα'),
  })
  const archiveProduct = useMutation({
    mutationFn: id => client.delete(`/api/products/${id}`),
    onSuccess: () => { toast.success('Αρχειοθετήθηκε'); setConfirmDelete(null); invalidate() },
    onError: () => toast.error('Σφάλμα'),
  })
  const hardDeleteProduct = useMutation({
    mutationFn: id => client.delete(`/api/products/${id}?hard=true`),
    onSuccess: () => { toast.success('Διαγράφηκε'); setConfirmDelete(null); invalidate() },
    onError: err => toast.error(err.response?.data?.detail || 'Σφάλμα'),
  })
  const reorderCatsInList = useMutation({
    mutationFn: items => client.put('/api/products/categories/reorder', items),
    onSuccess: () => invalidate(),
  })

  // ── Category reorder (sidebar drag) ──
  function handleReorderCats(fromId, toId) {
    const sorted = categories.filter(c => !c.parent_id).sort((a, b) => a.sort_order - b.sort_order)
    const fromIdx = sorted.findIndex(c => c.id === fromId)
    const toIdx = sorted.findIndex(c => c.id === toId)
    if (fromIdx === -1 || toIdx === -1) return
    const next = [...sorted]
    const [item] = next.splice(fromIdx, 1)
    next.splice(toIdx, 0, item)
    reorderCats.mutate(next.map((c, i) => ({ id: c.id, sort_order: i })))
  }

  function handleReorderSubcats(fromId, toId, parentId) {
    const subs = categories.filter(c => c.parent_id === parentId).sort((a, b) => a.sort_order - b.sort_order)
    const fromIdx = subs.findIndex(c => c.id === fromId)
    const toIdx = subs.findIndex(c => c.id === toId)
    if (fromIdx === -1 || toIdx === -1) return
    const next = [...subs]
    const [item] = next.splice(fromIdx, 1)
    next.splice(toIdx, 0, item)
    reorderSubcats.mutate(next.map((c, i) => ({ id: c.id, sort_order: i })))
  }

  function handleReparent(catId, newParentId) {
    reparentCatMutation.mutate({ id: catId, parent_id: newParentId })
  }

  // ── Product filtering ──
  const selectedCatObj = selectedCat && selectedCat !== '__uncategorized__' && selectedCat !== '__archived__'
    ? categories.find(c => c.id === selectedCat) : null
  const isParentScope = selectedCatObj && !selectedCatObj.parent_id
  const subCats = isParentScope ? categories.filter(c => c.parent_id === selectedCat).sort((a, b) => a.sort_order - b.sort_order) : []

  const filtered = (() => {
    let list = products.slice()

    if (selectedCat === '__archived__') {
      list = list.filter(p => p.lifecycle_status === 'archived')
    } else if (selectedCat === '__service__') {
      list = list.filter(p => p.is_service_item && p.lifecycle_status !== 'archived')
    } else if (selectedCat === '__uncategorized__') {
      list = list.filter(p => !p.category_id && !p.is_service_item && p.lifecycle_status !== 'archived')
    } else if (selectedCat) {
      if (isParentScope) {
        const ids = new Set([selectedCat, ...subCats.map(s => s.id)])
        list = list.filter(p => ids.has(p.category_id))
      } else {
        list = list.filter(p => p.category_id === selectedCat)
      }
      if (!showArchived) list = list.filter(p => p.lifecycle_status !== 'archived')
    } else {
      // "All products" — exclude service items (they have their own section)
      list = list.filter(p => !p.is_service_item)
      if (!showArchived) list = list.filter(p => p.lifecycle_status !== 'archived')
    }

    if (subCatFilter !== null && isParentScope) {
      if (subCatFilter === '__own__') list = list.filter(p => p.category_id === selectedCat)
      else list = list.filter(p => p.category_id === subCatFilter)
    }

    if (search.trim()) {
      const q = search.toLowerCase()
      list = list.filter(p => p.name.toLowerCase().includes(q))
    }

    const pmin = priceMin === '' ? -Infinity : Number(priceMin)
    const pmax = priceMax === '' ? Infinity : Number(priceMax)
    list = list.filter(p => p.base_price >= pmin && p.base_price <= pmax)

    if (dataQualityFilter === 'no-photo') list = list.filter(p => !p.image_url)
    if (dataQualityFilter === 'no-cat') list = list.filter(p => !p.category_id)

    if (showUnavailable) list = list.filter(p => !p.is_available)

    return list
  })()

  // Group by category
  const grouped = (() => {
    const groups = new Map()
    filtered.forEach(p => {
      const key = p.category_id ?? '__none__'
      if (!groups.has(key)) groups.set(key, [])
      groups.get(key).push(p)
    })
    const base = [...groups.entries()].map(([key, items]) => {
      const cat = key !== '__none__' ? categories.find(c => c.id === key) : null
      return { key, cat, items }
    }).sort((a, b) => {
      const ao = a.cat?.sort_order ?? 9999
      const bo = b.cat?.sort_order ?? 9999
      return ao - bo
    })
    if (!localGroupOrder) return base
    // Apply local order override
    const byKey = Object.fromEntries(base.map(g => [g.key, g]))
    const ordered = localGroupOrder.map(k => byKey[k]).filter(Boolean)
    // Append any new groups not yet in localGroupOrder
    base.forEach(g => { if (!localGroupOrder.includes(g.key)) ordered.push(g) })
    return ordered
  })()

  const showGroupHeaders = grouped.length > 1

  // ── Group collapse toggle ──
  function toggleGroup(key) {
    setCollapsedGroups(prev => {
      const n = new Set(prev)
      n.has(key) ? n.delete(key) : n.add(key)
      return n
    })
  }

  // ── Selection ──
  const toggleSelect = id => setSelected(prev => { const n = new Set(prev); n.has(id) ? n.delete(id) : n.add(id); return n })
  const clearSelect = () => setSelected(new Set())
  const anySelected = selected.size > 0

  async function bulkAction(action) {
    const ids = [...selected]
    if (!ids.length) return
    try {
      if (action === 'available') await Promise.all(ids.map(id => client.put(`/api/products/${id}`, { is_available: true })))
      else if (action === 'unavailable') await Promise.all(ids.map(id => client.put(`/api/products/${id}`, { is_available: false })))
      else if (action === 'archive') { setConfirmDelete({ type: 'bulk-archive', ids }); return }
      toast.success(`${ids.length} ενημερώθηκαν`)
      invalidate(); clearSelect()
    } catch { toast.error('Σφάλμα') }
  }

  async function confirmBulkArchive(ids) {
    const results = await Promise.allSettled(ids.map(id => client.delete(`/api/products/${id}`)))
    const ok = results.filter(r => r.status === 'fulfilled').length
    if (ok) toast.success(`${ok} αρχειοθετήθηκαν`)
    setConfirmDelete(null); invalidate(); clearSelect()
  }

  async function handleBulkSetPrepZone(prepZoneIds) {
    const ids = [...selected]
    setBulkPrepZoneModal(false)
    try {
      await client.post('/api/products/bulk-prep-zones', { product_ids: ids, prep_zone_ids: prepZoneIds })
      toast.success(`Ζώνες προετοιμασίας ορίστηκαν σε ${ids.length} προϊόντα`)
      invalidate(); clearSelect()
    } catch { toast.error('Σφάλμα') }
  }

  async function handleBulkMoveToCategory(categoryId) {
    const ids = [...selected]
    setBulkMoveCatModal(false)
    try {
      await Promise.all(ids.map(id => client.put(`/api/products/${id}`, { category_id: categoryId })))
      toast.success(`${ids.length} προϊόντα μετακινήθηκαν`)
      invalidate(); clearSelect()
    } catch { toast.error('Σφάλμα') }
  }

  function handleConfirmDelete() {
    if (!confirmDelete) return
    if (confirmDelete.type === 'category') deleteCat.mutate(confirmDelete.id)
    if (confirmDelete.type === 'product-archive') archiveProduct.mutate(confirmDelete.id)
    if (confirmDelete.type === 'product-hard') hardDeleteProduct.mutate(confirmDelete.id)
    if (confirmDelete.type === 'bulk-archive') confirmBulkArchive(confirmDelete.ids)
  }

  // ── Category group drag-reorder in list view ──
  function handleGroupDragStart(groupKey) {
    groupDragId.current = groupKey
  }
  function handleGroupDragOver(groupKey) {
    return e => {
      e.preventDefault()
      if (!groupDragId.current || groupDragId.current === groupKey) return
      setGroupDropTarget(groupKey)
    }
  }
  function handleGroupDragLeave() {
    setGroupDropTarget(null)
  }
  function handleGroupDrop(targetGroupKey) {
    return e => {
      e.preventDefault()
      setGroupDropTarget(null)
      const fromKey = groupDragId.current
      if (!fromKey || fromKey === targetGroupKey) { groupDragId.current = null; return }

      // Reorder groups locally (works for any mix of parent-own + sub-cats)
      const currentKeys = grouped.map(g => g.key)
      const fromIdx = currentKeys.indexOf(fromKey)
      const toIdx = currentKeys.indexOf(targetGroupKey)
      if (fromIdx === -1 || toIdx === -1) { groupDragId.current = null; return }
      const next = [...currentKeys]
      const [item] = next.splice(fromIdx, 1)
      next.splice(toIdx, 0, item)
      setLocalGroupOrder(next)

      // Persist to API based on what kind of groups these are
      const topLevelKeys = next.filter(k => {
        const cat = categories.find(c => c.id === k)
        return cat && !cat.parent_id
      })
      const subCatKeys = next.filter(k => {
        const cat = categories.find(c => c.id === k)
        return cat && cat.parent_id
      })
      if (subCatKeys.length > 1) {
        reorderSubcats.mutate(subCatKeys.map((id, i) => ({ id, sort_order: i })))
      } else if (topLevelKeys.length > 1) {
        reorderCatsInList.mutate(topLevelKeys.map((id, i) => ({ id, sort_order: i })))
      }

      groupDragId.current = null
    }
  }

  // ── Product drag-reorder within a group ──
  function handleProductDragStart(productId, groupKey) {
    return e => {
      productDragRef.current = { productId, groupKey }
      e.dataTransfer.effectAllowed = 'move'
      e.stopPropagation()
    }
  }
  function handleProductDragOver(productId, groupKey) {
    return e => {
      e.preventDefault()
      e.stopPropagation()
      if (!productDragRef.current) return
      if (productDragRef.current.groupKey !== groupKey) return
      if (productDragRef.current.productId === productId) return
      const rect = e.currentTarget.getBoundingClientRect()
      const after = e.clientY > rect.top + rect.height / 2
      setProductDropTarget({ productId, groupKey, after })
    }
  }
  function handleProductDragLeave(e) {
    e.stopPropagation()
    setProductDropTarget(null)
  }
  function handleProductDrop(targetProductId, groupKey) {
    return e => {
      e.preventDefault()
      e.stopPropagation()
      const insertAfter = productDropTarget?.after ?? false
      setProductDropTarget(null)
      const drag = productDragRef.current
      if (!drag || drag.productId === targetProductId || drag.groupKey !== groupKey) {
        productDragRef.current = null; return
      }
      const group = grouped.find(g => g.key === groupKey)
      if (!group) { productDragRef.current = null; return }
      const fromIdx = group.items.findIndex(p => p.id === drag.productId)
      const toIdx = group.items.findIndex(p => p.id === targetProductId)
      if (fromIdx === -1 || toIdx === -1) { productDragRef.current = null; return }
      const next = [...group.items]
      const [item] = next.splice(fromIdx, 1)
      // After removing the dragged item, find the new index of the target
      const newTargetIdx = next.findIndex(p => p.id === targetProductId)
      next.splice(insertAfter ? newTargetIdx + 1 : newTargetIdx, 0, item)
      reorderProducts.mutate(next.map((p, i) => ({ id: p.id, sort_order: i })))
      productDragRef.current = null
    }
  }

  // ── Page title ──
  function getTitle() {
    if (selectedCat === null) return 'Όλα τα προϊόντα'
    if (selectedCat === '__archived__') return 'Αρχειοθετημένα'
    if (selectedCat === '__service__') return 'Service'
    if (selectedCat === '__uncategorized__') return 'Χωρίς κατηγορία'
    const cat = categories.find(c => c.id === selectedCat)
    if (!cat) return 'Προϊόντα'
    if (cat.parent_id) {
      const parent = categories.find(c => c.id === cat.parent_id)
      return parent ? `${parent.name} / ${cat.name}` : cat.name
    }
    return cat.name
  }

  const totalActive = products.filter(p => p.lifecycle_status !== 'archived').length

  return (
    <div style={{ display: 'flex', height: '100%', minHeight: 0 }}>
      {/* Left: category panel */}
      <CategoryPanel
        categories={categories}
        products={products}
        selectedCat={selectedCat}
        onSelect={cat => { setSelectedCat(cat); setSubCatFilter(null); setLocalGroupOrder(null) }}
        onEdit={cat => setEditCat(cat)}
        onDelete={cat => setConfirmDelete({ type: 'category', id: cat.id })}
        onAdd={parentId => setEditCat({ _isNew: true, parent_id: parentId ?? null })}
        onReorder={handleReorderCats}
        onReorderSub={handleReorderSubcats}
        onReparent={handleReparent}
      />

      {/* Right: products panel */}
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0, minWidth: 0 }}>
        <ProductsHeader
          title={getTitle()}
          visibleCount={filtered.length}
          totalCount={totalActive}
          search={search} setSearch={setSearch}
          view={view} setView={setView}
          priceMin={priceMin} setPriceMin={setPriceMin}
          priceMax={priceMax} setPriceMax={setPriceMax}
          dataQualityFilter={dataQualityFilter} setDataQualityFilter={setDataQualityFilter}
          showUnavailable={showUnavailable} setShowUnavailable={setShowUnavailable}
          showArchived={showArchived} setShowArchived={setShowArchived}
          onNew={() => {
            if (selectedCat === '__service__') {
              setEditProduct({ ...EMPTY_PRODUCT, is_service_item: true, base_price: 0 })
              return
            }
            const SPECIAL = [null, '__uncategorized__', '__archived__', '__service__']
            const presetCat = (!SPECIAL.includes(subCatFilter) && subCatFilter)
              || (!SPECIAL.includes(selectedCat) && selectedCat)
              || ''
            setEditProduct({ ...EMPTY_PRODUCT, category_id: presetCat })
          }}
        />

        {/* Sub-cat filter chips */}
        {isParentScope && subCats.length > 0 && (
          <SubCatBar
            parentCat={selectedCatObj}
            subCats={subCats}
            products={products}
            subCatFilter={subCatFilter}
            setSubCatFilter={setSubCatFilter}
          />
        )}

        {/* Bulk bar */}
        {anySelected && (
          <BulkBar
            count={selected.size}
            onClear={clearSelect}
            onAvail={() => bulkAction('available')}
            onUnavail={() => bulkAction('unavailable')}
            onArchive={() => bulkAction('archive')}
            onSetPrepZone={() => setBulkPrepZoneModal(true)}
            onMoveToCategory={() => setBulkMoveCatModal(true)}
          />
        )}

        {/* Select-all bar */}
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '8px 24px', background: '#f3f4f6', borderBottom: '1px solid #e5e7eb', flexShrink: 0 }}>
          <label style={{ display: 'flex', alignItems: 'center', gap: 7, fontSize: 13, color: '#6b7280', cursor: 'pointer', userSelect: 'none' }}>
            <input type="checkbox"
              checked={filtered.length > 0 && filtered.every(p => selected.has(p.id))}
              onChange={e => e.target.checked ? setSelected(new Set(filtered.map(p => p.id))) : clearSelect()}
              style={{ accentColor: '#3b82f6', width: 14, height: 14 }}
            />
            {anySelected ? `${selected.size} επιλεγμένα` : 'Επιλογή όλων'}
          </label>
          <div style={{ display: 'flex', gap: 16, fontSize: 12, color: '#9ca3af' }}>
            <span><strong style={{ color: '#374151' }}>{products.filter(p => p.lifecycle_status !== 'archived').length}</strong> ενεργά</span>
            <span><strong style={{ color: '#374151' }}>{categories.length}</strong> κατηγορίες</span>
            <span><strong style={{ color: '#374151' }}>{products.filter(p => p.lifecycle_status === 'archived').length}</strong> αρχείο</span>
          </div>
        </div>

        {/* Product body */}
        <div style={{ flex: 1, overflowY: 'auto', padding: view === 'list' ? '0 24px 32px' : '16px 24px 32px' }}>
          {filtered.length === 0 ? (
            <div style={{ textAlign: 'center', padding: '80px 20px', color: '#9ca3af' }}>
              <div style={{ width: 64, height: 64, background: '#f3f4f6', borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '0 auto 16px' }}>
                <Icon name="search" size={28} className="text-gray-400" />
              </div>
              <h3 style={{ margin: '0 0 6px', fontSize: 17, color: '#374151', fontWeight: 600 }}>Δεν βρέθηκαν προϊόντα</h3>
              <p style={{ margin: '0 0 16px', fontSize: 13.5 }}>Δοκιμάστε διαφορετικά φίλτρα ή προσθέστε νέο προϊόν.</p>
              <button onClick={() => {
                const SPECIAL = [null, '__uncategorized__', '__archived__']
                const presetCat = (!SPECIAL.includes(subCatFilter) && subCatFilter)
                  || (!SPECIAL.includes(selectedCat) && selectedCat)
                  || ''
                setEditProduct({ ...EMPTY_PRODUCT, category_id: presetCat })
              }}
                style={{ display: 'inline-flex', alignItems: 'center', gap: 6, padding: '8px 16px', background: '#111827', color: '#fff', border: 'none', borderRadius: 8, fontSize: 13.5, cursor: 'pointer' }}>
                <Icon name="plus" size={14} />
                Νέο προϊόν
              </button>
            </div>
          ) : view === 'list' ? (
            <div style={{ display: 'flex', flexDirection: 'column', gap: 16, paddingTop: 14 }}>
              {grouped.map(({ key, cat, items }) => {
                const isCollapsed = collapsedGroups.has(key)
                const isGroupDropHere = groupDropTarget === key && showGroupHeaders
                return (
                  <div key={key}>
                    {showGroupHeaders && (
                      <GroupHeader
                        cat={cat}
                        count={items.length}
                        isOpen={!isCollapsed}
                        onToggle={() => toggleGroup(key)}
                        showToggle={showGroupHeaders}
                        dropIndicator={isGroupDropHere}
                        onDragStart={() => handleGroupDragStart(key)}
                        onDragOver={handleGroupDragOver(key)}
                        onDragLeave={handleGroupDragLeave}
                        onDrop={handleGroupDrop(key)}
                      />
                    )}
                    {!isCollapsed && (
                      <div style={{ background: '#fff', border: '1px solid #e5e7eb', borderRadius: 10, overflow: 'hidden', padding: 4, display: 'flex', flexDirection: 'column', gap: 2 }}>
                        {items.map(p => {
                          const pCat = categories.find(c => c.id === p.category_id)
                          const pParentCat = pCat?.parent_id ? categories.find(c => c.id === pCat.parent_id) : null
                          const dropMatch = productDropTarget?.productId === p.id && productDropTarget?.groupKey === key
                          const isDragging = productDragRef.current?.productId === p.id
                          return (
                            <ProductRow
                              key={p.id}
                              p={p} cat={pCat} parentCat={pParentCat}
                              selected={selected.has(p.id)}
                              onToggleSelect={toggleSelect}
                              onEdit={p => setEditProduct(p)}
                              onArchive={p => setConfirmDelete({ type: p.lifecycle_status === 'archived' ? 'product-hard' : 'product-archive', id: p.id })}
                              onToggleAvail={p => toggleAvail.mutate({ id: p.id, is_available: !p.is_available })}
                              anySelected={anySelected}
                              dragging={isDragging}
                              dropBefore={dropMatch && !productDropTarget?.after}
                              dropAfter={dropMatch && productDropTarget?.after}
                              onDragStart={handleProductDragStart(p.id, key)}
                              onDragOver={handleProductDragOver(p.id, key)}
                              onDragLeave={handleProductDragLeave}
                              onDrop={handleProductDrop(p.id, key)}
                            />
                          )
                        })}
                      </div>
                    )}
                  </div>
                )
              })}
            </div>
          ) : (
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(200px, 1fr))', gap: 14 }}>
              {filtered.map(p => {
                const pCat = categories.find(c => c.id === p.category_id)
                const pParentCat = pCat?.parent_id ? categories.find(c => c.id === pCat.parent_id) : null
                return (
                  <ProductCard
                    key={p.id}
                    p={p} cat={pCat} parentCat={pParentCat}
                    selected={selected.has(p.id)}
                    onToggleSelect={toggleSelect}
                    onEdit={p => setEditProduct(p)}
                    onArchive={p => setConfirmDelete({ type: p.lifecycle_status === 'archived' ? 'product-hard' : 'product-archive', id: p.id })}
                    onToggleAvail={p => toggleAvail.mutate({ id: p.id, is_available: !p.is_available })}
                  />
                )
              })}
            </div>
          )}
        </div>
      </div>

      {/* Category form modal */}
      {editCat !== null && (
        <CategoryModal
          cat={editCat}
          parentName={editCat.parent_id ? categories.find(c => c.id === editCat.parent_id)?.name : null}
          onSave={(name, color) => saveCat.mutate({ name, color, parent_id: editCat.parent_id ?? null })}
          onClose={() => setEditCat(null)}
        />
      )}

      {/* Product form modal */}
      {editProduct !== null && (
        <ProductFormModal
          product={editProduct}
          categories={categories}
          printers={printers}
          prepZones={prepZones}
          onSave={b => saveProduct.mutate(b)}
          onCopy={formData => setEditProduct({ ...EMPTY_PRODUCT, ...formData, id: undefined, image_url: undefined, name: formData.name + ' (αντίγραφο)' })}
          onClose={() => setEditProduct(null)}
        />
      )}

      {/* Confirm modal */}
      {confirmDelete && (
        <ConfirmModal
          title="Επιβεβαίωση"
          message={
            confirmDelete.type === 'category' ? 'Η κατηγορία θα διαγραφεί.'
            : confirmDelete.type === 'bulk-archive' ? `${confirmDelete.ids.length} προϊόντα θα αρχειοθετηθούν.`
            : confirmDelete.type === 'product-archive' ? 'Το προϊόν θα αρχειοθετηθεί.'
            : 'Οριστική διαγραφή. Το προϊόν θα χαθεί μόνιμα.'
          }
          confirmLabel={confirmDelete.type === 'product-hard' ? 'Διαγραφή' : 'Επιβεβαίωση'}
          confirmVariant="danger"
          onConfirm={handleConfirmDelete}
          onCancel={() => setConfirmDelete(null)}
        />
      )}

      {/* Bulk: set prep zone modal */}
      {bulkPrepZoneModal && (
        <BulkSetPrepZoneModal
          count={selected.size}
          prepZones={prepZones}
          onClose={() => setBulkPrepZoneModal(false)}
          onConfirm={handleBulkSetPrepZone}
        />
      )}

      {/* Bulk: move to category modal */}
      {bulkMoveCatModal && (
        <BulkMoveToCategoryModal
          count={selected.size}
          categories={categories}
          onClose={() => setBulkMoveCatModal(false)}
          onConfirm={handleBulkMoveToCategory}
        />
      )}
    </div>
  )
}

// ── Category Modal ────────────────────────────────────────────────────────────
const COLORS = ['#6366f1','#0ea5e9','#10b981','#f59e0b','#ef4444','#ec4899','#8b5cf6','#14b8a6','#f97316','#64748b','#84cc16','#06b6d4']

function CategoryModal({ cat, parentName, onSave, onClose }) {
  const [name, setName] = useState(cat.name || '')
  const [color, setColor] = useState(cat.color || COLORS[0])
  const isNew = !cat.id
  const isSub = !!cat.parent_id

  return (
    <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.4)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 50, padding: 16 }}>
      <div style={{ background: '#fff', borderRadius: 16, boxShadow: '0 20px 60px rgba(0,0,0,0.15)', width: '100%', maxWidth: 380, padding: 24 }}>
        <h2 style={{ margin: '0 0 4px', fontWeight: 700, fontSize: 16, color: '#111827' }}>
          {isNew ? (isSub ? 'Νέα υποκατηγορία' : 'Νέα κατηγορία') : (isSub ? 'Επεξεργασία υποκατηγορίας' : 'Επεξεργασία κατηγορίας')}
        </h2>
        {isSub && parentName && (
          <p style={{ margin: '0 0 16px', fontSize: 12, color: '#9ca3af' }}>
            Κατηγορία: <strong style={{ color: '#6b7280' }}>{parentName}</strong>
          </p>
        )}
        <div style={{ marginTop: 16, marginBottom: 14 }}>
          <label style={{ fontSize: 12, fontWeight: 600, color: '#6b7280', display: 'block', marginBottom: 5 }}>Όνομα</label>
          <input
            value={name} onChange={e => setName(e.target.value)} autoFocus
            style={{ width: '100%', padding: '9px 12px', border: '1px solid #e5e7eb', borderRadius: 8, fontSize: 14, outline: 'none', boxSizing: 'border-box' }}
          />
        </div>
        <div style={{ marginBottom: 20 }}>
          <label style={{ fontSize: 12, fontWeight: 600, color: '#6b7280', display: 'block', marginBottom: 8 }}>Χρώμα</label>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(6, 1fr)', gap: 8 }}>
            {COLORS.map(c => (
              <button key={c} onClick={() => setColor(c)}
                style={{ border: color === c ? '3px solid #111827' : '2px solid transparent', background: c, width: '100%', aspectRatio: '1', borderRadius: '50%', cursor: 'pointer', outline: 'none' }}
              />
            ))}
          </div>
        </div>
        <div style={{ display: 'flex', gap: 10 }}>
          <button onClick={onClose} style={{ flex: 1, padding: '9px 0', border: '1px solid #e5e7eb', background: '#fff', borderRadius: 8, fontSize: 14, cursor: 'pointer', color: '#374151' }}>
            Ακύρωση
          </button>
          <button onClick={() => onSave(name, color)} disabled={!name.trim()}
            style={{ flex: 1, padding: '9px 0', border: 'none', background: name.trim() ? '#111827' : '#d1d5db', color: '#fff', borderRadius: 8, fontSize: 14, fontWeight: 600, cursor: name.trim() ? 'pointer' : 'not-allowed' }}>
            Αποθήκευση
          </button>
        </div>
      </div>
    </div>
  )
}
