import { useEffect, useRef } from 'react';
import { Group, Rect, Text as KonvaText } from 'react-konva';
import { TextObject } from '../../types/canvas.types';
import Konva from 'konva';

// Helper function to get fontStyle string based on weight and italic
function getFontStyle(bold: boolean, italic: boolean, fontWeight?: 'normal' | 'bold' | 'black'): string {
  const weight = fontWeight === 'black' ? '900' : bold ? 'bold' : 'normal';
  const style = italic ? 'italic' : '';
  return `${weight} ${style}`.trim();
}

// Calculate luminance of a color to determine if it's light or dark
// Returns a value between 0 (black) and 255 (white)
function getLuminance(hexColor: string): number {
  // Remove # if present
  const hex = hexColor.replace('#', '');

  // Convert to RGB
  const r = parseInt(hex.substring(0, 2), 16);
  const g = parseInt(hex.substring(2, 4), 16);
  const b = parseInt(hex.substring(4, 6), 16);

  // Calculate relative luminance using the formula for perceived brightness
  // https://www.w3.org/TR/WCAG20/#relativeluminancedef
  return 0.299 * r + 0.587 * g + 0.114 * b;
}

// Get contrasting text color (white or black) based on background color
function getContrastTextColor(backgroundColor: string): string {
  const luminance = getLuminance(backgroundColor);
  // If luminance > 128, background is light, use black text
  // If luminance <= 128, background is dark, use white text
  return luminance > 128 ? '#000000' : '#FFFFFF';
}

interface TextEditableProps {
  object: TextObject;
  isSelected: boolean;
  onSelect: (e?: Konva.KonvaEventObject<MouseEvent>) => void;
  onDragStart?: (e: Konva.KonvaEventObject<DragEvent>) => void;
  onDragMove?: (e: Konva.KonvaEventObject<DragEvent>) => void;
  onDragEnd?: (e: Konva.KonvaEventObject<DragEvent>) => void;
  onTransformEnd?: (e: Konva.KonvaEventObject<Event>) => void;
  onEditingChange: (id: string, isEditing: boolean, clickX?: number, clickY?: number) => void;
  onMouseEnter?: () => void;
  onMouseLeave?: () => void;
  shapeRef?: ((node: Konva.Text | null) => void) | React.RefObject<Konva.Text>;
}

