import React, { useState, useEffect } from 'react';
import './elements.css';

const MIN_FRAME_SIZE = { width: 3, height: 3 };
const MIN_LINE_LENGTH = 2;
const MIN_TEXT_SIZE = { width: 1, height: 1 };

function ResizeHandles({ element, onResize, charWidth, charHeight }) {
  const [activeHandle, setActiveHandle] = useState(null);
  const [dragData, setDragData] = useState(null);

  // Determine which handles to show based on element type
  const getHandles = () => {
    switch (element.type) {
      case 'frame':
        return ['nw', 'n', 'ne', 'w', 'e', 'sw', 's', 'se'];
      case 'hline':
      case 'vline':
        return ['start', 'end'];
      case 'text':
      case 'dbtext':
      case 'expr':
        return ['nw', 'ne', 'sw', 'se'];
      case 'band':
        return ['s']; // Only bottom handle for height adjustment
      default:
        return [];
    }
  };

  // Calculate handle position in pixels (relative to parent element)
  const getHandlePosition = (handle) => {
    // Since handles are rendered inside the element div (which is already positioned),
    // we use relative positioning starting from 0,0 at the parent's top-left

    // Calculate width and height based on element type
    let width, height;
    if (element.type === 'hline') {
      width = element.length * charWidth;
      height = charHeight;
    } else if (element.type === 'vline') {
      width = charWidth;
      height = element.length * charHeight;
    } else if (element.type === 'text') {
      // For text fields, calculate based on content length or stored dimensions
      const contentLength = element.content ? element.content.length : 1;
      width = (element.width || Math.max(contentLength, 5)) * charWidth;
      height = (element.height || 1) * charHeight;
    } else if (element.type === 'dbtext' || element.type === 'expr') {
      // For DB text fields and expression fields, use stored dimensions
      width = (element.width || 10) * charWidth;
      height = (element.height || 1) * charHeight;
    } else if (element.type === 'band') {
      // For bands, always full width
      width = 80 * charWidth;
      height = (element.height || 3) * charHeight;
    } else {
      // For frames and other elements
      width = (element.width || 1) * charWidth;
      height = (element.height || 1) * charHeight;
    }

    const positions = {
      // Frame and text handles
      nw: { left: -4, top: -4 },
      n: { left: width / 2 - 4, top: -4 },
      ne: { left: width - 4, top: -4 },
      w: { left: -4, top: height / 2 - 4 },
      e: { left: width - 4, top: height / 2 - 4 },
      sw: { left: -4, top: height - 4 },
      s: { left: width / 2 - 4, top: height - 4 },
      se: { left: width - 4, top: height - 4 },

      // Line endpoint handles
      start: element.type === 'hline'
        ? { left: -4, top: height / 2 - 4 }
        : { left: width / 2 - 4, top: -4 },
      end: element.type === 'hline'
        ? { left: width - 4, top: height / 2 - 4 }
        : { left: width / 2 - 4, top: height - 4 }
    };

    return positions[handle];
  };

  // Get cursor style for handle
  const getCursor = (handle) => {
    const cursors = {
      nw: 'nw-resize',
      n: 'n-resize',
      ne: 'ne-resize',
      w: 'w-resize',
      e: 'e-resize',
      sw: 'sw-resize',
      s: 's-resize',
      se: 'se-resize',
      start: element.type === 'hline' ? 'ew-resize' : 'ns-resize',
      end: element.type === 'hline' ? 'ew-resize' : 'ns-resize'
    };
    return cursors[handle] || 'default';
  };

  const handleMouseDown = (e, handle) => {
    e.stopPropagation();
    setActiveHandle(handle);
    setDragData({
      handle,
      startX: e.clientX,
      startY: e.clientY,
      initialElement: { ...element }
    });
  };

  useEffect(() => {
    if (!activeHandle || !dragData) return;

    const handleMouseMove = (e) => {
      const deltaX = e.clientX - dragData.startX;
      const deltaY = e.clientY - dragData.startY;
      const deltaCol = Math.round(deltaX / charWidth);
      const deltaRow = Math.round(deltaY / charHeight);

      let updates = {};

      if (element.type === 'frame') {
        const initial = dragData.initialElement;

        switch (dragData.handle) {
          case 'se': // South-East (bottom-right)
            updates.width = Math.max(MIN_FRAME_SIZE.width, initial.width + deltaCol);
            updates.height = Math.max(MIN_FRAME_SIZE.height, initial.height + deltaRow);
            break;
          case 'nw': // North-West (top-left)
            const newWidthNW = Math.max(MIN_FRAME_SIZE.width, initial.width - deltaCol);
            const newHeightNW = Math.max(MIN_FRAME_SIZE.height, initial.height - deltaRow);
            updates.x = initial.x + (initial.width - newWidthNW);
            updates.y = initial.y + (initial.height - newHeightNW);
            updates.width = newWidthNW;
            updates.height = newHeightNW;
            break;
          case 'ne': // North-East (top-right)
            const newHeightNE = Math.max(MIN_FRAME_SIZE.height, initial.height - deltaRow);
            updates.y = initial.y + (initial.height - newHeightNE);
            updates.width = Math.max(MIN_FRAME_SIZE.width, initial.width + deltaCol);
            updates.height = newHeightNE;
            break;
          case 'sw': // South-West (bottom-left)
            const newWidthSW = Math.max(MIN_FRAME_SIZE.width, initial.width - deltaCol);
            updates.x = initial.x + (initial.width - newWidthSW);
            updates.width = newWidthSW;
            updates.height = Math.max(MIN_FRAME_SIZE.height, initial.height + deltaRow);
            break;
          case 'n': // North (top edge)
            const newHeightN = Math.max(MIN_FRAME_SIZE.height, initial.height - deltaRow);
            updates.y = initial.y + (initial.height - newHeightN);
            updates.height = newHeightN;
            break;
          case 's': // South (bottom edge)
            updates.height = Math.max(MIN_FRAME_SIZE.height, initial.height + deltaRow);
            break;
          case 'w': // West (left edge)
            const newWidthW = Math.max(MIN_FRAME_SIZE.width, initial.width - deltaCol);
            updates.x = initial.x + (initial.width - newWidthW);
            updates.width = newWidthW;
            break;
          case 'e': // East (right edge)
            updates.width = Math.max(MIN_FRAME_SIZE.width, initial.width + deltaCol);
            break;
        }
      } else if (element.type === 'hline') {
        const initial = dragData.initialElement;

        if (dragData.handle === 'start') {
          // Moving start point left/right
          const newLength = Math.max(MIN_LINE_LENGTH, initial.length - deltaCol);
          updates.x = initial.x + (initial.length - newLength);
          updates.length = newLength;
        } else {
          // Moving end point left/right
          updates.length = Math.max(MIN_LINE_LENGTH, initial.length + deltaCol);
        }
      } else if (element.type === 'vline') {
        const initial = dragData.initialElement;

        if (dragData.handle === 'start') {
          // Moving start point up/down
          const newLength = Math.max(MIN_LINE_LENGTH, initial.length - deltaRow);
          updates.y = initial.y + (initial.length - newLength);
          updates.length = newLength;
        } else {
          // Moving end point up/down
          updates.length = Math.max(MIN_LINE_LENGTH, initial.length + deltaRow);
        }
      } else if (element.type === 'text' || element.type === 'dbtext' || element.type === 'expr') {
        const initial = dragData.initialElement;

        switch (dragData.handle) {
          case 'se': // South-East
            updates.width = Math.max(MIN_TEXT_SIZE.width, initial.width + deltaCol);
            updates.height = Math.max(MIN_TEXT_SIZE.height, initial.height + deltaRow);
            break;
          case 'nw': // North-West
            const newWidthNW = Math.max(MIN_TEXT_SIZE.width, initial.width - deltaCol);
            const newHeightNW = Math.max(MIN_TEXT_SIZE.height, initial.height - deltaRow);
            updates.x = initial.x + (initial.width - newWidthNW);
            updates.y = initial.y + (initial.height - newHeightNW);
            updates.width = newWidthNW;
            updates.height = newHeightNW;
            break;
          case 'ne': // North-East
            const newHeightNE = Math.max(MIN_TEXT_SIZE.height, initial.height - deltaRow);
            updates.y = initial.y + (initial.height - newHeightNE);
            updates.width = Math.max(MIN_TEXT_SIZE.width, initial.width + deltaCol);
            updates.height = newHeightNE;
            break;
          case 'sw': // South-West
            const newWidthSW = Math.max(MIN_TEXT_SIZE.width, initial.width - deltaCol);
            updates.x = initial.x + (initial.width - newWidthSW);
            updates.width = newWidthSW;
            updates.height = Math.max(MIN_TEXT_SIZE.height, initial.height + deltaRow);
            break;
        }
      } else if (element.type === 'band') {
        const initial = dragData.initialElement;
        const MIN_BAND_HEIGHT = 1;

        // Bands only resize vertically (height)
        if (dragData.handle === 's') {
          updates.height = Math.max(MIN_BAND_HEIGHT, initial.height + deltaRow);
        }
      }

      if (Object.keys(updates).length > 0) {
        onResize(updates);
      }
    };

    const handleMouseUp = () => {
      setActiveHandle(null);
      setDragData(null);
    };

    document.addEventListener('mousemove', handleMouseMove);
    document.addEventListener('mouseup', handleMouseUp);

    return () => {
      document.removeEventListener('mousemove', handleMouseMove);
      document.removeEventListener('mouseup', handleMouseUp);
    };
  }, [activeHandle, dragData, element, onResize, charWidth, charHeight]);

  return (
    <>
      {getHandles().map(handle => (
        <div
          key={handle}
          className="resize-handle"
          style={{
            ...getHandlePosition(handle),
            cursor: getCursor(handle)
          }}
          onMouseDown={(e) => handleMouseDown(e, handle)}
        />
      ))}
    </>
  );
}

export default ResizeHandles;
