import React, { useEffect, useRef, useState } from "react";
import { Icon } from "@iconify/react";

interface FloatingToolbarProps {
  textareaRef: React.RefObject<HTMLTextAreaElement>;
  onFormat: (before: string, after: string) => void;
  visible: boolean;
  position: {
    top: number;
    left: number;
    selectionTop?: number;
    selectionBottom?: number;
    selectionLeft?: number;
    selectionRight?: number;
  };
  onHide?: () => void;
  onInsertColor?: () => void;
  activeFormats?: {
    bold?: boolean;
    italic?: boolean;
    strikethrough?: boolean;
  };
  hasSelection?: boolean;
}

export const FloatingToolbar: React.FC<FloatingToolbarProps> = ({
  textareaRef,
  onFormat,
  visible,
  position,
  onHide,
  onInsertColor,
  activeFormats = {},
  hasSelection = false,
}) => {
  const toolbarRef = useRef<HTMLDivElement>(null);
  const [isDragging, setIsDragging] = useState(false);
  const [startX, setStartX] = useState(0);
  const [scrollLeft, setScrollLeft] = useState(0);

  useEffect(() => {
    if (visible && toolbarRef.current) {
      setTimeout(() => {
        if (!toolbarRef.current) return;

        const toolbar = toolbarRef.current;
        const rect = toolbar.getBoundingClientRect();
        const windowWidth = window.innerWidth;
        const windowHeight = window.innerHeight;
        const padding = 10;
        const offset = 8; // Отступ от выделенного текста

        // Получаем внутренний контейнер с кнопками
        const toolbarContent = toolbar.querySelector(
          ".floating-toolbar"
        ) as HTMLElement;
        const toolbarContentWidth = toolbarContent
          ? toolbarContent.scrollWidth
          : rect.width;
        const availableWidth = windowWidth - padding * 2;
        const toolbarHeight = rect.height;

        // Используем границы выделения, если они есть
        const selectionTop = position.selectionTop ?? position.top;
        const selectionBottom = position.selectionBottom ?? position.top + 20;

        // Вычисляем пространство сверху и снизу от выделения
        const spaceAbove = selectionTop - padding;
        const spaceBelow = windowHeight - selectionBottom - padding;

        // Определяем, где больше места и где не будет перекрытия
        let top: number;

        // Проверяем, помещается ли панель сверху
        if (spaceAbove >= toolbarHeight + offset) {
          // Помещается сверху - размещаем над выделением
          top = selectionTop - toolbarHeight - offset;
        } else if (spaceBelow >= toolbarHeight + offset) {
          // Помещается снизу - размещаем под выделением
          top = selectionBottom + offset;
        } else {
          // Не помещается ни сверху, ни снизу - выбираем сторону с большим пространством
          if (spaceAbove > spaceBelow) {
            // Больше места сверху, но панель может частично выйти за границы
            top = Math.max(padding, selectionTop - toolbarHeight - offset);
          } else {
            // Больше места снизу
            top = Math.min(
              windowHeight - toolbarHeight - padding,
              selectionBottom + offset
            );
          }
        }

        // Горизонтальное позиционирование
        let left = position.left - toolbarContentWidth / 2; // Центрируем относительно середины выделения

        // Если контент шире доступного пространства, устанавливаем maxWidth для wrapper
        if (toolbarContentWidth > availableWidth) {
          toolbar.style.maxWidth = `${availableWidth}px`;
          left = padding; // Выравниваем по левому краю
        } else {
          // Проверяем границы экрана
          if (left + toolbarContentWidth > windowWidth - padding) {
            // Выравниваем по правому краю
            left = Math.max(
              padding,
              windowWidth - toolbarContentWidth - padding
            );
          }
          if (left < padding) {
            left = padding;
          }
        }

        // Финальная проверка вертикальных границ
        if (top < padding) {
          top = padding;
        }
        if (top + toolbarHeight > windowHeight - padding) {
          top = windowHeight - toolbarHeight - padding;
        }

        toolbar.style.top = `${top}px`;
        toolbar.style.left = `${left}px`;
      }, 0);
    }
  }, [visible, position]);

  const handleMouseDown = (e: React.MouseEvent) => {
    // Не начинаем перетаскивание если кликнули на кнопку
    if ((e.target as HTMLElement).closest(".floating-toolbar-btn")) return;

    if (!toolbarRef.current) return;
    setIsDragging(true);
    setStartX(e.pageX - toolbarRef.current.offsetLeft);
    setScrollLeft(toolbarRef.current.scrollLeft);
  };

  const handleMouseMove = (e: MouseEvent) => {
    if (!isDragging || !toolbarRef.current) return;
    e.preventDefault();
    const x = e.pageX - toolbarRef.current.offsetLeft;
    const walk = (x - startX) * 2; // Увеличиваем скорость прокрутки
    toolbarRef.current.scrollLeft = scrollLeft - walk;
  };

  const handleMouseUp = () => {
    setIsDragging(false);
  };

  // Обработчики для document чтобы отслеживать mouseMove и mouseUp даже вне элемента
  useEffect(() => {
    if (isDragging) {
      document.addEventListener("mousemove", handleMouseMove);
      document.addEventListener("mouseup", handleMouseUp);
    } else {
      document.removeEventListener("mousemove", handleMouseMove);
      document.removeEventListener("mouseup", handleMouseUp);
    }

    return () => {
      document.removeEventListener("mousemove", handleMouseMove);
      document.removeEventListener("mouseup", handleMouseUp);
    };
  }, [isDragging]);

  const handleFormat = (before: string, after: string) => {
    onFormat(before, after);
    // Не скрываем toolbar - оставляем его видимым для дальнейших действий
    setTimeout(() => {
      if (textareaRef.current) {
        textareaRef.current.focus();
        // Обновляем выделение после применения форматирования
        const start = textareaRef.current.selectionStart;
        const end = textareaRef.current.selectionEnd;
        if (start !== end) {
          textareaRef.current.setSelectionRange(start, end);
        }
      }
    }, 0);
  };

  const handleCopy = async () => {
    const textarea = textareaRef.current;
    if (!textarea) return;

    const start = textarea.selectionStart;
    const end = textarea.selectionEnd;

    if (start === end) return; // Нет выделения

    const selectedText = textarea.value.substring(start, end);

    try {
      await navigator.clipboard.writeText(selectedText);
      // Можно добавить уведомление об успешном копировании
    } catch (err) {
      // Fallback для старых браузеров
      const textArea = document.createElement("textarea");
      textArea.value = selectedText;
      textArea.style.position = "fixed";
      textArea.style.left = "-999999px";
      document.body.appendChild(textArea);
      textArea.select();
      document.execCommand("copy");
      document.body.removeChild(textArea);
    }
  };

  const handleCut = async () => {
    const textarea = textareaRef.current;
    if (!textarea) return;

    const start = textarea.selectionStart;
    const end = textarea.selectionEnd;

    if (start === end) return; // Нет выделения

    const selectedText = textarea.value.substring(start, end);

    try {
      await navigator.clipboard.writeText(selectedText);
    } catch (err) {
      // Fallback для старых браузеров
      const textArea = document.createElement("textarea");
      textArea.value = selectedText;
      textArea.style.position = "fixed";
      textArea.style.left = "-999999px";
      document.body.appendChild(textArea);
      textArea.select();
      document.execCommand("copy");
      document.body.removeChild(textArea);
    }

    // Удаляем выделенный текст
    const newValue =
      textarea.value.substring(0, start) + textarea.value.substring(end);

    // Обновляем значение через React-совместимое событие
    const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
      window.HTMLTextAreaElement.prototype,
      "value"
    )?.set;

    if (nativeInputValueSetter) {
      nativeInputValueSetter.call(textarea, newValue);
      const inputEvent = new Event("input", { bubbles: true });
      textarea.dispatchEvent(inputEvent);
    } else {
      textarea.value = newValue;
      const inputEvent = new Event("input", { bubbles: true });
      textarea.dispatchEvent(inputEvent);
    }

    textarea.setSelectionRange(start, start);
    textarea.focus();
  };

  const handlePaste = async () => {
    const textarea = textareaRef.current;
    if (!textarea) return;

    const start = textarea.selectionStart;
    const end = textarea.selectionEnd;

    try {
      const text = await navigator.clipboard.readText();

      // Вставляем текст в позицию курсора или заменяем выделенный текст
      const newValue =
        textarea.value.substring(0, start) +
        text +
        textarea.value.substring(end);

      // Обновляем значение через React-совместимое событие
      const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
        window.HTMLTextAreaElement.prototype,
        "value"
      )?.set;

      if (nativeInputValueSetter) {
        nativeInputValueSetter.call(textarea, newValue);
        const inputEvent = new Event("input", { bubbles: true });
        textarea.dispatchEvent(inputEvent);
      } else {
        textarea.value = newValue;
        const inputEvent = new Event("input", { bubbles: true });
        textarea.dispatchEvent(inputEvent);
      }

      // Устанавливаем курсор после вставленного текста
      const newCursorPos = start + text.length;
      textarea.setSelectionRange(newCursorPos, newCursorPos);
      textarea.focus();
    } catch (err) {
      // Fallback: используем execCommand для вставки
      textarea.focus();
      document.execCommand("paste");
    }
  };

  // Не показываем toolbar, если он не видим или нет выделения текста
  if (!visible || !hasSelection) return null;

  return (
    <div
      ref={toolbarRef}
      className="floating-toolbar-wrapper"
      style={{
        position: "fixed",
        top: `${position.top}px`,
        left: `${position.left}px`,
        zIndex: 1000,
        cursor: isDragging
          ? "grabbing"
          : toolbarRef.current &&
            toolbarRef.current.scrollWidth > toolbarRef.current.clientWidth
          ? "grab"
          : "default",
      }}
      onMouseDown={(e) => {
        // Предотвращаем потерю выделения при клике на toolbar
        e.preventDefault();
        handleMouseDown(e);
      }}
      onContextMenu={(e) => {
        // Предотвращаем появление контекстного меню браузера на toolbar
        e.preventDefault();
      }}
    >
      <div className="floating-toolbar">
        <button
          className="floating-toolbar-btn"
          onClick={onHide}
          title="Закрыть"
        >
          <Icon icon="mdi:close" />
        </button>

        {hasSelection && (
          <>
            <button
              className="floating-toolbar-btn"
              onClick={handleCopy}
              title="Копировать"
            >
              <Icon icon="mdi:content-copy" />
            </button>
            <button
              className="floating-toolbar-btn"
              onClick={handleCut}
              title="Вырезать"
            >
              <Icon icon="mdi:content-cut" />
            </button>
            <button
              className="floating-toolbar-btn"
              onClick={handlePaste}
              title="Вставить"
            >
              <Icon icon="mdi:content-paste" />
            </button>
          </>
        )}

        {hasSelection && (
          <>
            <div className="floating-toolbar-separator" />

            <button
              className={`floating-toolbar-btn ${
                activeFormats.bold ? "active" : ""
              }`}
              onClick={() => handleFormat("**", "**")}
              title="Жирный"
            >
              <Icon icon="mdi:format-bold" />
            </button>
            <button
              className={`floating-toolbar-btn ${
                activeFormats.italic ? "active" : ""
              }`}
              onClick={() => handleFormat("*", "*")}
              title="Курсив"
            >
              <Icon icon="mdi:format-italic" />
            </button>
            <button
              className={`floating-toolbar-btn ${
                activeFormats.strikethrough ? "active" : ""
              }`}
              onClick={() => handleFormat("~~", "~~")}
              title="Зачеркнутый"
            >
              <Icon icon="mdi:format-strikethrough" />
            </button>

            <div className="floating-toolbar-separator" />

            <button
              className="floating-toolbar-btn"
              onClick={() => onInsertColor?.()}
              title="Цвет текста"
            >
              <Icon icon="mdi:palette" />
            </button>

            <button
              className="floating-toolbar-btn"
              onClick={() => handleFormat("||", "||")}
              title="Скрытый текст"
            >
              <Icon icon="mdi:eye-off" />
            </button>
          </>
        )}
      </div>
    </div>
  );
};