export default function TextEditable({
  object,
  isSelected,
  onSelect,
  onDragStart,
  onDragMove,
  onDragEnd,
  onTransformEnd,
  onEditingChange,
  onMouseEnter,
  onMouseLeave,
  shapeRef
}: TextEditableProps) {
  const textNodeRef = useRef<Konva.Text | null>(null);
  const groupRef = useRef<Konva.Group | null>(null);

  // Auto-enter edit mode when text is first created (empty text)
  useEffect(() => {
    if (object.text === '' && isSelected && !object.isEditing) {
      // Delay to ensure Konva node is fully rendered
      const timer = setTimeout(() => {
        onEditingChange(object.id, true);
      }, 100);
      return () => clearTimeout(timer);
    }
  }, [object.text, isSelected, object.isEditing, object.id, onEditingChange]);

  // Handle double-click to edit
  const handleDoubleClick = (e: Konva.KonvaEventObject<MouseEvent>) => {
    if (!object.isEditing) {
      const stage = e.target.getStage();
      const pointerPos = stage?.getPointerPosition();
      if (pointerPos) {
        // Get the layer to account for its offset
        const layer = e.target.getLayer();
        const layerX = layer?.x() || 0;
        const layerY = layer?.y() || 0;

        // Get click position relative to the text object (accounting for layer offset)
        const clickX = pointerPos.x - layerX - object.x;
        const clickY = pointerPos.y - layerY - object.y;
        onEditingChange(object.id, true, clickX, clickY);
      } else {
        onEditingChange(object.id, true);
      }
    }
  };

  // Always use the object's fontSize (no dynamic scaling)
  const displayFontSize = object.fontSize;

  // Background padding and border radius
  const bgPaddingTop = 8;
  const bgPaddingRight = 8;
  const bgPaddingBottom = 5;
  const bgPaddingLeft = 8;
  const bgRadius = 8;

  // If hasBackground is true, wrap in Group with background Rect
  if (object.hasBackground) {
    // Get background color (defaults to current fill if not set)
    const bgColor = object.backgroundColor || object.fill;

    // Calculate contrasting text color
    const textColor = getContrastTextColor(bgColor);

    return (
      <Group
        ref={(node) => {
          groupRef.current = node;
          // Attach the Group to the transformer ref, not the inner text
          // Cast to any to handle the type mismatch between Group and Text
          if (typeof shapeRef === 'function') {
            (shapeRef as any)(node);
          } else if (shapeRef) {
            (shapeRef as any).current = node;
          }
        }}
        // Position the group so the VISUAL top-left (background rect) is at object.x, object.y
        x={object.x + bgPaddingLeft}
        y={object.y + bgPaddingTop}
        rotation={object.rotation}
        draggable={true}
        onClick={(e) => onSelect(e as Konva.KonvaEventObject<MouseEvent>)}
        onTap={(e) => onSelect(e as Konva.KonvaEventObject<MouseEvent>)}
        onDblClick={handleDoubleClick}
        onDblTap={handleDoubleClick}
        onDragStart={onDragStart}
        onDragMove={onDragMove}
        onDragEnd={onDragEnd}
        onTransformEnd={onTransformEnd}
        onMouseEnter={onMouseEnter}
        onMouseLeave={onMouseLeave}
        opacity={object.isEditing ? 0 : 1}
        listening={!object.isEditing}
      >
        {/* Background Rectangle */}
        <Rect
          x={-bgPaddingLeft}
          y={-bgPaddingTop}
          width={object.width + bgPaddingLeft + bgPaddingRight}
          height={object.height + bgPaddingTop + bgPaddingBottom}
          fill={bgColor}
          cornerRadius={bgRadius}
        />

        {/* Text */}
        <KonvaText
          id={object.id}
          ref={(node) => {
            // Store text node internally for measurements
            textNodeRef.current = node;
          }}
          x={0}
          y={0}
          width={object.width}
          height={object.height}
          text={object.text}
          fontSize={displayFontSize}
          fontFamily={object.fontFamily}
          fill={textColor}
          fontStyle={getFontStyle(object.bold, object.italic, object.fontWeight)}
          align={object.align || 'left'}
          verticalAlign="top"
          padding={0}
          lineHeight={1}
          draggable={false}
        />
      </Group>
    );
  }

  // No background - render text only
  return (
    <KonvaText
      id={object.id}
      ref={(node) => {
        // Call the callback ref if it's a function
        if (typeof shapeRef === 'function') {
          shapeRef(node);
        } else if (shapeRef) {
          // Set the RefObject if it's an object
          (shapeRef as React.MutableRefObject<Konva.Text | null>).current = node;
        }
        // Also store internally for our own use
        textNodeRef.current = node;
      }}
      x={object.x}
      y={object.y}
      width={object.width}
      height={object.height}
      text={object.text}
      fontSize={displayFontSize}
      fontFamily={object.fontFamily}
      fill={object.fill}
      fontStyle={getFontStyle(object.bold, object.italic, object.fontWeight)}
      align={object.align || 'left'}
      verticalAlign="top"
      rotation={object.rotation}
      padding={0}
      lineHeight={1}
      draggable={true}
      onClick={(e) => onSelect(e as Konva.KonvaEventObject<MouseEvent>)}
      onTap={(e) => onSelect(e as Konva.KonvaEventObject<MouseEvent>)}
      onDblClick={handleDoubleClick}
      onDblTap={handleDoubleClick}
      onDragStart={onDragStart}
      onDragMove={onDragMove}
      onDragEnd={onDragEnd}
      onTransformEnd={onTransformEnd}
      onMouseEnter={onMouseEnter}
      onMouseLeave={onMouseLeave}
      opacity={object.isEditing ? 0 : 1}
      listening={!object.isEditing}
    />
  );
}
