import React, { useState, useRef, useEffect } from 'react';
import { cn } from "@/lib/utils";

const EditableInput = ({
  name = '',
  value = '',
  className = '',
  style = {},
  onChange = () => {},
  onVariableHover = () => {}
}) => {
  const contentRef = useRef(null);
  const [internalValue, setInternalValue] = useState(value);
  const [selection, setSelection] = useState({ start: 0, end: 0 });

  // Get current cursor position
  const saveSelection = () => {
    const sel = window.getSelection();
    if (sel.rangeCount > 0) {
      const range = sel.getRangeAt(0);
      const preCaretRange = range.cloneRange();
      preCaretRange.selectNodeContents(contentRef.current);
      preCaretRange.setEnd(range.endContainer, range.endOffset);
      const start = preCaretRange.toString().length;

      preCaretRange.setEnd(range.startContainer, range.startOffset);
      const end = preCaretRange.toString().length;

      return { start, end };
    }
    return null;
  };

  // Restore cursor position
  const restoreSelection = (pos) => {
    if (!pos || !contentRef.current) return;

    const sel = window.getSelection();
    const range = document.createRange();
    let currentPos = 0;
    let startNode = null;
    let startOffset = 0;
    let endNode = null;
    let endOffset = 0;

    const traverse = (node) => {
      if (node.nodeType === 3) { // Text node
        const nextPos = currentPos + node.length;

        if (!startNode && pos.start >= currentPos && pos.start <= nextPos) {
          startNode = node;
          startOffset = pos.start - currentPos;
        }

        if (!endNode && pos.end >= currentPos && pos.end <= nextPos) {
          endNode = node;
          endOffset = pos.end - currentPos;
        }

        currentPos = nextPos;
      } else {
        for (const child of node.childNodes) {
          traverse(child);
        }
      }
    };

    traverse(contentRef.current);

    if (startNode && endNode) {
      range.setStart(startNode, startOffset);
      range.setEnd(endNode, endOffset);
      sel.removeAllRanges();
      sel.addRange(range);
    }
  };

  // Parse content to find variables
  const parseContent = (text) => {
    const regex = /{{.*?}}/g;
    const parts = [];
    let lastIndex = 0;

    let match;
    while ((match = regex.exec(text)) !== null) {
      if (match.index > lastIndex) {
        parts.push({
          type: 'text',
          content: text.slice(lastIndex, match.index)
        });
      }
      parts.push({
        type: 'variable',
        content: match[0]
      });
      lastIndex = regex.lastIndex;
    }

    if (lastIndex < text.length) {
      parts.push({
        type: 'text',
        content: text.slice(lastIndex)
      });
    }

    return parts;
  };

  const getCurrentCursor = () => {
    const selection = window.getSelection();
    if (selection.rangeCount === 0) return null;

    const range = selection.getRangeAt(0);
    const preCaretRange = range.cloneRange();
    preCaretRange.selectNodeContents(contentRef.current);
    preCaretRange.setEnd(range.endContainer, range.endOffset);
    const content = preCaretRange.toString().trim();
    if (content === '\u200B') {
      return 0;
    }
    return content.replace('\u200B', '').length;
  };

  const restoreCursor = (position) => {
    const element = contentRef.current;
    const selection = window.getSelection();
    const range = document.createRange();
    range.setStart(element, 0);
    range.collapse(true);

    const nodeStack = [element];
    let node, foundStart = false, stop = false;
    let charIndex = 0;

    while (!stop && (node = nodeStack.pop())) {
      if (node.nodeType === 3) {
        const nextCharIndex = charIndex + node.length;
        if (!foundStart && position >= charIndex && position <= nextCharIndex) {
          range.setStart(node, position - charIndex);
          foundStart = true;
        }
        if (foundStart && position >= charIndex && position <= nextCharIndex) {
          range.setEnd(node, position - charIndex);
          stop = true;
        }
        charIndex = nextCharIndex;
      } else {
        let i = node.childNodes.length;
        while (i--) {
          nodeStack.push(node.childNodes[i]);
        }
      }
    }

    selection.removeAllRanges();
    selection.addRange(range);
  };

  const handleInput = (e) => {
    const newValue = e.target.textContent;
    const cursorPosition = getCurrentCursor();
    setInternalValue(newValue);
    onChange(newValue);

    requestAnimationFrame(() => {
      if (contentRef.current) {
        restoreCursor(cursorPosition);
      }
    });
  };

  const handlePaste = (e) => {
    e.preventDefault();
    const text = e.clipboardData.getData('text/plain');
    const selection = window.getSelection();

    if (selection.rangeCount > 0) {
      const range = selection.getRangeAt(0);
      const cursorPosition = getCurrentCursor();
      range.deleteContents();
      const textNode = document.createTextNode(text);
      range.insertNode(textNode);

      const newValue = contentRef.current.textContent;
      setInternalValue(newValue);
      onChange(newValue);

      requestAnimationFrame(() => {
        restoreCursor(cursorPosition + text.length);
      });
    }
  };

  useEffect(() => {
    if (!contentRef.current) return;

    const parts = parseContent(internalValue);
    const currentSelection = saveSelection() || selection;

    contentRef.current.innerHTML = '';

    parts.forEach(({ type, content }) => {
      const span = document.createElement('span');
      span.textContent = content;

      if (type === 'variable') {
        span.className = 'bg-blue-100 text-blue-800 rounded px-1';
        span.onmouseover = () => onVariableHover(content);
      }

      contentRef.current.appendChild(span);
    });

    restoreSelection(currentSelection);
  }, [internalValue]);

  // Update internal value when prop value changes
  useEffect(() => {
    if (value !== internalValue) {
      setInternalValue(value);
    }
  }, [value]);

  return (
      <div
          ref={contentRef}
          contentEditable
          className={cn(
              "min-h-[40px] rounded-md border border-input bg-background px-3 py-2",
              "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
              "transition-colors",
              className
          )}
          style={style}
          onInput={handleInput}
          onPaste={handlePaste}
          data-value={internalValue}
          data-name={name}
          suppressContentEditableWarning={true}
      >
        {internalValue || '\u200B'}
      </div>
  );
};

export default EditableInput;
