'use client';

import { useEffect, useRef, useState } from 'react';
import { useCanvasStore, useLayerStore } from '@/store';
import { getContext, drawGrid, drawCheckerboard } from '@/lib/canvas-utils';
import { cn } from '@/lib/utils';

export function CanvasWrapper() {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const containerRef = useRef<HTMLDivElement>(null);

  const {
    width,
    height,
    zoom,
    offsetX,
    offsetY,
    showGrid,
    gridSize,
    backgroundColor,
    selection,
  } = useCanvasStore();

  const { layers } = useLayerStore();

  const [isPanning, setIsPanning] = useState(false);
  const [panStart, setPanStart] = useState({ x: 0, y: 0 });

  // Render canvas
  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    const ctx = getContext(canvas);
    const container = containerRef.current;
    if (!container) return;

    // Set canvas size to match container
    const rect = container.getBoundingClientRect();
    canvas.width = rect.width;
    canvas.height = rect.height;

    // Clear canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // Save context state
    ctx.save();

    // Apply transformations
    ctx.translate(offsetX + canvas.width / 2, offsetY + canvas.height / 2);
    ctx.scale(zoom, zoom);
    ctx.translate(-width / 2, -height / 2);

    // Draw checkerboard background (only within canvas bounds)
    drawCheckerboard(ctx, 10, '#ffffff', '#e0e0e0', width, height);

    // Draw background color if not transparent
    if (backgroundColor && backgroundColor !== 'transparent') {
      ctx.fillStyle = backgroundColor;
      ctx.fillRect(0, 0, width, height);
    }

    // Draw all visible layers
    layers
      .filter((layer) => layer.visible && layer.canvas)
      .sort((a, b) => a.order - b.order)
      .forEach((layer) => {
        if (!layer.canvas) return;

        ctx.globalAlpha = layer.opacity;
        ctx.globalCompositeOperation = layer.blendMode as GlobalCompositeOperation;
        ctx.drawImage(layer.canvas, layer.x, layer.y);
      });

    // Reset composite operation
    ctx.globalAlpha = 1;
    ctx.globalCompositeOperation = 'source-over';

    // Draw grid if enabled (only within canvas bounds)
    if (showGrid) {
      drawGrid(ctx, gridSize, 'rgba(0, 0, 0, 0.15)', width, height);
    }

    // Draw selection if active
    if (selection.active) {
      ctx.strokeStyle = '#0066ff';
      ctx.lineWidth = 1 / zoom;
      ctx.setLineDash([4 / zoom, 4 / zoom]);
      ctx.strokeRect(selection.x, selection.y, selection.width, selection.height);
      ctx.setLineDash([]);
    }

    // Restore context state
    ctx.restore();
  }, [layers, width, height, zoom, offsetX, offsetY, showGrid, gridSize, backgroundColor, selection]);

  // Handle mouse wheel for zooming
  const handleWheel = (e: React.WheelEvent) => {
    if (e.ctrlKey || e.metaKey) {
      e.preventDefault();
      const { zoomIn, zoomOut } = useCanvasStore.getState();
      if (e.deltaY < 0) {
        zoomIn();
      } else {
        zoomOut();
      }
    }
  };

  // Handle panning
  const handleMouseDown = (e: React.MouseEvent) => {
    if (e.button === 1 || (e.button === 0 && e.shiftKey)) {
      // Middle mouse or Shift + Left mouse for panning
      setIsPanning(true);
      setPanStart({ x: e.clientX - offsetX, y: e.clientY - offsetY });
      e.preventDefault();
    }
  };

  const handleMouseMove = (e: React.MouseEvent) => {
    if (isPanning) {
      const { setPanOffset } = useCanvasStore.getState();
      setPanOffset(e.clientX - panStart.x, e.clientY - panStart.y);
    }
  };

  const handleMouseUp = () => {
    setIsPanning(false);
  };

  return (
    <div
      ref={containerRef}
      className={cn(
        'relative h-full w-full overflow-hidden bg-canvas-bg',
        isPanning && 'cursor-grabbing'
      )}
      onWheel={handleWheel}
      onMouseDown={handleMouseDown}
      onMouseMove={handleMouseMove}
      onMouseUp={handleMouseUp}
      onMouseLeave={handleMouseUp}
    >
      <canvas
        ref={canvasRef}
        className="absolute inset-0"
      />
    </div>
  );
}
