import { useEffect, useState, useRef } from 'react'
import Icon from './components/Icon'
import ContextMenu from './components/ContextMenu'
import {
  onMessage, notifyReady,
  listLayouts, deleteLayout, renameLayout, activateLayout,
  addDetail, deleteDetail, bindAusschnitt, syncDetail, syncLayout,
  exportPdf, exportPdfAll, exportPdfMany,
  addLayoutFolder, removeLayoutFolder, setLayoutFolder,
  openLayoutDialog,
} from './lib/rhinoBridge'

const PAPER_FORMATS_MM = {
  A0: [841, 1189], A1: [594, 841], A2: [420, 594], A3: [297, 420],
  A4: [210, 297], Letter: [216, 279],
}

function detectFormat(wMm, hMm, tol = 2) {
  if (!(wMm > 0) || !(hMm > 0)) return null
  const a = Math.min(wMm, hMm), b = Math.max(wMm, hMm)
  for (const [name, [sw, sh]] of Object.entries(PAPER_FORMATS_MM)) {
    if (Math.abs(a - sw) <= tol && Math.abs(b - sh) <= tol) return name
  }
  return null
}

function formatLabel(wMm, hMm) {
  if (!(wMm > 0) || !(hMm > 0)) return '—'
  const f = detectFormat(wMm, hMm)
  if (!f) return `${Math.round(wMm)}×${Math.round(hMm)}mm`
  const landscape = wMm > hMm
  return landscape ? `${f} ↔` : `${f} ↕`
}

function OrientationBadge({ landscape }) {
  return (
    <span title={landscape ? 'Querformat' : 'Hochformat'}
      style={{
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        width: 24, height: 24, flexShrink: 0,
        borderRadius: 999,
        background: 'var(--bg-input)',
        color: 'var(--accent)',
      }}>
      <Icon name={landscape ? 'crop_landscape' : 'crop_portrait'} size={14} />
    </span>
  )
}

const cardStyle = {
  background: 'var(--bg-section)',
  border: '1px solid var(--border)',
  borderRadius: 'var(--r-lg)',
  padding: 8,
  marginBottom: 6,
}

const labelXs = {
  fontSize: 10, fontWeight: 600, color: 'var(--text-muted)',
  letterSpacing: '0.06em', textTransform: 'uppercase',
}

// Inline-editierbarer Name — Doppelklick aktiviert, Enter/Blur committet.
// forceEdit triggert Edit-Mode von aussen (z.B. Kontextmenue „Umbenennen").
function EditableName({ value, onCommit, style, title, forceEdit, onEditDone }) {
  const [editing, setEditing] = useState(false)
  const [text, setText] = useState(value || '')
  const inputRef = useRef(null)
  useEffect(() => { if (!editing) setText(value || '') }, [value, editing])
  useEffect(() => { if (editing) { inputRef.current?.focus(); inputRef.current?.select() } }, [editing])
  useEffect(() => { if (forceEdit) setEditing(true) }, [forceEdit])
  if (editing) {
    return (
      <input
        ref={inputRef}
        value={text}
        onChange={(e) => setText(e.target.value)}
        onBlur={() => {
          setEditing(false)
          const t = text.trim()
          if (t && t !== value) onCommit(t)
          else setText(value || '')
          onEditDone && onEditDone()
        }}
        onKeyDown={(e) => {
          if (e.key === 'Enter') e.currentTarget.blur()
          else if (e.key === 'Escape') {
            setText(value || ''); setEditing(false); onEditDone && onEditDone()
          }
        }}
        onClick={(e) => e.stopPropagation()}
        style={{ flex: 1, fontSize: 'inherit', fontFamily: 'inherit', ...style }}
      />
    )
  }
  return (
    <span
      onDoubleClick={(e) => { e.stopPropagation(); setEditing(true) }}
      title={title || 'Doppelklick zum Umbenennen'}
      style={{
        flex: 1, cursor: 'text',
        overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
        ...style,
      }}
    >
      {value || '(unbenannt)'}
    </span>
  )
}

