'use client';

import { useEffect, useRef, useState, useCallback } from 'react';
import { useTextStore } from '@/store/text-store';
import { useCanvasStore } from '@/store/canvas-store';
import { useLayerStore } from '@/store/layer-store';
import { useHistoryStore } from '@/store/history-store';
import { TextTool } from '@/tools/text-tool';
import { renderText } from '@/lib/text-utils';
import { DrawCommand } from '@/core/commands/draw-command';

export function OnCanvasTextEditor() {
  const {
    isOnCanvasEditorActive,
    editorPosition,
    editorText,
    editingTextId,
    settings,
    updateEditorText,
    updateEditorPosition,
    deactivateOnCanvasEditor,
    addTextObject,
    updateTextObject,
    setText,
  } = useTextStore();

  const { zoom, offsetX, offsetY, width: canvasWidth, height: canvasHeight } = useCanvasStore();
  const { getActiveLayer } = useLayerStore();
  const { executeCommand } = useHistoryStore();

  const [screenPosition, setScreenPosition] = useState({ x: 0, y: 0 });
  const [isDragging, setIsDragging] = useState(false);
  const [dragStart, setDragStart] = useState({ x: 0, y: 0, initialCanvasX: 0, initialCanvasY: 0 });
  const [textBounds, setTextBounds] = useState({ width: 0, height: 0 });

  const textareaRef = useRef<HTMLTextAreaElement>(null);
  const previewCanvasRef = useRef<HTMLCanvasElement>(null);
  const containerRef = useRef<HTMLDivElement>(null);
  const commitTextRef = useRef<(() => void) | null>(null);

  // Calculate screen position from canvas position
  const calculateScreenPosition = useCallback(() => {
    if (!editorPosition || !containerRef.current) return { x: 0, y: 0 };

    const container = containerRef.current.parentElement;
    if (!container) return { x: 0, y: 0 };

    const rect = container.getBoundingClientRect();

    // Apply canvas transformation: canvas coords -> screen coords
    // The canvas uses: translate(offsetX + width/2, offsetY + height/2), scale(zoom), translate(-canvasWidth/2, -canvasHeight/2)
    const transformedX = (editorPosition.x - canvasWidth / 2) * zoom + (rect.width / 2) + offsetX;
    const transformedY = (editorPosition.y - canvasHeight / 2) * zoom + (rect.height / 2) + offsetY;

    return {
      x: transformedX,
      y: transformedY,
    };
  }, [editorPosition, zoom, offsetX, offsetY, canvasWidth, canvasHeight]);

  // Update screen position when canvas transforms or position changes
  useEffect(() => {
    if (isOnCanvasEditorActive && editorPosition) {
      const pos = calculateScreenPosition();
      setScreenPosition(pos);
    }
  }, [isOnCanvasEditorActive, editorPosition, calculateScreenPosition]);

  // Measure text bounds
  const measureTextBounds = useCallback((text: string) => {
    if (!previewCanvasRef.current) {
      return { width: 200, height: settings.fontSize * settings.lineHeight };
    }

    const canvas = previewCanvasRef.current;
    const ctx = canvas.getContext('2d');
    if (!ctx) {
      return { width: 200, height: settings.fontSize * settings.lineHeight };
    }

    // Measure text
    ctx.font = `${settings.fontStyle} ${settings.fontWeight} ${settings.fontSize}px ${settings.fontFamily}`;
    const lines = text ? text.split('\n') : [''];

    let maxWidth = 0;
    lines.forEach((line) => {
      const width = ctx.measureText(line || ' ').width; // Measure space if empty
      if (width > maxWidth) maxWidth = width;
    });

    // Add padding for better visibility and ensure minimum size
    const width = Math.max(maxWidth + 40, 200);
    const height = Math.max(lines.length * settings.fontSize * settings.lineHeight + 10, settings.fontSize * settings.lineHeight + 10);

    return { width, height };
  }, [settings]);

  // Update text bounds when text or settings change
  useEffect(() => {
    const bounds = measureTextBounds(editorText);
    setTextBounds(bounds);
  }, [editorText, settings, measureTextBounds]);

  // Render text preview on canvas
  useEffect(() => {
    if (!previewCanvasRef.current) return;

    const canvas = previewCanvasRef.current;
    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    // Set canvas size to match text bounds (scaled)
    canvas.width = textBounds.width * zoom;
    canvas.height = textBounds.height * zoom;

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

    if (!editorText) return;

    // Scale context for rendering
    ctx.save();
    ctx.scale(zoom, zoom);

    // Render text at origin with 'top' baseline so it's visible
    // Add small padding from top edge
    renderText(ctx, 10, 0, { ...settings, text: editorText, baseline: 'top' });

    ctx.restore();
  }, [editorText, settings, textBounds, zoom]);

  // Handle commit text
  const commitText = useCallback(() => {
    if (!editorPosition) return;

    if (!editorText.trim()) {
      // Empty text, just close editor
      deactivateOnCanvasEditor();
      return;
    }

    const activeLayer = getActiveLayer();
    if (!activeLayer) {
      deactivateOnCanvasEditor();
      return;
    }

    if (editingTextId) {
      // Update existing text object - update position if moved
      updateTextObject(editingTextId, {
        x: editorPosition.x + 10,
        y: editorPosition.y,
        text: editorText,
        fontFamily: settings.fontFamily,
        fontSize: settings.fontSize,
        fontStyle: settings.fontStyle,
        fontWeight: settings.fontWeight,
        color: settings.color,
        align: settings.align,
        baseline: 'top',
        lineHeight: settings.lineHeight,
        letterSpacing: settings.letterSpacing,
      });
    } else {
      // Create new text object
      addTextObject({
        layerId: activeLayer.id,
        x: editorPosition.x + 10,
        y: editorPosition.y,
        text: editorText,
        fontFamily: settings.fontFamily,
        fontSize: settings.fontSize,
        fontStyle: settings.fontStyle,
        fontWeight: settings.fontWeight,
        color: settings.color,
        align: settings.align,
        baseline: 'top',
        lineHeight: settings.lineHeight,
        letterSpacing: settings.letterSpacing,
      });
    }

    // Update settings text for future use
    setText(editorText);

    // Close editor
    deactivateOnCanvasEditor();
  }, [editorPosition, editorText, editingTextId, settings, deactivateOnCanvasEditor, addTextObject, updateTextObject, setText, getActiveLayer]);

  // Store commitText in ref for click outside handler
  useEffect(() => {
    commitTextRef.current = commitText;
  }, [commitText]);

  // Handle keyboard shortcuts
  const handleKeyDown = useCallback(
    (e: React.KeyboardEvent) => {
      if (e.key === 'Enter' && e.ctrlKey) {
        e.preventDefault();
        commitText();
      } else if (e.key === 'Escape') {
        e.preventDefault();
        deactivateOnCanvasEditor();
      }
    },
    [commitText, deactivateOnCanvasEditor]
  );

  // Handle drag start
  const handleMouseDown = useCallback(
    (e: React.MouseEvent) => {
      if (!editorPosition) return;

      setIsDragging(true);
      setDragStart({
        x: e.clientX,
        y: e.clientY,
        initialCanvasX: editorPosition.x,
        initialCanvasY: editorPosition.y,
      });
      e.preventDefault();
      e.stopPropagation();
    },
    [editorPosition]
  );

  // Handle drag move
  const handleMouseMove = useCallback(
    (e: globalThis.MouseEvent) => {
      if (!isDragging) return;

      const deltaX = e.clientX - dragStart.x;
      const deltaY = e.clientY - dragStart.y;

      // Convert screen delta to canvas delta
      const canvasDeltaX = deltaX / zoom;
      const canvasDeltaY = deltaY / zoom;

      updateEditorPosition(
        dragStart.initialCanvasX + canvasDeltaX,
        dragStart.initialCanvasY + canvasDeltaY
      );
    },
    [isDragging, dragStart, zoom, updateEditorPosition]
  );

  // Handle drag end
  const handleMouseUp = useCallback(() => {
    setIsDragging(false);
  }, []);

  // Attach global mouse listeners for dragging
  useEffect(() => {
    if (isDragging) {
      window.addEventListener('mousemove', handleMouseMove);
      window.addEventListener('mouseup', handleMouseUp);
      return () => {
        window.removeEventListener('mousemove', handleMouseMove);
        window.removeEventListener('mouseup', handleMouseUp);
      };
    }
  }, [isDragging, handleMouseMove, handleMouseUp]);

  // No separate click-outside handler needed - using overlay approach

  // Focus textarea when editor activates
  useEffect(() => {
    if (isOnCanvasEditorActive) {
      setTimeout(() => {
        textareaRef.current?.focus();
      }, 10);
    }
  }, [isOnCanvasEditorActive]);

  if (!isOnCanvasEditorActive || !editorPosition) return null;

  const scaledWidth = textBounds.width * zoom;
  const scaledHeight = textBounds.height * zoom;

  return (
    <>
      {/* Full-screen overlay to capture outside clicks */}
      <div
        className="fixed inset-0"
        style={{
          zIndex: 999,
          pointerEvents: 'auto',
        }}
        onMouseDown={(e) => {
          e.preventDefault();
          e.stopPropagation();
          commitText();
        }}
      />

      <div
        ref={containerRef}
        className="absolute"
        style={{
          left: `${screenPosition.x}px`,
          top: `${screenPosition.y}px`,
          width: `${scaledWidth}px`,
          height: `${scaledHeight}px`,
          zIndex: 1000,
          pointerEvents: 'auto',
        }}
      >
        {/* Bounding box - visual only */}
        <div
          className="absolute inset-0 border-2 border-primary pointer-events-none"
          style={{
            borderStyle: 'dashed',
          }}
        >
          {/* Transform handles - draggable */}
          <div
            className="absolute w-2 h-2 bg-white border-2 border-primary rounded-full -left-1 -top-1 cursor-move"
            style={{ pointerEvents: 'auto' }}
            onMouseDown={handleMouseDown}
          />
          <div
            className="absolute w-2 h-2 bg-white border-2 border-primary rounded-full left-1/2 -translate-x-1/2 -top-1 cursor-move"
            style={{ pointerEvents: 'auto' }}
            onMouseDown={handleMouseDown}
          />
          <div
            className="absolute w-2 h-2 bg-white border-2 border-primary rounded-full -right-1 -top-1 cursor-move"
            style={{ pointerEvents: 'auto' }}
            onMouseDown={handleMouseDown}
          />
          <div
            className="absolute w-2 h-2 bg-white border-2 border-primary rounded-full -left-1 top-1/2 -translate-y-1/2 cursor-move"
            style={{ pointerEvents: 'auto' }}
            onMouseDown={handleMouseDown}
          />
          <div
            className="absolute w-2 h-2 bg-white border-2 border-primary rounded-full -right-1 top-1/2 -translate-y-1/2 cursor-move"
            style={{ pointerEvents: 'auto' }}
            onMouseDown={handleMouseDown}
          />
          <div
            className="absolute w-2 h-2 bg-white border-2 border-primary rounded-full -left-1 -bottom-1 cursor-move"
            style={{ pointerEvents: 'auto' }}
            onMouseDown={handleMouseDown}
          />
          <div
            className="absolute w-2 h-2 bg-white border-2 border-primary rounded-full left-1/2 -translate-x-1/2 -bottom-1 cursor-move"
            style={{ pointerEvents: 'auto' }}
            onMouseDown={handleMouseDown}
          />
          <div
            className="absolute w-2 h-2 bg-white border-2 border-primary rounded-full -right-1 -bottom-1 cursor-move"
            style={{ pointerEvents: 'auto' }}
            onMouseDown={handleMouseDown}
          />
        </div>

        {/* Text preview canvas */}
        <canvas
          ref={previewCanvasRef}
          className="absolute left-0 top-0 pointer-events-none"
          style={{
            width: `${scaledWidth}px`,
            height: `${scaledHeight}px`,
            zIndex: 1,
          }}
        />

        {/* Transparent textarea for input */}
        <textarea
          ref={textareaRef}
          value={editorText}
          onChange={(e) => updateEditorText(e.target.value)}
          onKeyDown={handleKeyDown}
          onMouseDown={(e) => {
            // Stop propagation to prevent overlay from committing during text interaction
            e.stopPropagation();
          }}
          wrap="off"
          spellCheck={false}
          autoComplete="off"
          className="absolute left-0 top-0 resize-none overflow-hidden outline-none border-none text-editor-input"
          style={{
            width: `${scaledWidth}px`,
            height: `${scaledHeight}px`,
            background: 'transparent',
            color: 'transparent',
            caretColor: settings.color,
            fontFamily: settings.fontFamily,
            fontSize: `${settings.fontSize * zoom}px`,
            fontStyle: settings.fontStyle,
            fontWeight: settings.fontWeight,
            lineHeight: settings.lineHeight,
            letterSpacing: `${settings.letterSpacing * zoom}px`,
            textAlign: settings.align,
            padding: 0,
            paddingLeft: `${10 * zoom}px`,
            margin: 0,
            whiteSpace: 'pre',
            zIndex: 10,
            userSelect: 'text',
            WebkitUserSelect: 'text',
            MozUserSelect: 'text',
            cursor: 'text',
          }}
        />
      </div>

    </>
  );
}
