import React, { useState, useCallback, useMemo, useEffect, useRef } from 'react';
import type {
  Theme, RibbonTab, ViewMode, RightPanel, DrawerTab,
  CursorPos, CommandHistoryEntry, KIMessage, KISuggestion,
} from './types/ui.types';
import type { CADElement, CADLayer, BlockDefinition } from './types/cad.types';
import { createDefaultBlocks, BlockService } from './services/blockService';
import { SeatingService } from './services/seatingService';
import type { ToolState } from './interaction';
import { GroupManager, type ElementGroup } from './tools/modification/GroupTool';
import Topbar from './components/Topbar';
import RibbonBar from './components/RibbonBar';
import LeftSidebar from './components/LeftSidebar';
import CanvasArea from './components/CanvasArea';
import RightSidebar from './components/RightSidebar';
import CommandLine from './components/CommandLine';
import StatusBar from './components/StatusBar';
import MobileDrawers from './components/MobileDrawers';
import BackgroundImport from './components/BackgroundImport';
import HistoryPanel from './components/HistoryPanel';
import { BackgroundService, type BackgroundConfig } from './services/backgroundService';
import { HistoryManager, type CADStateSnapshot, type HistoryEntry } from './history';
import { getCommandRegistry } from './services/commandRegistry';
import { importFile, type ImportResult } from './services/importService';
import { exportProject, downloadBlob, type ExportFormat } from './services/exportService';
import type { ProjectData } from './types/cad.types';
import { loadProjectDataTyped, createElementTyped, updateElement, deleteElement as apiDeleteElement, createLayerTyped, updateLayer, deleteLayer as apiDeleteLayer, createBlockTyped, updateBlock, deleteBlock as apiDeleteBlock, aiChat } from './services/api';
import { useYjsBinding } from './crdt';
import { registerBuiltinPlugins, pluginRegistry } from './plugins';
import type { PluginContext } from './plugins';
import './styles.css';
import './styles/auth.css';
import { useAuth } from './contexts/AuthContext';
import { Login } from './pages/Login';
import { Register } from './pages/Register';
import { Dashboard } from './pages/Dashboard';

// ─── Mock Data ──────────────────────────────────────────────
function makeInitialLayers(): CADLayer[] {
  const ts = Date.now();
  return [
    { id: `layer-${ts}-0`, name: 'Wände', visible: true, locked: false, color: '#e74c3c', lineType: 'solid', transparency: 0, sortOrder: 0, parentId: null },
    { id: `layer-${ts}-1`, name: 'Türen', visible: true, locked: false, color: '#3498db', lineType: 'solid', transparency: 0, sortOrder: 1, parentId: null },
    { id: `layer-${ts}-2`, name: 'Bestuhlung', visible: true, locked: false, color: '#2ecc71', lineType: 'solid', transparency: 0, sortOrder: 2, parentId: null },
    { id: `layer-${ts}-3`, name: 'Bühne', visible: true, locked: false, color: '#f39c12', lineType: 'solid', transparency: 0, sortOrder: 3, parentId: null },
    { id: `layer-${ts}-4`, name: 'Hintergrund', visible: true, locked: true, color: '#95a5a6', lineType: 'dotted', transparency: 50, sortOrder: 4, parentId: null },
  ];
}

const initialLayers: CADLayer[] = makeInitialLayers();

const initialBlocks: BlockDefinition[] = createDefaultBlocks();

const initialCommandHistory: CommandHistoryEntry[] = [
  { prefix: '·', text: 'Bereit · Werkzeug: Auswahl · 110 Objekte · 5 Ebenen', type: 'info' },
  { prefix: '·', text: 'Auto-Save aktiv · letzte Speicherung vor 3 Sekunden', type: 'info' },
];

const initialKIMessages: KIMessage[] = [
  { id: 'ki-1', role: 'assistant', content: 'Hallo! Ich bin der KI Copilot. Wie kann ich helfen?' },
];

const initialKISuggestions: KISuggestion[] = [
  { id: 'sug-1', label: 'Bestuhlung automatisch generieren' },
  { id: 'sug-2', label: 'Maße analysieren' },
  { id: 'sug-3', label: 'Flächen berechnen' },
];

// Prevent duplicate drawing creation across StrictMode double-render
const loadedProjects = new Set<string>();

// ─── CAD Editor Component ───────────────────────────────
interface CADEditorProps {
  projectId: string;
  token: string;
  onNavigateBack: () => void;
}

