/**
 * 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 { ArtboardConfig, CanvasObject, ImageObject } from '../types/canvas';
import type { UseCanvasStateReturn } 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';

export interface DesignCanvasProps extends UseCanvasStateReturn {
  svgData: string | null;
  /** Ref to the Konva Stage, created in App.tsx for cross-view access (PNG export). */
  stageRef: React.RefObject<Konva.Stage | null>;
  /** Called when user clicks Export — App.tsx navigates to View 3. */
  onExport: () => void;
}

export default function DesignCanvas({
  svgData,
  state,
  addObject,
  removeObject,
  updateObject,
  selectObjects,
  deselectAll,
  reorderObject,
  toggleVisibility,
  toggleLock,
  setArtboard,
  undo,
  redo,
  canUndo,
  canRedo,
  stageRef,
  onExport,
}: DesignCanvasProps) {

  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 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);
  }, []);

  // -- Keyboard shortcuts ---------------------------------------------------

  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      // Don't fire shortcuts when typing in an input/textarea
      const tag = (document.activeElement?.tagName ?? '').toLowerCase();
      if (tag === 'input' || tag === 'textarea' || tag === 'select') return;

      const ctrl = e.ctrlKey || e.metaKey;

      if (ctrl && e.shiftKey && e.key.toLowerCase() === 'z') {
        e.preventDefault();
        redo();
        return;
      }

      if (ctrl && e.key.toLowerCase() === 'z') {
        e.preventDefault();
        undo();
        return;
      }

      if (ctrl && e.key.toLowerCase() === 'y') {
        e.preventDefault();
        redo();
        return;
      }

      if (ctrl && e.key.toLowerCase() === 'a') {
        e.preventDefault();
        selectObjects(state.objects.map((o) => o.id));
        return;
      }

      if (e.key === 'Delete' || e.key === 'Backspace') {
        e.preventDefault();
        for (const id of state.selectedIds) {
          removeObject(id);
        }
        return;
      }

      if (e.key === 'Escape') {
        e.preventDefault();
        deselectAll();
        return;
      }
    };

    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [undo, redo, removeObject, selectObjects, deselectAll, state.objects, state.selectedIds]);

  // -- Convert text to paths ------------------------------------------------

  const handleConvertToPath = useCallback(
    (textObjectId: string, imageObject: ImageObject) => {
      removeObject(textObjectId);
      addObject(imageObject);
      selectObjects([imageObject.id]);
    },
    [removeObject, addObject, selectObjects],
  );

  // -- 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}
        />
        <button
          type="button"
          className="canvas-tool-btn"
          onClick={onExport}
          title="Export design"
          data-testid="export-btn"
        >
          ⤓ Export
        </button>
      </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}
              onConvertToPath={handleConvertToPath}
            />
          )}
        </div>
      </div>
    </div>
  );
}
