/**
 * DesignCanvas — View 2 container.
 *
 * Layout: top CanvasToolbar, left canvas (KonvaStage), right panel area
 * containing AlignmentBar, ObjectPanel, and ShapeProperties.
 * Manages tool state, artboard setup flow, zoom, grid, and imported SVG loading.
 */

import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import type Konva from 'konva';
import type { TraceMetadata } from '../types/engine';
import type { ArtboardConfig, CanvasObject } from '../types/canvas';
import { useCanvasState } from '../hooks/useCanvasState';
import ArtboardSetup from '../components/canvas/ArtboardSetup';
import KonvaStage from '../components/canvas/KonvaStage';
import type { CanvasTool } from '../components/canvas/KonvaStage';
import CanvasToolbar from '../components/canvas/CanvasToolbar';
import ObjectPanel from '../components/canvas/ObjectPanel';
import AlignmentBar from '../components/canvas/AlignmentBar';
import ShapeProperties from '../components/canvas/ShapeProperties';
import { toPx } from '../utils/artboardShapes';
import styles from './DesignCanvas.module.css';

interface DesignCanvasProps {
  svgData: string | null;
  traceMetadata: TraceMetadata | null;
}

export default function DesignCanvas({
  svgData,
  traceMetadata,
}: DesignCanvasProps) {
  const {
    state,
    addObject,
    removeObject: _removeObject,
    updateObject,
    selectObjects,
    deselectAll,
    reorderObject,
    toggleVisibility,
    toggleLock,
    setArtboard,
    undo,
    redo,
    canUndo,
    canRedo,
  } = useCanvasState(traceMetadata);

  const [activeTool, setActiveTool] = useState<CanvasTool>('pointer');
  const [showArtboardSetup, setShowArtboardSetup] = useState(true);
  const [svgImported, setSvgImported] = useState(false);
  const [showGrid, setShowGrid] = useState(false);
  const [zoomLevel, setZoomLevel] = useState(1);

  const stageRef = useRef<Konva.Stage | null>(null);
  const canvasContainerRef = useRef<HTMLDivElement | null>(null);
  const [stageSize, setStageSize] = useState({ width: 800, height: 600 });

  // -- Resize observer for canvas container --------------------------------

  useEffect(() => {
    const container = canvasContainerRef.current;
    if (!container) return;

    const updateSize = () => {
      setStageSize({
        width: container.clientWidth,
        height: container.clientHeight,
      });
    };

    updateSize();
    const observer = new ResizeObserver(updateSize);
    observer.observe(container);
    return () => observer.disconnect();
  }, [showArtboardSetup]);

  // -- Artboard setup -------------------------------------------------------

  const handleArtboardConfirm = useCallback(
    (config: ArtboardConfig) => {
      setArtboard(config);
      setShowArtboardSetup(false);
    },
    [setArtboard],
  );

  // -- Import SVG from View 1 -----------------------------------------------

  useEffect(() => {
    if (!svgData || svgImported || !state.artboard) return;

    const blob = new Blob([svgData], { type: 'image/svg+xml' });
    const url = URL.createObjectURL(blob);

    // Load the image to get natural dimensions
    const img = new window.Image();
    img.onload = () => {
      const artW = toPx(state.artboard!.width, state.artboard!.unit);
      const artH = toPx(state.artboard!.height, state.artboard!.unit);

      // Scale SVG to fit within artboard
      const scale = Math.min(artW / img.width, artH / img.height, 1);
      const scaledW = img.width * scale;
      const scaledH = img.height * scale;

      const imageObj: CanvasObject = {
        type: 'image',
        id: `imported-svg-${Date.now()}`,
        name: 'Imported SVG',
        x: (artW - scaledW) / 2,
        y: (artH - scaledH) / 2,
        width: scaledW,
        height: scaledH,
        rotation: 0,
        visible: true,
        locked: false,
        opacity: 1,
        src: url,
      };

      addObject(imageObj);
      setSvgImported(true);
    };
    img.src = url;
  }, [svgData, svgImported, state.artboard, addObject]);

  // -- Selection handling ---------------------------------------------------

  const handleSelect = useCallback(
    (ids: string[], additive: boolean) => {
      if (additive) {
        const current = new Set(state.selectedIds);
        for (const id of ids) {
          if (current.has(id)) {
            current.delete(id);
          } else {
            current.add(id);
          }
        }
        selectObjects([...current]);
      } else {
        selectObjects(ids);
      }
    },
    [state.selectedIds, selectObjects],
  );

  // -- Rename handler (dispatches updateObject with name change) -----------

  const handleRename = useCallback(
    (id: string, newName: string) => {
      updateObject(id, { name: newName });
    },
    [updateObject],
  );

  // -- Zoom controls --------------------------------------------------------

  const handleZoomIn = useCallback(() => {
    setZoomLevel((z) => Math.min(z + 0.25, 4));
  }, []);

  const handleZoomOut = useCallback(() => {
    setZoomLevel((z) => Math.max(z - 0.25, 0.25));
  }, []);

  const handleZoomFit = useCallback(() => {
    setZoomLevel(1);
  }, []);

  // -- Selected object for properties panel ---------------------------------

  const selectedObject = useMemo(() => {
    if (state.selectedIds.length !== 1) return null;
    return state.objects.find((o) => o.id === state.selectedIds[0]) ?? null;
  }, [state.objects, state.selectedIds]);

  // -- Render ---------------------------------------------------------------

  if (showArtboardSetup) {
    return <ArtboardSetup onConfirm={handleArtboardConfirm} />;
  }

  return (
    <div className={styles.container}>
      {/* Top toolbar */}
      <div className={styles.toolbar}>
        <CanvasToolbar
          activeTool={activeTool}
          onToolChange={setActiveTool}
          canUndo={canUndo}
          canRedo={canRedo}
          onUndo={undo}
          onRedo={redo}
          showGrid={showGrid}
          onToggleGrid={() => setShowGrid((g) => !g)}
          zoomLevel={zoomLevel}
          onZoomIn={handleZoomIn}
          onZoomOut={handleZoomOut}
          onZoomFit={handleZoomFit}
        />
      </div>

      {/* Main area: canvas + right panel */}
      <div className={styles.mainArea}>
        {/* Canvas */}
        <div
          className={styles.canvasArea}
          ref={canvasContainerRef}
          data-testid="canvas-container"
        >
          <KonvaStage
            width={stageSize.width}
            height={stageSize.height}
            artboard={state.artboard}
            objects={state.objects}
            selectedIds={state.selectedIds}
            activeTool={activeTool}
            onSelect={handleSelect}
            onDeselectAll={deselectAll}
            onAddObject={addObject}
            onUpdateObject={updateObject}
            stageRef={stageRef}
          />
        </div>

        {/* Right panel: alignment bar, object panel, shape properties */}
        <div className={styles.panelArea} data-testid="panel-area">
          {/* Alignment bar — visible when selection exists */}
          <AlignmentBar
            objects={state.objects}
            selectedIds={state.selectedIds}
            artboard={state.artboard}
            onUpdateObject={updateObject}
          />

          {/* Object / layer panel */}
          <ObjectPanel
            objects={state.objects}
            selectedIds={state.selectedIds}
            onSelect={handleSelect}
            onReorder={reorderObject}
            onToggleVisibility={toggleVisibility}
            onToggleLock={toggleLock}
            onRename={handleRename}
          />

          {/* Shape properties — visible when exactly 1 object selected */}
          {selectedObject && (
            <ShapeProperties
              object={selectedObject}
              onUpdate={updateObject}
            />
          )}
        </div>
      </div>
    </div>
  );
}