export default function LayoutsApp() {
  const [state, setState] = useState({ layouts: [], snapshots: [], details: {}, folders: [] })
  const [selectedId, setSelectedId] = useState(null)
  const [checked, setChecked] = useState(new Set())  // Multi-Select IDs
  const [collapsedFolders, setCollapsedFolders] = useState(new Set())
  const [draggingId, setDraggingId] = useState(null)
  const [dragTarget, setDragTarget] = useState(null)  // '__root' | folderName
  const [ctxMenu, setCtxMenu] = useState(null)         // {x,y,kind,id}
  const [renamingId, setRenamingId] = useState(null)   // signal to inline-edit

  useEffect(() => {
    onMessage('STATE', (s) => setState((prev) => ({ ...prev, ...s })))
    notifyReady()
  }, [])

  const layouts = state.layouts || []
  const snaps   = state.snapshots || []
  const folders = state.folders || []
  const details = (selectedId && state.details && state.details[selectedId]) || []
  const selected = layouts.find(l => l.id === selectedId)

  // Layouts gruppieren: Root + per Folder
  const grouped = { __root: [] }
  for (const f of folders) grouped[f] = []
  for (const l of layouts) {
    const f = l.folder || '__root'
    if (!grouped[f]) grouped[f] = []
    grouped[f].push(l)
  }

  const toggleCheck = (id) => {
    setChecked(prev => {
      const next = new Set(prev)
      if (next.has(id)) next.delete(id); else next.add(id)
      return next
    })
  }
  const toggleFolderCollapse = (name) => {
    setCollapsedFolders(prev => {
      const next = new Set(prev)
      if (next.has(name)) next.delete(name); else next.add(name)
      return next
    })
  }
  const checkAllInFolder = (folderLayouts) => {
    setChecked(prev => {
      const next = new Set(prev)
      const allIn = folderLayouts.every(l => next.has(l.id))
      if (allIn) folderLayouts.forEach(l => next.delete(l.id))
      else       folderLayouts.forEach(l => next.add(l.id))
      return next
    })
  }
  const handleExportSelection = () => {
    const ids = [...checked].filter(id => layouts.find(l => l.id === id))
    if (ids.length === 0) return
    exportPdfMany(ids, 300)
  }
  const handleExportFolder = (folderName) => {
    const ids = (grouped[folderName] || []).map(l => l.id)
    if (ids.length === 0) return
    exportPdfMany(ids, 300)
  }
  const handleNewFolder = () => {
    const name = window.prompt('Name fuer neuen Ordner:')
    if (name && name.trim()) addLayoutFolder(name.trim())
  }

  // Kontextmenue-Items pro Layout
  const layoutCtxItems = (l) => [
    { label: 'In Rhino oeffnen',   icon: 'open_in_new',
      onClick: () => activateLayout(l.id) },
    { label: 'Umbenennen',         icon: 'edit',
      onClick: () => setRenamingId(l.id) },
    { divider: true },
    { label: 'Als PDF exportieren', icon: 'picture_as_pdf',
      onClick: () => exportPdf(l.id, 300) },
    { label: 'Papierformat ändern', icon: 'aspect_ratio',
      onClick: () => openLayoutDialog('edit', {
        id: l.id, name: l.name, width: l.widthMm, height: l.heightMm,
      }) },
    { divider: true },
    ...(folders.length > 0 ? [
      ...folders.map(f => ({
        label: `Verschieben → ${f}`,
        icon: 'folder',
        disabled: l.folder === f,
        onClick: () => setLayoutFolder(l.id, f),
      })),
      { label: 'Aus Ordner entfernen',
        icon: 'folder_off',
        disabled: !l.folder,
        onClick: () => setLayoutFolder(l.id, '') },
      { divider: true },
    ] : []),
    { label: 'Löschen',           icon: 'delete', danger: true,
      onClick: () => {
        if (window.confirm(`Layout "${l.name}" löschen?`)) deleteLayout(l.id)
      } },
  ]

  // Kontextmenue-Items pro Ordner
  const folderCtxItems = (folderName) => {
    const items = grouped[folderName] || []
    return [
      { label: collapsedFolders.has(folderName) ? 'Aufklappen' : 'Einklappen',
        icon: collapsedFolders.has(folderName) ? 'expand_more' : 'expand_less',
        onClick: () => toggleFolderCollapse(folderName) },
      { divider: true },
      { label: 'Alle ankreuzen / abwählen',
        icon: 'check_box',
        onClick: () => checkAllInFolder(items) },
      { label: `Ordner als PDF (${items.length})`,
        icon: 'picture_as_pdf',
        disabled: items.length === 0,
        onClick: () => handleExportFolder(folderName) },
      { divider: true },
      { label: 'Ordner umbenennen',
        icon: 'edit',
        onClick: () => {
          const next = window.prompt('Neuer Ordner-Name:', folderName)
          if (next && next.trim() && next !== folderName) {
            // Atomar via Server-Side waere besser; simpler: alle Layouts
            // umhaengen + alten loeschen + neuen anlegen.
            addLayoutFolder(next.trim())
            items.forEach(l => setLayoutFolder(l.id, next.trim()))
            removeLayoutFolder(folderName)
          }
        } },
      { label: 'Ordner loeschen',
        icon: 'folder_off', danger: true,
        onClick: () => {
          if (window.confirm(`Ordner "${folderName}" loeschen? Layouts werden zur Wurzel verschoben.`))
            removeLayoutFolder(folderName)
        } },
    ]
  }

  // Drag&Drop-Handler — analog Ausschnitte-Pattern
  const handleDragOver = (folderName) => (ev) => {
    ev.preventDefault()
    ev.dataTransfer.dropEffect = 'move'
    setDragTarget(folderName || '__root')
  }
  const handleDragLeave = () => () => setDragTarget(null)
  const handleDrop = (folderName) => (ev) => {
    ev.preventDefault()
    setDragTarget(null)
    const id = ev.dataTransfer.getData('text/plain') || draggingId
    if (id) setLayoutFolder(id, folderName || '')
    setDraggingId(null)
  }

  // Auto-Select erstes Layout wenn nichts gewaehlt
  useEffect(() => {
    if (selectedId == null && layouts.length > 0) setSelectedId(layouts[0].id)
    if (selectedId != null && !layouts.find(l => l.id === selectedId)) {
      setSelectedId(layouts[0]?.id || null)
    }
  }, [layouts, selectedId])

  return (
    <div style={{
      display: 'flex', flexDirection: 'column',
      height: '100vh', overflow: 'hidden',
      background: 'var(--bg-base)', color: 'var(--text-primary)',
      fontFamily: 'var(--font)', fontSize: 11,
    }}>
      <div style={{ flex: 1, overflowY: 'auto', overflowX: 'hidden', padding: 8 }}>
        {/* Layout-Liste */}
        {layouts.length === 0 && folders.length === 0 ? (
          <div style={{
            padding: '32px 16px', textAlign: 'center',
            color: 'var(--text-muted)', fontSize: 11,
            border: '1px dashed var(--border)',
            borderRadius: 'var(--r-lg)',
            background: 'var(--bg-section)',
          }}>
            <Icon name="dashboard" size={32} style={{ color: 'var(--text-muted)', opacity: 0.5 }} />
            <div style={{ marginTop: 8 }}>Noch keine Layouts.</div>
            <div style={{ marginTop: 4, fontSize: 10 }}>
              Unten <Icon name="add" size={11} /> klicken um ein neues Layout anzulegen.
            </div>
          </div>
        ) : (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 6, marginBottom: 10 }}>
            {/* Ordner-Gruppen */}
            {folders.map(folderName => {
              const items = grouped[folderName] || []
              const isCollapsed = collapsedFolders.has(folderName)
              const allChecked  = items.length > 0 && items.every(l => checked.has(l.id))
              const isDropTarget = dragTarget === folderName
              return (
                <div key={folderName}
                  onContextMenu={(ev) => {
                    ev.preventDefault(); ev.stopPropagation()
                    setCtxMenu({ x: ev.clientX, y: ev.clientY, kind: 'folder', id: folderName })
                  }}
                  onDragOver={handleDragOver(folderName)}
                  onDragLeave={handleDragLeave()}
                  onDrop={handleDrop(folderName)}
                  style={{
                    border: `1px solid ${isDropTarget ? 'var(--accent-border)' : 'var(--border)'}`,
                    borderRadius: 'var(--r-lg)',
                    background: isDropTarget ? 'var(--accent-dim)' : 'var(--bg-section)',
                    marginBottom: 8,
                    padding: 8,
                    transition: 'background 0.14s, border-color 0.14s',
                  }}>
                  <div
                    onClick={() => toggleFolderCollapse(folderName)}
                    style={{
                      display: 'flex', alignItems: 'center', gap: 6,
                      cursor: 'pointer', userSelect: 'none',
                      padding: 2,
                    }}
                  >
                    <input
                      type="checkbox"
                      checked={allChecked}
                      onClick={(e) => e.stopPropagation()}
                      onChange={() => checkAllInFolder(items)}
                      title="Alle in diesem Ordner ankreuzen"
                      style={{ margin: 0, flexShrink: 0 }}
                    />
                    <span style={{
                      transform: isCollapsed ? 'rotate(-90deg)' : 'rotate(0deg)',
                      transition: 'transform 0.2s cubic-bezier(0.4, 0, 0.2, 1)',
                      color: 'var(--text-muted)', display: 'inline-flex',
                    }}>
                      <Icon name="arrow_drop_down" size={16} />
                    </span>
                    <Icon name="folder" size={14} style={{ color: 'var(--warn)' }} />
                    <span style={{ flex: 1, fontSize: 11, fontWeight: 500,
                                   color: 'var(--text-primary)' }}>
                      {folderName}
                    </span>
                    <span className="chip" style={{ fontSize: 8 }}>{items.length}</span>
                    <button
                      className="btn-icon-sm"
                      onClick={(ev) => {
                        ev.stopPropagation()
                        setCtxMenu({ x: ev.clientX, y: ev.clientY, kind: 'folder', id: folderName })
                      }}
                      title="Ordner-Aktionen"
                    >
                      <Icon name="more_vert" size={14} />
                    </button>
                  </div>
                  {!isCollapsed && (
                    <div style={{ marginTop: 6, display: 'flex', flexDirection: 'column' }}>
                      {items.map(l => (
                        <LayoutRow key={l.id} l={l}
                          active={l.id === selectedId}
                          checked={checked.has(l.id)}
                          dragging={draggingId === l.id}
                          forceEditName={renamingId === l.id}
                          onEditDone={() => setRenamingId(null)}
                          onCheck={() => toggleCheck(l.id)}
                          onSelect={() => setSelectedId(l.id)}
                          onActivate={() => activateLayout(l.id)}
                          onRename={(n) => renameLayout(l.id, n)}
                          onContextMenu={(ev) => {
                            ev.preventDefault(); ev.stopPropagation()
                            setSelectedId(l.id)
                            setCtxMenu({ x: ev.clientX, y: ev.clientY, kind: 'layout', id: l.id })
                          }}
                          onMenuClick={(ev) => {
                            setSelectedId(l.id)
                            setCtxMenu({ x: ev.clientX, y: ev.clientY, kind: 'layout', id: l.id })
                          }}
                          onDragStart={(ev) => {
                            ev.dataTransfer.setData('text/plain', l.id)
                            ev.dataTransfer.effectAllowed = 'move'
                            setDraggingId(l.id)
                          }}
                          onDragEnd={() => { setDraggingId(null); setDragTarget(null) }}
                        />
                      ))}
                      {items.length === 0 && (
                        <div style={{
                          padding: '10px 6px', fontSize: 10, color: 'var(--text-muted)',
                          textAlign: 'center', fontStyle: 'italic',
                        }}>
                          Leer — Layouts hier ablegen.
                        </div>
                      )}
                    </div>
                  )}
                </div>
              )
            })}

            {/* Root-Drop-Zone — auch wenn keine Root-Layouts existieren, damit
                man ein Layout aus einem Ordner zurueck auf "kein Ordner"
                ziehen kann. */}
            <div
              onDragOver={handleDragOver('')}
              onDragLeave={handleDragLeave()}
              onDrop={handleDrop('')}
              style={{
                display: 'flex', flexDirection: 'column', gap: 3,
                padding: grouped.__root.length === 0 ? 8 : 0,
                border: `1px ${dragTarget === '__root' ? 'solid var(--accent)' : 'dashed transparent'}`,
                borderRadius: 'var(--r)',
                background: dragTarget === '__root' ? 'var(--bg-item-active)' : 'transparent',
                transition: 'all 0.1s',
                minHeight: grouped.__root.length === 0 ? 32 : 0,
              }}
            >
              {grouped.__root.map(l => (
                <LayoutRow key={l.id} l={l}
                  active={l.id === selectedId}
                  checked={checked.has(l.id)}
                  dragging={draggingId === l.id}
                  forceEditName={renamingId === l.id}
                  onEditDone={() => setRenamingId(null)}
                  onCheck={() => toggleCheck(l.id)}
                  onSelect={() => setSelectedId(l.id)}
                  onActivate={() => activateLayout(l.id)}
                  onRename={(n) => renameLayout(l.id, n)}
                  onContextMenu={(ev) => {
                    ev.preventDefault(); ev.stopPropagation()
                    setSelectedId(l.id)
                    setCtxMenu({ x: ev.clientX, y: ev.clientY, kind: 'layout', id: l.id })
                  }}
                  onMenuClick={(ev) => {
                    setSelectedId(l.id)
                    setCtxMenu({ x: ev.clientX, y: ev.clientY, kind: 'layout', id: l.id })
                  }}
                  onDragStart={(ev) => {
                    ev.dataTransfer.setData('text/plain', l.id)
                    ev.dataTransfer.effectAllowed = 'move'
                    setDraggingId(l.id)
                  }}
                  onDragEnd={() => { setDraggingId(null); setDragTarget(null) }}
                />
              ))}
              {grouped.__root.length === 0 && draggingId && (
                <div style={{
                  textAlign: 'center', color: 'var(--text-muted)',
                  fontSize: 10, fontStyle: 'italic',
                }}>
                  Hier ablegen um aus Ordner zu entfernen
                </div>
              )}
            </div>
          </div>
        )}

        {/* Details des aktuell gewaehlten Layouts */}
        {selected && (
          <div style={cardStyle}>
            <div style={{ display: 'flex', alignItems: 'center', marginBottom: 6 }}>
              <span style={{ ...labelXs, flex: 1 }}>
                Details · {selected.name}
              </span>
              <button
                onClick={() => addDetail(selected.id, null)}
                className="btn-icon-tonal"
                title="Neues Detail (zentriert auf Seite)"
                style={{ marginRight: 4 }}
              >
                <Icon name="add" size={13} />
              </button>
              <button
                onClick={() => syncLayout(selected.id)}
                className="btn-icon-tonal"
                disabled={details.length === 0}
                title="Alle Details mit ihren Ausschnitten neu synchronisieren"
              >
                <Icon name="sync" size={13} />
              </button>
            </div>

            {details.length === 0 ? (
              <div style={{
                padding: '20px 12px', textAlign: 'center',
                color: 'var(--text-muted)', fontSize: 11,
                border: '1px dashed var(--border)',
                borderRadius: 'var(--r)',
                background: 'var(--bg-input)',
              }}>
                <Icon name="crop_landscape" size={24} style={{ color: 'var(--text-muted)', opacity: 0.5 }} />
                <div style={{ marginTop: 6 }}>Keine Details auf diesem Layout.</div>
                <div style={{ marginTop: 4, fontSize: 10 }}>
                  Oben <Icon name="add" size={11} /> klicken um eines hinzuzufügen.
                </div>
              </div>
            ) : (
              <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
                {details.map((d, i) => (
                  <div key={d.id} style={{
                    display: 'flex', flexDirection: 'column', gap: 4,
                    padding: '6px 8px',
                    background: 'var(--bg-input)',
                    border: '1px solid var(--border-light)',
                    borderRadius: 'var(--r)',
                  }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                      <span className="chip" style={{ flexShrink: 0 }}>#{i + 1}</span>
                      <span style={{
                        flex: 1, fontWeight: 500,
                        overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
                      }}>
                        {d.name || '(Detail)'}
                      </span>
                      <span style={{ fontSize: 10, color: 'var(--text-muted)', fontFamily: 'DM Mono, monospace' }}>
                        {Math.round(d.width)}×{Math.round(d.height)}
                      </span>
                      <button
                        className="btn-icon-sm btn-icon-danger"
                        onClick={() => {
                          if (window.confirm('Detail loeschen?')) deleteDetail(selected.id, d.id)
                        }}
                        title="Detail loeschen"
                      >
                        <Icon name="delete" size={12} />
                      </button>
                    </div>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
                      <select
                        value={d.boundAusschnitt || ''}
                        onChange={(e) => bindAusschnitt(selected.id, d.id, e.target.value || null)}
                        style={{ flex: 1, fontSize: 11 }}
                        title="Welcher Ausschnitt auf diesem Detail liegt"
                      >
                        <option value="">— kein Ausschnitt —</option>
                        {snaps.map(s => (
                          <option key={s.id} value={s.id}>
                            {s.name}{s.folder ? ` · ${s.folder}` : ''}{s.scale ? ` · ${s.scale}` : ''}
                          </option>
                        ))}
                      </select>
                      <button
                        onClick={() => syncDetail(selected.id, d.id)}
                        disabled={!d.boundAusschnitt}
                        className="btn-icon-sm"
                        title="Gebundenen Ausschnitt neu anwenden"
                      >
                        <Icon name="sync" size={12} />
                      </button>
                    </div>
                  </div>
                ))}
              </div>
            )}
          </div>
        )}
      </div>

      {/* Sticky Footer: Anzahl + Aktionen */}
      <div style={{
        display: 'flex', alignItems: 'center', gap: 8,
        padding: '8px 10px',
        borderTop: '1px solid var(--border)',
        background: 'var(--bg-panel)',
        flexShrink: 0,
      }}>
        <span className="chip" style={{
          fontSize: 9, minWidth: 22, justifyContent: 'center',
        }}>{layouts.length}</span>
        <span style={{ fontSize: 10, color: 'var(--text-muted)', flex: 1 }}>
          Layouts
        </span>
        {/* PDF-Aktionen: feste Breite damit das Auswahl-Counter den Footer
            nicht horizontal verschiebt. */}
        <button
          onClick={handleExportSelection}
          className="btn-icon-tonal"
          disabled={checked.size === 0}
          title={checked.size > 0
            ? `Auswahl (${checked.size}) als ein PDF exportieren`
            : 'Erst Layouts ankreuzen'}
          style={{ width: 'auto', minWidth: 26, padding: '0 8px', gap: 3 }}
        >
          <Icon name="picture_as_pdf" size={14} />
          {checked.size > 0 && (
            <span style={{ fontSize: 9, fontFamily: 'DM Mono, monospace' }}>
              {checked.size}
            </span>
          )}
        </button>
        <button
          onClick={() => exportPdfAll(300)}
          className="btn-icon-tonal"
          disabled={layouts.length === 0}
          title="Alle Layouts als ein PDF exportieren"
          style={{ width: 'auto', minWidth: 26, padding: '0 8px', gap: 3 }}
        >
          <Icon name="picture_as_pdf" size={14} />
          <span style={{ fontSize: 9 }}>·∗</span>
        </button>
        <div style={{ width: 1, height: 18, background: 'var(--border)' }} />
        <button
          onClick={handleNewFolder}
          className="btn-icon-tonal"
          title="Neuer Ordner"
        >
          <Icon name="create_new_folder" size={14} />
        </button>
        <button
          onClick={() => listLayouts()}
          className="btn-icon-tonal"
          title="Aktualisieren"
        >
          <Icon name="refresh" size={14} />
        </button>
        <button
          onClick={() => openLayoutDialog('new', null)}
          className="btn-add"
          title="Neues Layout erstellen"
        >
          <Icon name="add" size={16} />
        </button>
      </div>

      {/* Kontextmenue */}
      {ctxMenu && (
        <ContextMenu
          x={ctxMenu.x}
          y={ctxMenu.y}
          items={
            ctxMenu.kind === 'folder'
              ? folderCtxItems(ctxMenu.id)
              : (() => {
                  const l = layouts.find(x => x.id === ctxMenu.id)
                  return l ? layoutCtxItems(l) : []
                })()
          }
          onClose={() => setCtxMenu(null)}
        />
      )}

    </div>
  )
}