const CADEditor: React.FC<CADEditorProps> = ({ projectId, token, onNavigateBack }) => {
  // Theme
  const [theme, setTheme] = useState<Theme>('dark');

  // Auth user for collaboration
  const { user } = useAuth();

  // Yjs collaboration binding
  const collab = useYjsBinding({
    docName: `project-${projectId}`,
    userId: user?.id || 'anonymous',
    userName: user?.name || 'Gast',
    userColor: '#3498db',
    enabled: true,
  });

  // Project
  const [projectName, setProjectName] = useState('Unbenannt');
  const [savedStatus, setSavedStatus] = useState('Lädt…');
  const [drawingId, setDrawingId] = useState<string | null>(null);

  // Ribbon
  const [activeRibbonTab, setActiveRibbonTab] = useState<RibbonTab>('start');

  // Tools
  const [activeTool, setActiveTool] = useState('select');

  // Canvas / View
  const [viewMode, setViewMode] = useState<ViewMode>('2d');
  const [cursorPos, setCursorPos] = useState<CursorPos>({ x: 0, y: 0 });
  const [gridEnabled, setGridEnabled] = useState(true);
  const [orthoEnabled, setOrthoEnabled] = useState(false);
  const [snapEnabled, setSnapEnabled] = useState(true);
  const [polarEnabled, setPolarEnabled] = useState(false);

  // Right sidebar
  const [activeRightPanel, setActiveRightPanel] = useState<RightPanel>('tool');
  const [selectedElement, setSelectedElement] = useState<CADElement | null>(null);
  const [layers, setLayers] = useState<CADLayer[]>(initialLayers);
  const [activeLayerId, setActiveLayerId] = useState<string>(initialLayers[0].id);
  const [blocks, setBlocks] = useState<BlockDefinition[]>(initialBlocks);
  const [blockCategory, setBlockCategory] = useState('Alle');
  const [selectedTemplate, setSelectedTemplate] = useState<string | null>(null);

  // Command line
  const [commandHistory, setCommandHistory] = useState<CommandHistoryEntry[]>(initialCommandHistory);

  // KI Copilot
  const [kiMessages, setKIMessages] = useState<KIMessage[]>(initialKIMessages);
  const [kiSuggestions] = useState<KISuggestion[]>(initialKISuggestions);
  const [kiLoading, setKiLoading] = useState(false);

  // Plugin system
  useEffect(() => {
    const ctx: PluginContext = {
      addElement: (el) => setElements((prev) => [...prev, el]),
      removeElement: (id) => setElements((prev) => prev.filter((e) => e.id !== id)),
      updateElement: (id, props) => setElements((prev) => prev.map((e) => (e.id === id ? { ...e, ...props } : e))),
      getElements: () => elements,
      getLayers: () => layers,
      getActiveLayerId: () => activeLayerId,
      showToast: (msg) => setCommandHistory((prev) => [...prev, { prefix: '·', text: msg, type: 'info' }]),
      log: (msg) => console.log(`[Plugin] ${msg}`),
    };
    pluginRegistry.setContext(ctx);
    registerBuiltinPlugins();
    pluginRegistry.initDefaults();
  }, []);

  // Status bar
  const onlineCount = collab.cursors.length + 1;

  // Mobile drawers
  const [mobileLeftOpen, setMobileLeftOpen] = useState(false);
  const [mobileRightOpen, setMobileRightOpen] = useState(false);
  const [activeDrawerTab, setActiveDrawerTab] = useState<DrawerTab>('tool');

  // Background
  const [bgImportOpen, setBgImportOpen] = useState(false);
  const [bgConfig, setBgConfig] = useState<BackgroundConfig | null>(null);
  const bgServiceRef = React.useRef<BackgroundService>(new BackgroundService());

  // History panel
  const [historyPanelOpen, setHistoryPanelOpen] = useState(false);

  // Elements + undo/redo (HistoryManager)
  const [elements, setElements] = useState<CADElement[]>([]);
  const historyManagerRef = React.useRef<HistoryManager>(new HistoryManager());
  const [historyEntries, setHistoryEntries] = useState<HistoryEntry[]>([]);
  const [toolState, setToolState] = useState<ToolState | null>(null);

  const seatCount = useMemo(() => {
    const svc = new SeatingService();
    return svc.countSeats(elements).total;
  }, [elements]);

  // Groups
  const groupManagerRef = React.useRef(new GroupManager());
  const [groups, setGroups] = useState<ElementGroup[]>([]);

  // Clipboard (for copy/paste)
  const clipboardRef = React.useRef<CADElement[] | null>(null);

  // ─── Handlers ───────────────────────────────────────────
  const handleThemeToggle = useCallback(() => {
    setTheme((prev) => (prev === 'dark' ? 'light' : 'dark'));
  }, []);

  const syncHistory = useCallback(() => {
    setHistoryEntries(historyManagerRef.current.getHistory());
  }, []);

  const restoreSnapshot = useCallback((snap: CADStateSnapshot) => {
    setElements(snap.elements);
    setLayers(snap.layers);
    setBlocks(snap.blocks);
    setGroups(snap.groups);
    setBgConfig(snap.bgConfig);
  }, []);

  const handleUndo = useCallback(() => {
    const snap = historyManagerRef.current.undo();
    if (snap) {
      restoreSnapshot(snap);
      syncHistory();
      setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Rückgängig: letzte Aktion', type: 'info' }]);
    }
  }, [restoreSnapshot, syncHistory]);

  const handleRedo = useCallback(() => {
    const snap = historyManagerRef.current.redo();
    if (snap) {
      restoreSnapshot(snap);
      syncHistory();
      setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Wiederherstellen: letzte Aktion', type: 'info' }]);
    }
  }, [restoreSnapshot, syncHistory]);

  const pushHistorySnapshot = useCallback((label: string) => {
    historyManagerRef.current.pushSnapshot({
      elements,
      layers,
      blocks,
      groups,
      bgConfig,
    }, label);
    syncHistory();
  }, [elements, layers, blocks, groups, bgConfig, syncHistory]);

  // Initialize HistoryManager with initial state on mount
  const historyInitRef = React.useRef(false);
  React.useEffect(() => {
    if (historyInitRef.current) return;
    historyInitRef.current = true;
    historyManagerRef.current.initialize({
      elements: [],
      layers: initialLayers,
      blocks: initialBlocks,
      groups: [],
      bgConfig: null,
    });
    syncHistory();
  }, [syncHistory]);

  // Load project data from backend on mount
  const [dataLoaded, setDataLoaded] = useState(false);
  React.useEffect(() => {
    if (!projectId || !token) return;
    let cancelled = false;
    (async () => {
      try {
        setSavedStatus('Lädt…');
        const data = await loadProjectDataTyped(token, projectId);
        if (cancelled) return;
        setProjectName(data.project.name);
        setDrawingId(data.drawing?.id || null);
        if (data.elements.length > 0) setElements(data.elements);
        if (data.layers.length > 0) setLayers(data.layers);
        if (data.blocks.length > 0) setBlocks(data.blocks);
        // Save initial layers to backend if backend has none
        if (data.layers.length === 0 && data.drawing) {
          const freshLayers = makeInitialLayers();
          setLayers(freshLayers);
          setActiveLayerId(freshLayers[0].id);
          for (const layer of freshLayers) {
            createLayerTyped(token, data.drawing.id, layer).catch(() => {});
          }
        } else {
          setActiveLayerId(data.layers[0]?.id ?? initialLayers[0].id);
        }
        setSavedStatus('gespeichert');
        setDataLoaded(true);
        // Push initial data to Yjs CRDT after load
        if (collab.status === 'connected') {
          collab.loadFromState({ elements: data.elements, layers: data.layers, blocks: data.blocks });
        }
      } catch (err) {
        console.error('Failed to load project:', err);
        setSavedStatus('Fehler beim Laden');
      }
    })();
    return () => { cancelled = true; };
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [projectId, token]);

  // Sync remote → local: when Yjs data changes from other users, update local state
  React.useEffect(() => {
    if (collab.status !== 'connected') return;
    // Skip if collab data is empty (not yet loaded)
    if (collab.elements.length === 0 && collab.layers.length === 0 && collab.blocks.length === 0) return;

    // Only update local state if remote data differs AND local is not ahead of remote
    // (prevents race condition where local element is overwritten by stale Yjs sync)
    const localIds = new Set(elements.map(e => e.id));
    const remoteIds = new Set(collab.elements.map(e => e.id));
    const localHasExtra = elements.some(e => !remoteIds.has(e.id));
    const remoteHasExtra = collab.elements.some(e => !localIds.has(e.id));
    // Only sync from remote if remote has elements local doesn't have AND local doesn't have unsaved elements
    if (remoteHasExtra && !localHasExtra) {
      setElements(collab.elements);
    } else if (remoteHasExtra && localHasExtra) {
      // Merge: keep local elements, update any that changed remotely
      const merged = elements.map(el => {
        const remote = collab.elements.find(e => e.id === el.id);
        return remote || el;
      });
      // Add remote-only elements
      collab.elements.forEach(el => { if (!localIds.has(el.id)) merged.push(el); });
      setElements(merged);
    }

    const sameLayers = collab.layers.length === layers.length &&
      collab.layers.every((l, i) => l.id === layers[i]?.id);
    if (!sameLayers) setLayers(collab.layers);

    const sameBlocks = collab.blocks.length === blocks.length &&
      collab.blocks.every((b, i) => b.id === blocks[i]?.id);
    if (!sameBlocks) setBlocks(collab.blocks);
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [collab.elements, collab.layers, collab.blocks, collab.status]);

  const handleElementCreated = useCallback((el: CADElement) => {
    const elWithLayer = el.layerId ? el : { ...el, layerId: activeLayerId };
    setElements((prev) => {
      const newElements = [...prev, elWithLayer];
      historyManagerRef.current.pushSnapshot({
        elements: newElements, layers, blocks, groups, bgConfig,
      }, 'Element erstellt');
      return newElements;
    });
    syncHistory();
    // Push to Yjs CRDT for real-time sync
    collab.setElement(elWithLayer);
    // Save to backend
    if (drawingId && token) {
      setSavedStatus('Speichert…');
      createElementTyped(token, drawingId, elWithLayer).then(() => {
        setSavedStatus('gespeichert');
      }).catch((err) => {
        console.error('Failed to save element:', err);
        setSavedStatus('Fehler beim Speichern');
      });
    }
  }, [layers, blocks, groups, bgConfig, syncHistory, drawingId, token, collab, activeLayerId]);

  const handleElementsDeleted = useCallback((ids: string[]) => {
    setElements((prev) => {
      const newElements = prev.filter((e) => !ids.includes(e.id));
      historyManagerRef.current.pushSnapshot({
        elements: newElements, layers, blocks, groups, bgConfig,
      }, `${ids.length} Element(e) gelöscht`);
      return newElements;
    });
    syncHistory();
    // Push deletions to Yjs CRDT for real-time sync
    ids.forEach(id => collab.deleteElement(id));
    // Delete from backend
    if (token) {
      setSavedStatus('Speichert…');
      Promise.all(ids.map(id => apiDeleteElement(token, id))).then(() => {
        setSavedStatus('gespeichert');
      }).catch((err) => {
        console.error('Failed to delete elements:', err);
        setSavedStatus('Fehler beim Speichern');
      });
    }
  }, [elements, layers, blocks, groups, bgConfig, syncHistory, token, collab]);

  const handleElementsModified = useCallback((modified: CADElement[]) => {
    setElements((prev) => {
      const newElements = prev.map((e) => {
        const found = modified.find((m) => m.id === e.id);
        return found ?? e;
      });
      historyManagerRef.current.pushSnapshot({
        elements: newElements, layers, blocks, groups, bgConfig,
      }, `${modified.length} Element(e) geändert`);
      return newElements;
    });
    syncHistory();
    // Push modifications to Yjs CRDT for real-time sync
    modified.forEach(el => collab.setElement(el));
    // Update in backend
    if (token) {
      setSavedStatus('Speichert…');
      Promise.all(modified.map(el => updateElement(token, el.id, el))).then(() => {
        setSavedStatus('gespeichert');
      }).catch((err) => {
        console.error('Failed to update elements:', err);
        setSavedStatus('Fehler beim Speichern');
      });
    }
  }, [layers, blocks, groups, bgConfig, syncHistory, token, collab]);

  const lastCursorUpdateRef = useRef(0);
  const handleCursorMoved = useCallback((x: number, y: number) => {
    const now = performance.now();
    if (now - lastCursorUpdateRef.current < 33) return; // throttle to ~30fps
    lastCursorUpdateRef.current = now;
    setCursorPos({ x, y });
    collab.setCursor(x, y);
  }, [collab]);

  const handleToolStateChanged = useCallback((state: ToolState) => {
    setToolState(state);
  }, []);

  const handleTextEdit = useCallback((el: CADElement) => {
    const text = window.prompt('Text eingeben:', '');
    if (text !== null && text.trim() !== '') {
      setElements((prev) => prev.map((e) =>
        e.id === el.id ? { ...e, properties: { ...e.properties, text } } : e
      ));
    }
  }, []);

  const handleCommandTrigger = useCallback((msg: string) => {
    setCommandHistory((prev) => [...prev, { prefix: '·', text: msg, type: 'info' }]);
  }, []);

  // Block management handlers
  const handleRenameBlock = useCallback((id: string, name: string) => {
    setBlocks((prev) => prev.map((b) => b.id === id ? { ...b, name } : b));
    setCommandHistory((prev) => [...prev, { prefix: '·', text: `Block umbenannt: ${name}`, type: 'info' }]);
  }, []);

  const handleDuplicateBlock = useCallback((id: string) => {
    setBlocks((prev) => {
      const block = prev.find((b) => b.id === id);
      if (!block) return prev;
      const newId = `blk-${Date.now()}`;
      const copy: BlockDefinition = {
        ...block,
        id: newId,
        name: `${block.name} (Kopie)`,
        elements: block.elements.map((el) => ({ ...el, id: `${el.id}_copy_${Date.now()}` })),
      };
      return [...prev, copy];
    });
    setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Block dupliziert', type: 'info' }]);
  }, []);

  const handleDeleteBlock = useCallback((id: string) => {
    setBlocks((prev) => prev.filter((b) => b.id !== id));
    setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Block gelöscht', type: 'info' }]);
    // Delete from backend
    if (token) {
      apiDeleteBlock(token, id).catch((err) => {
        console.error('Failed to delete block:', err);
      });
    }
  }, [token]);

  const handleSvgImport = useCallback((svg: string, name: string, category: string) => {
    const svc = new BlockService();
    const block = svc.importSVG(svg, name, category);
    setBlocks((prev) => [...prev, block]);
    setCommandHistory((prev) => [...prev, { prefix: '·', text: `SVG importiert: ${name}`, type: 'info' }]);
  }, []);

  const handleSaveGroupAsBlock = useCallback((name: string) => {
    const selectedEls = selectedElement ? [selectedElement] : [];
    setBlocks((prev) => {
      const newId = `blk_grp_${Date.now()}`;
      const block: BlockDefinition = {
        id: newId,
        name,
        description: 'Aus Auswahl erstellt',
        category: 'Custom',
        elements: selectedEls.map(el => ({ ...el, id: `el_${Date.now()}_${Math.random().toString(36).slice(2, 7)}` })),
      };
      return [...prev, block];
    });
    setCommandHistory((prev) => [...prev, { prefix: '·', text: `Block erstellt: ${name} (${selectedEls.length} Elemente)`, type: 'info' }]);
  }, [selectedElement]);

  const handleBlockCategoryChange = useCallback((cat: string) => {
    setBlockCategory(cat);
  }, []);

  const handleTemplateSelect = useCallback((templateName: string | null) => {
    setSelectedTemplate(templateName);
    if (templateName) {
      setCommandHistory((prev) => [...prev, { prefix: '·', text: `Vorlage gewählt: ${templateName} – Klicken zum Platzieren`, type: 'info' }]);
    }
  }, []);

  const handleBlockSearch = useCallback((_query: string) => {
    // Search is handled locally in BlockLibrary component
  }, []);

  const handleDragBlock = useCallback((blockId: string) => {
    setCommandHistory((prev) => [...prev, { prefix: '·', text: `Block gezogen: ${blockId}`, type: 'info' }]);
  }, []);

  const handleBlockDrop = useCallback((blockId: string, x: number, y: number) => {
    const svc = new BlockService();
    blocks.forEach(b => svc.addBlock(b));
    const instance = svc.createInstance(blockId, x, y, activeLayerId);
    if (instance) {
      setElements((prev) => [...prev, instance]);
      setCommandHistory((prev) => [...prev, { prefix: '·', text: `Block platziert: ${blockId} bei (${x.toFixed(2)}, ${y.toFixed(2)})`, type: 'info' }]);
    }
  }, [blocks, activeLayerId]);

  const handleSelectionChange = useCallback((selectedIds: string[]) => {
    if (selectedIds.length === 1) {
      const el = elements.find(e => e.id === selectedIds[0]);
      setSelectedElement(el ?? null);
    } else {
      setSelectedElement(null);
    }
  }, [elements]);

  const handleImport = useCallback(async (file: File) => {
    setCommandHistory((prev) => [...prev, { prefix: '·', text: `Importiere ${file.name}...`, type: 'info' }]);
    const result = await importFile(file);
    if (result.success) {
      setElements((prev) => [...prev, ...result.elements]);
      if (result.layers && result.layers.length > 0) {
        setLayers((prev) => {
          const existingIds = new Set(prev.map(l => l.id));
          const newLayers = result.layers!.filter(l => !existingIds.has(l.id));
          return [...prev, ...newLayers];
        });
      }
      if (result.blocks && result.blocks.length > 0) {
        setBlocks((prev) => [...prev, ...result.blocks!]);
      }
      setCommandHistory((prev) => [...prev, { prefix: '·', text: `Importiert: ${result.elements.length} Elemente aus ${file.name}`, type: 'info' }]);
      if (result.warnings.length > 0) {
        result.warnings.forEach(w => setCommandHistory((prev) => [...prev, { prefix: '·', text: w, type: 'info' }]));
      }
    } else {
      setCommandHistory((prev) => [...prev, { prefix: '·', text: `Import fehlgeschlagen: ${result.error || 'Unbekannter Fehler'}`, type: 'info' }]);
    }
  }, []);

  const handleExport = useCallback(async (format: ExportFormat) => {
    const projectData: ProjectData = {
      version: '1.0',
      name: projectName,
      layers,
      elements,
      blocks,
    };
    setCommandHistory((prev) => [...prev, { prefix: '·', text: `Exportiere als ${format.toUpperCase()}...`, type: 'info' }]);
    const result = await exportProject(projectData, { format });
    if (result.success && result.blob) {
      downloadBlob(result.blob, result.filename);
      setCommandHistory((prev) => [...prev, { prefix: '·', text: `Exportiert: ${result.filename}`, type: 'info' }]);
    } else {
      setCommandHistory((prev) => [...prev, { prefix: '·', text: `Export fehlgeschlagen: ${result.error || 'Unbekannter Fehler'}`, type: 'info' }]);
    }
  }, [layers, elements, blocks]);

  const handleRibbonAction = useCallback((action: string) => {
    setCommandHistory((prev) => [...prev, { prefix: '›', text: action, type: 'command' }]);

    // ─── File actions ───
    if (action === 'new') {
      onNavigateBack();
      return;
    }
    if (action === 'open') {
      onNavigateBack();
      return;
    }
    if (action === 'save') {
      setSavedStatus('Gespeichert');
      setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Projekt gespeichert', type: 'info' }]);
      // Save elements to backend if drawingId exists
      if (drawingId && token) {
        elements.forEach((el) => {
          if (!el.id.startsWith('el-')) return;
          updateElement(token, el.id, el).catch(() => {});
        });
      }
      return;
    }
    if (action === 'import') {
      const input = document.createElement('input');
      input.type = 'file';
      input.accept = '.dxf,.svg,.json';
      input.onchange = () => {
        if (input.files && input.files[0]) {
          handleImport(input.files[0]);
        }
      };
      input.click();
      return;
    }
    if (action === 'export') {
      const input = document.createElement('input');
      input.type = 'file';
      input.setAttribute('nwsave', '');
      input.accept = '.dxf,.svg,.pdf,.png,.json';
      input.onchange = () => {
        const name = input.value || 'cad-export';
        const ext = name.split('.').pop()?.toLowerCase() as ExportFormat;
        if (ext && ['dxf', 'svg', 'pdf', 'png', 'json'].includes(ext)) {
          handleExport(ext);
        } else {
          handleExport('dxf');
        }
      };
      input.click();
      return;
    }

    // ─── Edit actions ───
    if (action === 'undo') { handleUndo(); return; }
    if (action === 'redo') { handleRedo(); return; }
    if (action === 'copy') {
      const selected = elements.filter((e) => (e as any).selected);
      const clip = selected.length > 0 ? selected : elements.slice(0, 1);
      clipboardRef.current = clip;
      setCommandHistory((prev) => [...prev, { prefix: '·', text: `${clip.length} Element(e) kopiert`, type: 'info' }]);
      return;
    }
    if (action === 'paste') {
      if (clipboardRef.current && clipboardRef.current.length > 0) {
        const offset = 20;
        const pasted = clipboardRef.current.map((el, i) => ({
          ...el,
          id: `el-${Date.now()}-${i}`,
          x: (el as any).x ? (el as any).x + offset : undefined,
          y: (el as any).y ? (el as any).y + offset : undefined,
        }));
        setElements((prev) => [...prev, ...pasted]);
        setCommandHistory((prev) => [...prev, { prefix: '·', text: `${pasted.length} Element(e) eingefügt`, type: 'info' }]);
      } else {
        setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Zwischenablage leer', type: 'info' }]);
      }
      return;
    }

    // ─── Insert actions (set active tool) ───
    if (action === 'insert-line') { setActiveTool('line'); setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Linie-Werkzeug aktiv', type: 'info' }]); return; }
    if (action === 'insert-rect') { setActiveTool('rect'); setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Rechteck-Werkzeug aktiv', type: 'info' }]); return; }
    if (action === 'insert-circle') { setActiveTool('circle'); setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Kreis-Werkzeug aktiv', type: 'info' }]); return; }
    if (action === 'insert-text') { setActiveTool('text'); setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Text-Werkzeug aktiv', type: 'info' }]); return; }
    if (action === 'insert-freehand') { setActiveTool('polyline'); setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Freihand-Werkzeug aktiv', type: 'info' }]); return; }
    if (action === 'insert-image') {
      const input = document.createElement('input');
      input.type = 'file';
      input.accept = 'image/*';
      input.onchange = () => {
        if (input.files && input.files[0]) {
          const reader = new FileReader();
          reader.onload = () => {
            const imgEl: CADElement = {
              id: `el-${Date.now()}`,
              type: 'image' as any,
              layerId: activeLayerId,
              x: 0, y: 0,
              properties: { src: reader.result as string, width: 200, height: 200 },
            } as any;
            setElements((prev) => [...prev, imgEl]);
            setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Bild eingefügt', type: 'info' }]);
          };
          reader.readAsDataURL(input.files[0]);
        }
      };
      input.click();
      return;
    }

    // ─── Format actions ───
    if (action.startsWith('format-')) {
      setCommandHistory((prev) => [...prev, { prefix: '·', text: `Format: ${action.replace('format-', '')} (Auswahl erforderlich)`, type: 'info' }]);
      return;
    }

    // ─── View actions ───
    if (action === 'zoom-fit') {
      setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Zoom: an Ansicht angepasst', type: 'info' }]);
      return;
    }
    if (action === 'zoom-100') {
      setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Zoom: 100%', type: 'info' }]);
      return;
    }
    if (action === 'grid') {
      setGridEnabled((p) => !p);
      setCommandHistory((prev) => [...prev, { prefix: '·', text: `Grid ${gridEnabled ? 'aus' : 'ein'}`, type: 'info' }]);
      return;
    }
    if (action === 'layer') { setActiveRightPanel('layer'); setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Layer-Manager geöffnet', type: 'info' }]); return; }

    // ─── Tools actions ───
    if (action === 'measure') { setActiveTool('dimension'); setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Messwerkzeug aktiv', type: 'info' }]); return; }
    if (action === 'search') {
      setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Suche: Befehlszeile verwenden (Strg+F)', type: 'info' }]);
      return;
    }
    if (action === 'plugins') { setActiveRightPanel('plugins'); setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Plugin-Manager geöffnet', type: 'info' }]); return; }
    if (action === 'history') { setHistoryPanelOpen((prev) => !prev); return; }

    // ─── Background ───
    if (action === 'background-import') { setBgImportOpen(true); return; }

    // ─── KI actions ───
    if (action === 'ki') { setActiveRightPanel('ki'); setCommandHistory((prev) => [...prev, { prefix: '·', text: 'KI Copilot geöffnet', type: 'info' }]); return; }
    if (action === 'ki-draw') { setActiveRightPanel('ki'); setCommandHistory((prev) => [...prev, { prefix: '·', text: 'KI Zeichnen: Beschreibung eingeben', type: 'info' }]); return; }
    if (action === 'ki-analyze') { setActiveRightPanel('ki'); setCommandHistory((prev) => [...prev, { prefix: '·', text: 'KI Analyse gestartet', type: 'info' }]); return; }
  }, [handleUndo, handleRedo, handleImport, handleExport, onNavigateBack, drawingId, token, elements, activeLayerId, gridEnabled]);

  const handleToolChange = useCallback((tool: string) => {
    setActiveTool(tool);
    setMobileLeftOpen(false);
  }, []);

  const handleViewChange = useCallback((mode: ViewMode) => {
    setViewMode(mode);
  }, []);

  const handleToggleGrid = useCallback(() => setGridEnabled((p) => !p), []);
  const handleToggleOrtho = useCallback(() => setOrthoEnabled((p) => !p), []);
  const handleToggleSnap = useCallback(() => setSnapEnabled((p) => !p), []);
  const handleTogglePolar = useCallback(() => setPolarEnabled((p) => !p), []);

  // Layer handlers
  const handleSelectLayer = useCallback((id: string) => setActiveLayerId(id), []);
  const handleAddLayer = useCallback(() => {
    setLayers((prev) => {
      const newId = `layer-${Date.now()}`;
      const newLayer: CADLayer = {
        id: newId, name: `Layer ${prev.length + 1}`, visible: true, locked: false,
        color: '#ffffff', lineType: 'solid', transparency: 0,
        sortOrder: prev.length, parentId: null,
      };
      // Save to backend
      if (drawingId && token) {
        createLayerTyped(token, drawingId, newLayer).catch((err) => {
          console.error('Failed to save layer:', err);
        });
      }
      return [...prev, newLayer];
    });
  }, [drawingId, token]);
  const handleToggleLayer = useCallback((id: string) => {
    setLayers((prev) => prev.map((l) => l.id === id ? { ...l, visible: !l.visible } : l));
  }, []);
  const handleDeleteLayer = useCallback((id: string) => {
    setLayers((prev) => prev.filter((l) => l.id !== id));
    // Delete from backend
    if (token) {
      apiDeleteLayer(token, id).catch((err) => {
        console.error('Failed to delete layer:', err);
      });
    }
  }, [token]);
  const handleRenameLayer = useCallback((id: string, name: string) => {
    setLayers((prev) => prev.map((l) => l.id === id ? { ...l, name } : l));
  }, []);
  const handleDuplicateLayer = useCallback((id: string) => {
    setLayers((prev) => {
      const layer = prev.find((l) => l.id === id);
      if (!layer) return prev;
      const newId = `layer-${Date.now()}`;
      const copy: CADLayer = { ...layer, id: newId, name: `${layer.name} (Kopie)`, sortOrder: prev.length };
      return [...prev, copy];
    });
  }, []);
  const handleToggleLock = useCallback((id: string) => {
    setLayers((prev) => prev.map((l) => l.id === id ? { ...l, locked: !l.locked } : l));
  }, []);
  const handleUpdateLayerColor = useCallback((id: string, color: string) => {
    setLayers((prev) => prev.map((l) => l.id === id ? { ...l, color } : l));
  }, []);
  const handleUpdateLayerLineType = useCallback((id: string, lineType: 'solid' | 'dashed' | 'dotted') => {
    setLayers((prev) => prev.map((l) => l.id === id ? { ...l, lineType } : l));
  }, []);
  const handleUpdateLayerTransparency = useCallback((id: string, transparency: number) => {
    setLayers((prev) => prev.map((l) => l.id === id ? { ...l, transparency } : l));
  }, []);

  const handleZoomIn = useCallback(() => {
    setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Zoom: vergrößert', type: 'info' }]);
  }, []);
  const handleZoomOut = useCallback(() => {
    setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Zoom: verkleinert', type: 'info' }]);
  }, []);
  const handleZoomFit = useCallback(() => {
    setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Zoom: an Ansicht angepasst', type: 'info' }]);
  }, []);

  const handleBgApply = useCallback((config: BackgroundConfig, _image: HTMLImageElement | null) => {
    setBgConfig(config);
    setBgImportOpen(false);
    setCommandHistory((prev) => [...prev, { prefix: '·', text: `Hintergrund geladen: ${config.name} (${config.width}×${config.height}px, Maßstab: ${config.scale.toFixed(3)} px/mm)`, type: 'info' }]);
  }, []);

  const handleCommand = useCallback((cmd: string) => {
    const upper = cmd.trim().toUpperCase();
    setCommandHistory((prev) => [...prev, { prefix: '›', text: cmd, type: 'command' }]);

    const registry = getCommandRegistry();

    if (upper === 'UNDO' || upper === 'U') {
      handleUndo();
      return;
    }
    if (upper === 'REDO') {
      handleRedo();
      return;
    }

    // Group command: create group from currently selected elements
    if (upper === 'GROUP' || upper === 'GRP') {
      const gm = groupManagerRef.current;
      // For now, group all elements (selection state is in InteractionEngine, not accessible here)
      // In a full implementation, we'd need selected IDs from the interaction engine
      setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Gruppe erstellt (Auswahl im Canvas erforderlich)', type: 'info' }]);
      setGroups(gm.getGroups());
      return;
    }

    // Ungroup command
    if (upper === 'UNG' || upper === 'UNGROUP') {
      const gm = groupManagerRef.current;
      const allGroups = gm.getGroups();
      if (allGroups.length > 0) {
        gm.ungroup(allGroups[allGroups.length - 1].id);
        setGroups(gm.getGroups());
        setCommandHistory((prev) => [...prev, { prefix: '·', text: 'Gruppe aufgelöst', type: 'info' }]);
      }
      return;
    }

    // Import command — trigger file dialog
    if (upper === 'IMPORT' || upper === 'IMP' || upper === 'I') {
      handleRibbonAction('import');
      return;
    }
    // Export command — trigger export dialog
    if (upper === 'EXPORT' || upper === 'EXP' || upper === 'EX') {
      handleRibbonAction('export');
      return;
    }

    const tool = registry.getToolId(upper);
    if (tool) {
      setActiveTool(tool);
      setMobileLeftOpen(false);
      const label = registry.getLabel(upper) ?? `Werkzeug: ${tool}`;
      setCommandHistory((prev) => [...prev, { prefix: '·', text: label, type: 'info' }]);
    } else {
      // Check plugin commands
      const pluginCmds = pluginRegistry.getCommandExtensions();
      const parts = cmd.trim().split(/\s+/);
      const cmdName = parts[0].toUpperCase();
      const pluginCmd = pluginCmds.find((c) => c.name.toUpperCase() === cmdName);
      if (pluginCmd) {
        const ctx: PluginContext = {
          addElement: (el) => setElements((prev) => [...prev, el]),
          removeElement: (id) => setElements((prev) => prev.filter((e) => e.id !== id)),
          updateElement: (id, props) => setElements((prev) => prev.map((e) => (e.id === id ? { ...e, ...props } : e))),
          getElements: () => elements,
          getLayers: () => layers,
          getActiveLayerId: () => activeLayerId,
          showToast: (msg) => setCommandHistory((prev) => [...prev, { prefix: '·', text: msg, type: 'info' }]),
          log: (msg) => console.log(`[Plugin] ${msg}`),
        };
        pluginCmd.execute(parts.slice(1), ctx);
      } else {
        setCommandHistory((prev) => [...prev, { prefix: '·', text: `Unbekannter Befehl: ${cmd}`, type: 'info' }]);
      }
    }
  }, [handleUndo, handleRedo, handleRibbonAction]);

  const handleKISend = useCallback(async (text: string) => {
    const userMsg: KIMessage = { id: `ki-${Date.now()}`, role: 'user', content: text };
    const pendingId = `ki-${Date.now() + 1}`;
    const pendingMsg: KIMessage = { id: pendingId, role: 'assistant', content: '…' };
    setKIMessages((prev) => [...prev, userMsg, pendingMsg]);
    setKiLoading(true);

    try {
      // Build CAD context
      const elementTypeSummary: Record<string, number> = {};
      for (const el of elements) {
        elementTypeSummary[el.type] = (elementTypeSummary[el.type] || 0) + 1;
      }
      const context = {
        projectName,
        elementCount: elements.length,
        layerCount: layers.length,
        elementTypeSummary,
      };

      // Build message history (last 10 messages)
      const history = kiMessages.slice(-10).map((m) => ({
        role: m.role,
        content: typeof m.content === 'string' ? m.content : String(m.content),
      }));
      history.push({ role: 'user', content: text });

      const result = await aiChat(token, history, context);

      setKIMessages((prev) =>
        prev.map((m) =>
          m.id === pendingId
            ? { ...m, content: result.content }
            : m
        )
      );
    } catch (err: any) {
      setKIMessages((prev) =>
        prev.map((m) =>
          m.id === pendingId
            ? { ...m, content: `Fehler: ${err.message || 'KI-Anfrage fehlgeschlagen'}` }
            : m
        )
      );
    } finally {
      setKiLoading(false);
    }
  }, [token, projectName, elements, layers, kiMessages]);

  const handleSuggestionClick = useCallback((suggestion: KISuggestion) => {
    handleKISend(suggestion.label);
  }, [handleKISend]);

  const activeLayerName = layers.find((l) => l.id === activeLayerId)?.name ?? '—';

  // ─── Render ─────────────────────────────────────────────
  return (
    <div className={`app ${theme}`} data-theme={theme}>
      <Topbar
        projectName={projectName}
        savedStatus={savedStatus}
        onUndo={handleUndo}
        onRedo={handleRedo}
        onThemeToggle={handleThemeToggle}
        theme={theme}
      />
      <RibbonBar
        activeTab={activeRibbonTab}
        onTabChange={setActiveRibbonTab}
        onAction={handleRibbonAction}
      />
      <div className="app-body">
        <LeftSidebar
          activeTool={activeTool}
          onToolChange={handleToolChange}
          selectedTemplate={selectedTemplate}
          onTemplateSelect={handleTemplateSelect}
        />
        <CanvasArea
          cursorPos={cursorPos}
          viewMode={viewMode}
          onViewChange={handleViewChange}
          gridEnabled={gridEnabled}
          orthoEnabled={orthoEnabled}
          snapEnabled={snapEnabled}
          polarEnabled={polarEnabled}
          activeTool={activeTool}
          elements={elements}
          layers={layers}
          onElementCreated={handleElementCreated}
          onElementsDeleted={handleElementsDeleted}
          onElementsModified={handleElementsModified}
          onCursorMoved={handleCursorMoved}
          onToolStateChanged={handleToolStateChanged}
          onToggleGrid={handleToggleGrid}
          onToggleOrtho={handleToggleOrtho}
          onToggleSnap={handleToggleSnap}
          onZoomIn={handleZoomIn}
          onZoomOut={handleZoomOut}
          onZoomFit={handleZoomFit}
          onTextEdit={handleTextEdit}
          onCommandTrigger={handleCommandTrigger}
          blocks={blocks}
          onBlockDrop={handleBlockDrop}
          onSelectionChange={handleSelectionChange}
          selectedTemplate={selectedTemplate}
          bgConfig={bgConfig}
          remoteCursors={collab.cursors}
        />
        <RightSidebar
          activePanel={activeRightPanel}
          onPanelChange={setActiveRightPanel}
          selectedElement={selectedElement}
          layers={layers}
          blocks={blocks}
          activeLayerId={activeLayerId}
          onSelectLayer={handleSelectLayer}
          onAddLayer={handleAddLayer}
          onToggleLayer={handleToggleLayer}
          onDeleteLayer={handleDeleteLayer}
          onRenameLayer={handleRenameLayer}
          onDuplicateLayer={handleDuplicateLayer}
          onToggleLock={handleToggleLock}
          onUpdateLayerColor={handleUpdateLayerColor}
          onUpdateLayerLineType={handleUpdateLayerLineType}
          onUpdateLayerTransparency={handleUpdateLayerTransparency}
          onRenameBlock={handleRenameBlock}
          onDuplicateBlock={handleDuplicateBlock}
          onDeleteBlock={handleDeleteBlock}
          onSvgImport={handleSvgImport}
          onSaveGroupAsBlock={handleSaveGroupAsBlock}
          onBlockCategoryChange={handleBlockCategoryChange}
          onBlockSearch={handleBlockSearch}
          onDragBlock={handleDragBlock}
          kiMessages={kiMessages}
          kiSuggestions={kiSuggestions}
          onKISend={handleKISend}
          onKISuggestionClick={handleSuggestionClick}
          kiLoading={kiLoading}
        />
      </div>
      <CommandLine
        history={commandHistory}
        onCommand={handleCommand}
      />
      <StatusBar
        snapEnabled={snapEnabled}
        orthoEnabled={orthoEnabled}
        polarEnabled={polarEnabled}
        gridEnabled={gridEnabled}
        cursorX={cursorPos.x}
        cursorY={cursorPos.y}
        activeLayer={activeLayerName}
        activeTool={activeTool}
        onlineCount={onlineCount}
        onToggleSnap={handleToggleSnap}
        onToggleOrtho={handleToggleOrtho}
        onTogglePolar={handleTogglePolar}
        onToggleGrid={handleToggleGrid}
        seatCount={seatCount}
      />
      <MobileDrawers
        leftOpen={mobileLeftOpen}
        rightOpen={mobileRightOpen}
        activeRightTab={activeDrawerTab}
        onCloseLeft={() => setMobileLeftOpen(false)}
        onCloseRight={() => setMobileRightOpen(false)}
        onRightTabChange={setActiveDrawerTab}
      />
      <BackgroundImport
        open={bgImportOpen}
        onClose={() => setBgImportOpen(false)}
        onApply={handleBgApply}
        backgroundService={bgServiceRef.current}
      />
      {historyPanelOpen && (
        <HistoryPanel
          entries={historyEntries}
          onJumpTo={(entryId: string) => {
            const snap = historyManagerRef.current.jumpTo(entryId);
            if (snap) {
              restoreSnapshot(snap);
              syncHistory();
              setCommandHistory((prev) => [...prev, { prefix: '·', text: `Historie: zu „${snap.label}“ gesprungen`, type: 'info' }]);
            }
          }}
          onClose={() => setHistoryPanelOpen(false)}
        />
      )}
    </div>
  );
};

// ─── App Wrapper (Auth Gate) ───────────────────────────
const App: React.FC = () => {
  const { user, token } = useAuth();
  const [authView, setAuthView] = useState<'login' | 'register'>('login');
  const [openedProjectId, setOpenedProjectId] = useState<string | null>(null);

  // Not authenticated → show Login or Register
  if (!user || !token) {
    return authView === 'login'
      ? <Login onSwitchToRegister={() => setAuthView('register')} />
      : <Register onSwitchToLogin={() => setAuthView('login')} />;
  }

  // Authenticated but no project opened → show Dashboard
  if (!openedProjectId) {
    return <Dashboard onOpenProject={(id) => setOpenedProjectId(id)} />;
  }

  // Authenticated + project opened → show CAD Editor
  return <CADEditor projectId={openedProjectId} token={token} onNavigateBack={() => setOpenedProjectId(null)} />;
};

export default App;
