import { useCallback, useEffect, useState } from 'react';
import {
  GREEN_SCROLLBAR_BORDER_RADIUS_PX,
  GREEN_SCROLLBAR_MIN_THUMB_PCT,
  GREEN_SCROLLBAR_THUMB_COLOR,
  GREEN_SCROLLBAR_TRACK_COLOR,
  GREEN_SCROLLBAR_WIDTH_PX,
} from './greenScrollbarConstants';

/**
 * Scroll vertical custom (track gris + thumb verde), mismo criterio que `Tabla`.
 * @param {React.RefObject<HTMLElement>} scrollRef — Contenedor con overflow auto y scrollbar nativo oculto.
 */
export const GreenScrollbar = ({
  scrollRef,
  insetRight = 0,
  trackWidth = GREEN_SCROLLBAR_WIDTH_PX,
  className = '',
  style,
}) => {
  const [scrollState, setScrollState] = useState({
    scrollTop: 0,
    clientHeight: 0,
    scrollHeight: 0,
  });
  const [isDragging, setIsDragging] = useState(false);

  const syncScrollState = useCallback(() => {
    const el = scrollRef?.current;
    if (!el) return;
    setScrollState({
      scrollTop: el.scrollTop,
      clientHeight: el.clientHeight,
      scrollHeight: el.scrollHeight,
    });
  }, [scrollRef]);

  useEffect(() => {
    const el = scrollRef?.current;
    if (!el) return undefined;
    syncScrollState();
    el.addEventListener('scroll', syncScrollState, { passive: true });
    const ro = new ResizeObserver(() => syncScrollState());
    ro.observe(el);
    return () => {
      el.removeEventListener('scroll', syncScrollState);
      ro.disconnect();
    };
  }, [scrollRef, syncScrollState]);

  const { scrollTop, clientHeight, scrollHeight } = scrollState;
  const canScroll = scrollHeight > clientHeight + 1;
  if (!canScroll) return null;

  const maxScrollTop = Math.max(0, scrollHeight - clientHeight);
  const thumbHeightPct = Math.max(GREEN_SCROLLBAR_MIN_THUMB_PCT, (clientHeight / scrollHeight) * 100);
  const travelPct = 100 - thumbHeightPct;
  const thumbTopPct = maxScrollTop > 0 ? (scrollTop / maxScrollTop) * travelPct : 0;

  return (
    <div
      aria-hidden
      className={['anima-green-scrollbar', className].filter(Boolean).join(' ')}
      style={{
        position: 'absolute',
        top: 0,
        right: insetRight,
        width: trackWidth,
        height: '100%',
        borderRadius: GREEN_SCROLLBAR_BORDER_RADIUS_PX,
        backgroundColor: GREEN_SCROLLBAR_TRACK_COLOR,
        overflow: 'hidden',
        cursor: 'pointer',
        flexShrink: 0,
        zIndex: 2,
        ...(style || {}),
      }}
      onMouseDown={(e) => {
        if (e.button !== 0) return;
        const el = scrollRef?.current;
        if (!el) return;
        const track = e.currentTarget;
        const rect = track.getBoundingClientRect();
        const y = Math.max(0, Math.min(e.clientY - rect.top, rect.height));
        const ratio = rect.height > 0 ? y / rect.height : 0;
        el.scrollTop = ratio * maxScrollTop;
        syncScrollState();
      }}
    >
      <div
        style={{
          position: 'absolute',
          left: 0,
          top: `${thumbTopPct}%`,
          width: '100%',
          height: `${thumbHeightPct}%`,
          borderRadius: GREEN_SCROLLBAR_BORDER_RADIUS_PX,
          backgroundColor: GREEN_SCROLLBAR_THUMB_COLOR,
          transition: isDragging ? 'none' : 'top 0.1s ease, height 0.1s ease',
          cursor: 'grab',
        }}
        onMouseDown={(e) => {
          if (e.button !== 0) return;
          e.stopPropagation();
          const el = scrollRef?.current;
          if (!el) return;
          const track = e.currentTarget.parentElement;
          if (!track) return;
          const trackHeight = track.getBoundingClientRect().height;
          const thumbHeightPx = (thumbHeightPct / 100) * trackHeight;
          const travelPx = Math.max(1, trackHeight - thumbHeightPx);
          const startY = e.clientY;
          const startTop = el.scrollTop;
          const initialUserSelect = document.body.style.userSelect;
          setIsDragging(true);
          document.body.style.userSelect = 'none';
          const onMove = (moveEvt) => {
            const dy = moveEvt.clientY - startY;
            const ratio = dy / travelPx;
            const nextTop = startTop + ratio * (scrollHeight - clientHeight);
            el.scrollTop = Math.max(0, Math.min(scrollHeight - clientHeight, nextTop));
            syncScrollState();
          };
          const onUp = () => {
            setIsDragging(false);
            document.body.style.userSelect = initialUserSelect;
            document.removeEventListener('mousemove', onMove);
            document.removeEventListener('mouseup', onUp);
          };
          document.addEventListener('mousemove', onMove);
          document.addEventListener('mouseup', onUp);
        }}
      />
    </div>
  );
};

export default GreenScrollbar;
