import {
  splitProps,
  createSignal,
  onMount,
  onCleanup,
  type Component,
  type JSX,
} from 'solid-js';
import clsx from 'clsx';

interface CyberScrollbarProps {
  children: JSX.Element;
  class?: string;
}

/**
 * Custom scrollbar with glow edge and hexagonal crystal indicator.
 * Hides the native scrollbar and renders a custom overlay:
 * - Always-visible subtle glow from right edge
 * - Hexagonal crystal appears on mouse proximity to right edge (~40px)
 * - Crystal fills solid on click/drag for scroll control
 * - Crystal fades out when mouse leaves detection perimeter
 */
export const CyberScrollbar: Component<CyberScrollbarProps> = (rawProps) => {
  const [local, rest] = splitProps(rawProps, ['children', 'class']);

  let contentRef: HTMLDivElement | undefined;
  let wrapperRef: HTMLDivElement | undefined;

  const [scrollRatio, setScrollRatio] = createSignal(0);
  const [thumbHeight, setThumbHeight] = createSignal(0);
  const [crystalVisible, setCrystalVisible] = createSignal(false);
  const [crystalActive, setCrystalActive] = createSignal(false);
  const [crystalY, setCrystalY] = createSignal(0);
  const [needsScrollbar, setNeedsScrollbar] = createSignal(false);

  const DETECTION_PERIMETER = 40; // px from right edge
  const CRYSTAL_HEIGHT = 40; // px

  const recalculate = () => {
    if (!contentRef) return;
    const el = contentRef;
    const hasScroll = el.scrollHeight > el.clientHeight;
    setNeedsScrollbar(hasScroll);
    if (hasScroll) {
      const ratio = el.clientHeight / el.scrollHeight;
      setThumbHeight(Math.max(ratio * el.clientHeight, CRYSTAL_HEIGHT));
    }
  };

  const onScroll = () => {
    if (!contentRef) return;
    const el = contentRef;
    const maxScroll = el.scrollHeight - el.clientHeight;
    if (maxScroll > 0) {
      setScrollRatio(el.scrollTop / maxScroll);
    }
  };

  const onWrapperMouseMove = (e: MouseEvent) => {
    if (!wrapperRef || !contentRef) return;
    const rect = wrapperRef.getBoundingClientRect();
    const distFromRight = rect.right - e.clientX;

    if (distFromRight <= DETECTION_PERIMETER && needsScrollbar()) {
      setCrystalVisible(true);
      // Clamp crystal Y to within the scrollbar track
      const trackHeight = rect.height;
      const maxY = trackHeight - CRYSTAL_HEIGHT;
      const relativeY = e.clientY - rect.top - CRYSTAL_HEIGHT / 2;
      setCrystalY(Math.max(0, Math.min(relativeY, maxY)));
    } else {
      if (!crystalActive()) {
        setCrystalVisible(false);
      }
    }
  };

  const onWrapperMouseLeave = () => {
    if (!crystalActive()) {
      setCrystalVisible(false);
    }
  };

  const onCrystalMouseDown = (e: MouseEvent) => {
    e.preventDefault();
    setCrystalActive(true);
    scrollToCrystalPosition();

    const onMouseMove = (e: MouseEvent) => {
      if (!wrapperRef || !contentRef) return;
      const rect = wrapperRef.getBoundingClientRect();
      const trackHeight = rect.height;
      const maxY = trackHeight - CRYSTAL_HEIGHT;
      const relativeY = e.clientY - rect.top - CRYSTAL_HEIGHT / 2;
      const clampedY = Math.max(0, Math.min(relativeY, maxY));
      setCrystalY(clampedY);

      // Scroll content proportionally
      const ratio = clampedY / maxY;
      const maxScroll = contentRef.scrollHeight - contentRef.clientHeight;
      contentRef.scrollTop = ratio * maxScroll;
      setScrollRatio(ratio);
    };

    const onMouseUp = () => {
      setCrystalActive(false);
      document.removeEventListener('mousemove', onMouseMove);
      document.removeEventListener('mouseup', onMouseUp);
    };

    document.addEventListener('mousemove', onMouseMove);
    document.addEventListener('mouseup', onMouseUp);
  };

  const scrollToCrystalPosition = () => {
    if (!wrapperRef || !contentRef) return;
    const rect = wrapperRef.getBoundingClientRect();
    const trackHeight = rect.height;
    const maxY = trackHeight - CRYSTAL_HEIGHT;
    const ratio = crystalY() / maxY;
    const maxScroll = contentRef.scrollHeight - contentRef.clientHeight;
    contentRef.scrollTop = ratio * maxScroll;
    setScrollRatio(ratio);
  };

  let resizeObserver: ResizeObserver | undefined;

  onMount(() => {
    recalculate();
    if (contentRef) {
      resizeObserver = new ResizeObserver(() => recalculate());
      resizeObserver.observe(contentRef);
    }
  });

  onCleanup(() => {
    resizeObserver?.disconnect();
  });

  // Compute the thumb position in the track
  const thumbTop = () => {
    if (!contentRef) return 0;
    const trackHeight = (wrapperRef?.clientHeight ?? 0) - CRYSTAL_HEIGHT;
    return scrollRatio() * trackHeight;
  };

  return (
    <div
      ref={wrapperRef}
      class={clsx('hh-scroll-container', local.class)}
      onMouseMove={onWrapperMouseMove}
      onMouseLeave={onWrapperMouseLeave}
      style={{
        position: 'relative',
        overflow: 'hidden',
      }}
      {...rest}
    >
      {/* Scrollable content area */}
      <div
        ref={contentRef}
        class="hh-scroll-content"
        onScroll={onScroll}
        style={{
          overflow: 'auto',
          height: '100%',
          'scrollbar-width': 'none',
        } as JSX.CSSProperties}
      >
        <style>{`.hh-scroll-content::-webkit-scrollbar { display: none; }`}</style>
        {local.children}
      </div>

      {/* Glow edge — always visible when scrollable */}
      <div
        style={{
          position: 'absolute',
          top: '0',
          right: '0',
          bottom: '0',
          width: '3px',
          background: `linear-gradient(
            to left,
            color-mix(in srgb, var(--hh-color-primary) 20%, transparent),
            transparent
          )`,
          'pointer-events': 'none',
          opacity: needsScrollbar() ? '1' : '0',
          transition: 'opacity var(--hh-transition-normal)',
          'z-index': '2',
        }}
      />

      {/* Track glow — shows scroll position */}
      <div
        style={{
          position: 'absolute',
          top: `${thumbTop()}px`,
          right: '0',
          width: '2px',
          height: `${thumbHeight()}px`,
          background: `color-mix(in srgb, var(--hh-color-primary) 30%, transparent)`,
          'pointer-events': 'none',
          opacity: needsScrollbar() ? '0.6' : '0',
          transition: 'opacity var(--hh-transition-normal)',
          'z-index': '2',
        }}
      />

      {/* Hexagonal crystal indicator */}
      <div
        onMouseDown={onCrystalMouseDown}
        style={{
          position: 'absolute',
          top: `${crystalY()}px`,
          right: '2px',
          width: '12px',
          height: `${CRYSTAL_HEIGHT}px`,
          'clip-path': 'polygon(50% 0%, 100% 15%, 100% 85%, 50% 100%, 0% 85%, 0% 15%)',
          background: crystalActive()
            ? 'var(--hh-color-primary)'
            : 'transparent',
          'box-shadow': crystalActive()
            ? '0 0 8px var(--hh-color-primary)'
            : 'none',
          border: '1px solid var(--hh-color-primary)',
          opacity: crystalVisible() ? '1' : '0',
          animation: crystalVisible() ? 'hh-crystal-flicker 0.3s ease-out' : 'none',
          transition: `opacity var(--hh-transition-normal), background var(--hh-transition-fast)`,
          cursor: 'pointer',
          'z-index': '3',
        } as JSX.CSSProperties}
      />
    </div>
  );
};
