import React, { useMemo, useEffect, useRef, useCallback } from "react";
import { OverlayScrollbarsComponent } from "overlayscrollbars-react";
import "overlayscrollbars/overlayscrollbars.css";

/**
 * Обертка для OverlayScrollbars с правильной интеграцией с React
 */
export const OverlayScrollbarsWrapper = React.forwardRef(
  (
    {
      children,
      className,
      onScroll,
      overflowX = "hidden",
      overflowY = "scroll",
      scrollbarVisibility = "auto",
      ...props
    },
    ref
  ) => {
    const internalRef = useRef(null);
    const scrollHandlerRef = useRef(onScroll);

    // Обновляем ref обработчика при изменении
    useEffect(() => {
      scrollHandlerRef.current = onScroll;
    }, [onScroll]);

    // Получаем DOM-элемент из OverlayScrollbars компонента
    const getDOMElement = (element) => {
      if (!element) return null;

      // Если это уже DOM элемент
      if (typeof element.querySelector === "function") {
        return element;
      }

      // Если это экземпляр OverlayScrollbars, получаем host элемент
      if (element.osInstance && typeof element.osInstance === "function") {
        const instance = element.osInstance();
        if (instance && instance.getElements) {
          const elements = instance.getElements();
          return elements?.host || null;
        }
      }

      // Пытаемся получить DOM-элемент через различные методы
      if (element?.getElement && typeof element.getElement === "function") {
        return element.getElement();
      }

      if (element?.$el) {
        return element.$el;
      }

      if (element?.current) {
        return element.current;
      }

      // Если это объект с host свойством (может быть экземпляр)
      if (element?.host && typeof element.host.querySelector === "function") {
        return element.host;
      }

      return null;
    };

    // Получаем viewport элемент (scrollable контейнер)
    const getViewportElement = (element) => {
      const domElement = getDOMElement(element);
      if (!domElement || typeof domElement.querySelector !== "function") {
        return null;
      }
      return domElement.querySelector(".os-viewport");
    };

    // Объединяем внешний ref с viewport элементом
    useEffect(() => {
      if (!internalRef.current) return;

      // Функция для обновления ref с viewport элементом
      const updateRef = () => {
        const viewport = getViewportElement(internalRef.current);
        if (viewport) {
          if (typeof ref === "function") {
            ref(viewport);
          } else if (ref) {
            ref.current = viewport;
          }
          return true;
        }
        return false;
      };

      // Пытаемся получить viewport сразу
      const found = updateRef();
      if (found) return; // Если нашли сразу, выходим

      // Если viewport еще не создан, ждем его появления
      const domElement = getDOMElement(internalRef.current);
      if (domElement && typeof domElement.observe === "function") {
        const observer = new MutationObserver(() => {
          if (updateRef()) {
            observer.disconnect();
          }
        });

        observer.observe(domElement, {
          childList: true,
          subtree: true,
        });

        // Также проверяем периодически
        const checkInterval = setInterval(() => {
          if (updateRef()) {
            clearInterval(checkInterval);
            observer.disconnect();
          }
        }, 100);

        // Очищаем через 2 секунды
        setTimeout(() => {
          clearInterval(checkInterval);
          observer.disconnect();
        }, 2000);

        return () => {
          clearInterval(checkInterval);
          observer.disconnect();
        };
      } else {
        // Fallback: периодическая проверка
        const checkInterval = setInterval(() => {
          if (updateRef()) {
            clearInterval(checkInterval);
          }
        }, 100);

        setTimeout(() => {
          clearInterval(checkInterval);
        }, 2000);

        return () => {
          clearInterval(checkInterval);
        };
      }
    }, [ref]);

    // Подключаем обработчик события скролла напрямую на viewport элемент
    useEffect(() => {
      const element = internalRef.current;
      if (!element || !scrollHandlerRef.current) return;

      const handleScroll = (event) => {
        if (scrollHandlerRef.current) {
          scrollHandlerRef.current(event);
        }
      };

      // Ждем, пока OverlayScrollbars создаст viewport элемент
      const setupScrollHandler = () => {
        const viewport = getViewportElement(element);
        if (viewport) {
          viewport.addEventListener("scroll", handleScroll);
          return () => {
            viewport.removeEventListener("scroll", handleScroll);
          };
        }
        return null;
      };

      // Пытаемся подключить сразу
      let cleanup = setupScrollHandler();

      // Если viewport еще не создан, ждем его появления
      if (!cleanup) {
        const domElement = getDOMElement(element);
        if (!domElement || typeof domElement.observe !== "function") {
          // Если не можем наблюдать за изменениями, просто периодически проверяем
          const checkInterval = setInterval(() => {
            if (!cleanup) {
              cleanup = setupScrollHandler();
              if (cleanup) {
                clearInterval(checkInterval);
              }
            }
          }, 100);

          setTimeout(() => {
            clearInterval(checkInterval);
          }, 2000);

          return () => {
            clearInterval(checkInterval);
            if (cleanup) cleanup();
          };
        }

        const observer = new MutationObserver(() => {
          cleanup = setupScrollHandler();
          if (cleanup) {
            observer.disconnect();
          }
        });

        observer.observe(domElement, {
          childList: true,
          subtree: true,
        });

        // Также проверяем периодически на случай, если MutationObserver не сработал
        const checkInterval = setInterval(() => {
          if (!cleanup) {
            cleanup = setupScrollHandler();
            if (cleanup) {
              clearInterval(checkInterval);
              observer.disconnect();
            }
          }
        }, 100);

        // Очищаем через 2 секунды, если viewport так и не появился
        setTimeout(() => {
          clearInterval(checkInterval);
          observer.disconnect();
        }, 2000);

        return () => {
          clearInterval(checkInterval);
          observer.disconnect();
          if (cleanup) cleanup();
        };
      }

      return cleanup;
    }, []);

    const options = useMemo(
      () => ({
        scrollbars: {
          theme: "os-theme-custom",
          visibility: scrollbarVisibility,
          autoHide: "never",
          autoHideDelay: 0,
          dragScrolling: true,
          clickScrolling: false,
          touchSupport: true,
          snapHandle: false,
        },
        overflow: {
          x: overflowX,
          y: overflowY,
        },
      }),
      [overflowX, overflowY, scrollbarVisibility]
    );

    // Обработчик инициализации OverlayScrollbars
    const handleInitialized = useCallback(
      (instance) => {
        if (!instance) {
          console.warn("OverlayScrollbars: instance is null");
          return;
        }

        // Получаем DOM элементы из экземпляра
        // Метод может называться elements() или getElements()
        let elements;
        if (typeof instance.elements === "function") {
          elements = instance.elements();
        } else if (typeof instance.getElements === "function") {
          elements = instance.getElements();
        } else {
          console.warn("OverlayScrollbars: cannot get elements from instance");
          return;
        }

        const viewport = elements?.viewport;

        if (!viewport) {
          console.warn("OverlayScrollbars: viewport element not found");
          return;
        }

        if (ref) {
          // Обновляем внешний ref с viewport элементом
          if (typeof ref === "function") {
            ref(viewport);
          } else if (ref) {
            ref.current = viewport;
          }
        }
      },
      [ref]
    );

    const events = useMemo(
      () => ({
        initialized: () => {
          // После инициализации получаем instance через ref
          if (!internalRef.current) return;

          const instance = internalRef.current.osInstance?.();
          if (instance) {
            handleInitialized(instance);
          }
        },
      }),
      [handleInitialized]
    );

    return (
      <OverlayScrollbarsComponent
        ref={internalRef}
        options={options}
        className={className}
        events={events}
        {...props}
      >
        {children}
      </OverlayScrollbarsComponent>
    );
  }
);

OverlayScrollbarsWrapper.displayName = "OverlayScrollbarsWrapper";
