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 handleInput = (e) => {
    const newValue = e.target.textContent;
    const newSelection = saveSelection();

    setInternalValue(newValue);
    setSelection(newSelection);
    onChange(newValue);
  };

  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);
      range.deleteContents();

      const processedContent = parseContent(text);
      const fragment = document.createDocumentFragment();

      processedContent.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';
        }
        fragment.appendChild(span);
      });

      range.insertNode(fragment);
      handleInput({ target: contentRef.current });
    }
  };

  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}
      />
  );
};

export default EditableInput;