function LayoutRow({ l, active, checked, dragging, forceEditName,
                     onCheck, onSelect, onActivate, onRename,
                     onContextMenu, onMenuClick,
                     onDragStart, onDragEnd, onEditDone }) {
  const landscape = (l.widthMm || l.width) >= (l.heightMm || l.height)
  return (
    <div
      draggable
      onDragStart={onDragStart}
      onDragEnd={onDragEnd}
      onClick={onSelect}
      onDoubleClick={onActivate}
      onContextMenu={onContextMenu}
      style={{
        display: 'flex', alignItems: 'center', gap: 8,
        padding: '6px 8px',
        border: '1px solid ' + (active ? 'var(--accent)' : 'var(--border-light)'),
        borderRadius: 'var(--r)',
        background: active ? 'var(--bg-item-active)' : 'var(--bg-input)',
        cursor: 'grab',
        userSelect: 'none',
        marginBottom: 4,
        opacity: dragging ? 0.4 : 1,
        transition: 'background 0.14s, border-color 0.14s, opacity 0.14s',
      }}
      onMouseEnter={(ev) => { if (!active && !dragging) ev.currentTarget.style.background = 'var(--bg-item-hover)' }}
      onMouseLeave={(ev) => { if (!active && !dragging) ev.currentTarget.style.background = 'var(--bg-input)' }}
    >
      <input
        type="checkbox"
        checked={checked}
        onClick={(e) => e.stopPropagation()}
        onChange={onCheck}
        style={{ margin: 0, flexShrink: 0 }}
        title="Fuer PDF-Export ankreuzen"
      />
      <OrientationBadge landscape={landscape} />
      <EditableName
        value={l.name}
        onCommit={onRename}
        forceEdit={forceEditName}
        onEditDone={onEditDone}
        style={{
          flex: 1, minWidth: 0,
          color: 'var(--text-primary)', fontWeight: 500,
          overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
        }}
      />
      <span className="chip chip-accent" style={{
        fontSize: 9, fontFamily: 'DM Mono, monospace', fontWeight: 600,
        flexShrink: 0,
      }} title={`${Math.round(l.widthMm || 0)}×${Math.round(l.heightMm || 0)} mm`}>
        {formatLabel(l.widthMm, l.heightMm)}
      </span>
      <button
        className="btn-icon-sm"
        onClick={(ev) => { ev.stopPropagation(); onMenuClick(ev) }}
        title="Aktionen"
      >
        <Icon name="more_vert" size={14} />
      </button>
    </div>
  )
}
