<script lang="ts">
  import { createEventDispatcher, onMount } from 'svelte';
  
  export let imageUrl: string;
  export let personName: string;
  export let initialCrop: { x: number; y: number; width: number; height: number } | null = null;
  
  const dispatch = createEventDispatcher<{
    save: { x: number; y: number; width: number; height: number };
    cancel: void;
  }>();
  
  let canvas: HTMLCanvasElement;
  let ctx: CanvasRenderingContext2D;
  let image: HTMLImageElement;
  let isImageLoaded = false;
  
  // Crop rectangle state
  let crop = {
    x: 0,
    y: 0,
    width: 200,
    height: 200
  };
  
  // Interaction state
  let isDragging = false;
  let isResizing = false;
  let dragStart = { x: 0, y: 0 };
  let resizeHandle = '';
  
  // Canvas dimensions
  let canvasWidth = 600;
  let canvasHeight = 400;
  
  // Get crop ratio from environment
  const cropRatio = parseFloat(import.meta.env.VITE_CROP_RATIO || '1.0');
  
  onMount(() => {
    ctx = canvas.getContext('2d')!;
    loadImage();
  });
  
  async function loadImage() {
    image = new Image();
    image.onload = () => {
      isImageLoaded = true;
      
      // Calculate canvas size to fit image while maintaining aspect ratio
      const maxWidth = 600;
      const maxHeight = 400;
      const imageAspect = image.width / image.height;
      
      if (imageAspect > maxWidth / maxHeight) {
        canvasWidth = maxWidth;
        canvasHeight = maxWidth / imageAspect;
      } else {
        canvasHeight = maxHeight;
        canvasWidth = maxHeight * imageAspect;
      }
      
      canvas.width = canvasWidth;
      canvas.height = canvasHeight;
      
      // Initialize crop rectangle
      if (initialCrop) {
        // Scale initial crop to canvas dimensions
        const scaleX = canvasWidth / image.width;
        const scaleY = canvasHeight / image.height;
        crop = {
          x: initialCrop.x * scaleX,
          y: initialCrop.y * scaleY,
          width: initialCrop.width * scaleX,
          height: initialCrop.height * scaleY
        };
      } else {
        // Default crop: centered with correct aspect ratio
        const maxSize = Math.min(canvasWidth, canvasHeight) * 0.6;
        const cropWidth = maxSize;
        const cropHeight = cropWidth / cropRatio;
        
        // If height exceeds canvas, scale down proportionally
        if (cropHeight > canvasHeight * 0.8) {
          const scale = (canvasHeight * 0.8) / cropHeight;
          crop = {
            x: (canvasWidth - (cropWidth * scale)) / 2,
            y: (canvasHeight - (cropHeight * scale)) / 2,
            width: cropWidth * scale,
            height: cropHeight * scale
          };
        } else {
          crop = {
            x: (canvasWidth - cropWidth) / 2,
            y: (canvasHeight - cropHeight) / 2,
            width: cropWidth,
            height: cropHeight
          };
        }
      }
      
      drawCanvas();
    };
    image.src = imageUrl;
  }
  
  function drawCanvas() {
    if (!ctx || !isImageLoaded) return;
    
    // Clear canvas
    ctx.clearRect(0, 0, canvasWidth, canvasHeight);
    
    // Draw image
    ctx.drawImage(image, 0, 0, canvasWidth, canvasHeight);
    
    // Draw overlay (darken non-crop area)
    ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
    ctx.fillRect(0, 0, canvasWidth, canvasHeight);
    
    // Clear crop area
    ctx.globalCompositeOperation = 'destination-out';
    ctx.fillRect(crop.x, crop.y, crop.width, crop.height);
    ctx.globalCompositeOperation = 'source-over';
    
    // Draw crop rectangle border
    ctx.strokeStyle = '#3b82f6';
    ctx.lineWidth = 2;
    ctx.strokeRect(crop.x, crop.y, crop.width, crop.height);
    
    // Draw resize handles
    const handleSize = 12; // Increased from 8 for easier grabbing
    ctx.fillStyle = '#3b82f6';
    ctx.strokeStyle = '#ffffff';
    ctx.lineWidth = 1;
    
    // Corner handles with white borders for better visibility
    const handles = [
      { x: crop.x - handleSize/2, y: crop.y - handleSize/2, cursor: 'nw-resize' },
      { x: crop.x + crop.width - handleSize/2, y: crop.y - handleSize/2, cursor: 'ne-resize' },
      { x: crop.x - handleSize/2, y: crop.y + crop.height - handleSize/2, cursor: 'sw-resize' },
      { x: crop.x + crop.width - handleSize/2, y: crop.y + crop.height - handleSize/2, cursor: 'se-resize' },
    ];
    
    handles.forEach(handle => {
      ctx.fillRect(handle.x, handle.y, handleSize, handleSize);
      ctx.strokeRect(handle.x, handle.y, handleSize, handleSize);
    });
  }
  
  function getMousePos(e: MouseEvent) {
    const rect = canvas.getBoundingClientRect();
    return {
      x: e.clientX - rect.left,
      y: e.clientY - rect.top
    };
  }
  
  function isInCropArea(x: number, y: number) {
    return x >= crop.x && x <= crop.x + crop.width && 
           y >= crop.y && y <= crop.y + crop.height;
  }
  
  function getResizeHandle(x: number, y: number) {
    const handleSize = 12; // Match the drawing size
    const tolerance = handleSize;
    
    if (Math.abs(x - crop.x) <= tolerance && Math.abs(y - crop.y) <= tolerance) return 'nw';
    if (Math.abs(x - (crop.x + crop.width)) <= tolerance && Math.abs(y - crop.y) <= tolerance) return 'ne';
    if (Math.abs(x - crop.x) <= tolerance && Math.abs(y - (crop.y + crop.height)) <= tolerance) return 'sw';
    if (Math.abs(x - (crop.x + crop.width)) <= tolerance && Math.abs(y - (crop.y + crop.height)) <= tolerance) return 'se';
    
    return '';
  }
  
  function handleMouseDown(e: MouseEvent) {
    const pos = getMousePos(e);
    const handle = getResizeHandle(pos.x, pos.y);
    
    if (handle) {
      isResizing = true;
      resizeHandle = handle;
      dragStart = pos;
    } else if (isInCropArea(pos.x, pos.y)) {
      isDragging = true;
      dragStart = { x: pos.x - crop.x, y: pos.y - crop.y };
    }
  }
  
  function handleMouseMove(e: MouseEvent) {
    const pos = getMousePos(e);
    
    if (isResizing) {
      const dx = pos.x - dragStart.x;
      const dy = pos.y - dragStart.y;
      
      const newCrop = { ...crop };
      
      // Use primary axis movement for more predictable resizing
      switch (resizeHandle) {
        case 'nw':
          // Use the dominant movement direction
          const primaryDelta = Math.abs(dx) > Math.abs(dy) ? dx : dy * cropRatio;
          const newWidth = Math.max(20, crop.width - primaryDelta);
          const newHeight = newWidth / cropRatio;
          
          newCrop.x = Math.max(0, crop.x + crop.width - newWidth);
          newCrop.y = Math.max(0, crop.y + crop.height - newHeight);
          newCrop.width = newWidth;
          newCrop.height = newHeight;
          break;
          
        case 'ne':
          // For NE, primarily follow horizontal movement
          const newWidthNE = Math.max(20, crop.width + dx);
          const newHeightNE = newWidthNE / cropRatio;
          
          newCrop.width = newWidthNE;
          newCrop.height = newHeightNE;
          newCrop.y = Math.max(0, crop.y + crop.height - newHeightNE);
          break;
          
        case 'sw':
          // For SW, primarily follow horizontal movement  
          const newWidthSW = Math.max(20, crop.width - dx);
          const newHeightSW = newWidthSW / cropRatio;
          
          newCrop.x = Math.max(0, crop.x + crop.width - newWidthSW);
          newCrop.width = newWidthSW;
          newCrop.height = newHeightSW;
          break;
          
        case 'se':
          // For SE, primarily follow horizontal movement
          const newWidthSE = Math.max(20, crop.width + dx);
          const newHeightSE = newWidthSE / cropRatio;
          
          newCrop.width = newWidthSE;
          newCrop.height = newHeightSE;
          break;
      }
      
      // Ensure crop stays within canvas bounds
      if (newCrop.x + newCrop.width > canvasWidth) {
        newCrop.width = canvasWidth - newCrop.x;
        newCrop.height = newCrop.width / cropRatio;
      }
      if (newCrop.y + newCrop.height > canvasHeight) {
        newCrop.height = canvasHeight - newCrop.y;
        newCrop.width = newCrop.height * cropRatio;
      }
      
      // Adjust position if crop extends beyond bounds after resizing
      if (newCrop.x + newCrop.width > canvasWidth) {
        newCrop.x = canvasWidth - newCrop.width;
      }
      if (newCrop.y + newCrop.height > canvasHeight) {
        newCrop.y = canvasHeight - newCrop.height;
      }
      
      crop = newCrop;
      drawCanvas();
    } else if (isDragging) {
      crop.x = Math.max(0, Math.min(canvasWidth - crop.width, pos.x - dragStart.x));
      crop.y = Math.max(0, Math.min(canvasHeight - crop.height, pos.y - dragStart.y));
      drawCanvas();
    } else {
      // Update cursor based on hover state
      const handle = getResizeHandle(pos.x, pos.y);
      if (handle) {
        canvas.style.cursor = handle + '-resize';
      } else if (isInCropArea(pos.x, pos.y)) {
        canvas.style.cursor = 'move';
      } else {
        canvas.style.cursor = 'default';
      }
    }
  }
  
  function handleMouseUp() {
    isDragging = false;
    isResizing = false;
    resizeHandle = '';
    canvas.style.cursor = 'default';
  }
  
  function handleSave() {
    // Convert canvas coordinates back to image coordinates
    const scaleX = image.width / canvasWidth;
    const scaleY = image.height / canvasHeight;
    
    const imageCrop = {
      x: Math.round(crop.x * scaleX),
      y: Math.round(crop.y * scaleY),
      width: Math.round(crop.width * scaleX),
      height: Math.round(crop.height * scaleY)
    };
    
    dispatch('save', imageCrop);
  }
  
  function handleCancel() {
    dispatch('cancel');
  }
</script>

<div class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50" on:click={handleCancel}>
  <div class="bg-white rounded-lg shadow-xl max-w-4xl w-full mx-4" on:click|stopPropagation>
    <div class="p-6">
      <div class="flex items-center justify-between mb-4">
        <h3 class="text-lg font-semibold text-gray-900">
          Crop Photo - {personName}
        </h3>
        
        <button 
          on:click={handleCancel}
          class="text-gray-400 hover:text-gray-600"
        >
          <svg class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
          </svg>
        </button>
      </div>
      
      <div class="flex flex-col items-center space-y-4">
        <div class="border border-gray-300 rounded-lg overflow-hidden">
          <canvas 
            bind:this={canvas}
            on:mousedown={handleMouseDown}
            on:mousemove={handleMouseMove}
            on:mouseup={handleMouseUp}
            on:mouseleave={handleMouseUp}
            class="block"
          ></canvas>
        </div>
        
        <p class="text-sm text-gray-600 text-center max-w-lg">
          Drag the crop area to move it, or drag the corner handles to resize. 
          The selected area will be used for the member card.
          <br>
          <span class="font-medium">Aspect Ratio: {cropRatio.toFixed(1)}:1 {cropRatio === 1.0 ? '(Square)' : cropRatio === 1.5 ? '(3:2)' : ''}</span>
        </p>
        
        <div class="flex space-x-3">
          <button 
            on:click={handleCancel}
            class="px-4 py-2 bg-gray-200 text-gray-700 rounded-lg font-medium hover:bg-gray-300"
          >
            Cancel
          </button>
          
          <button 
            on:click={handleSave}
            class="px-4 py-2 bg-blue-600 text-white rounded-lg font-medium hover:bg-blue-700"
          >
            Save Crop
          </button>
        </div>
      </div>
    </div>
  </div>
</div>
