'use client';

import {useCallback,useEffect,useRef,type RefObject} from 'react';

export function useProjectScrollSelection(
  track:RefObject<HTMLDivElement|null>,
  category:string,
  onSelect:(id:string)=>void,
) {
  const cancelPending=useRef(()=>{});
  const cancel=useCallback(()=>cancelPending.current(),[]);

  useEffect(()=>{
    const element=track.current;
    if(!element)return;
    const rtl=getComputedStyle(element).direction==='rtl';
    const position=()=>Math.min(Math.max(0,rtl?-element.scrollLeft:element.scrollLeft),Math.max(0,element.scrollWidth-element.clientWidth));
    let origin=0;
    let intent=0;
    let armed=false;
    let dragging=false;
    let touchOrigin:{x:number;y:number}|null=null;
    let timer:ReturnType<typeof setTimeout>|undefined;

    const reset=()=>{
      armed=false;
      intent=0;
      clearTimeout(timer);
    };
    cancelPending.current=reset;
    const arm=()=>{
      if(!armed){origin=position();armed=true}
    };
    const selectAdjacent=()=>{
      if(!armed||dragging)return;
      // Gesture direction still works when the native scroller reaches an end
      // or every compact card fits on screen.
      const delta=Math.abs(intent)>=8?intent:position()-origin;
      reset();
      if(Math.abs(delta)<8)return;
      const cards=Array.from(element.querySelectorAll<HTMLElement>('[data-project-id]'));
      if(cards.length<2)return;
      const active=cards.findIndex(card=>card.classList.contains('is-expanded'));
      // One completed gesture advances exactly one project, regardless of
      // swipe distance or momentum. Never derive selection from scroll ratio.
      const index=active<0?0:Math.max(0,Math.min(cards.length-1,active+(delta>0?1:-1)));
      const id=cards[index]?.dataset.projectId;
      if(id&&index!==active){
        if(cards[active]?.contains(document.activeElement))element.focus({preventScroll:true});
        onSelect(id);
      }
    };
    const settle=()=>{
      if(!armed)return;
      clearTimeout(timer);
      timer=setTimeout(selectAdjacent,180);
    };
    const wheel=(event:WheelEvent)=>{
      const horizontal=event.deltaX||(event.shiftKey?event.deltaY:0);
      if(!horizontal)return;
      arm();
      const unit=event.deltaMode===1?16:event.deltaMode===2?element.clientWidth:1;
      intent+=(rtl?-horizontal:horizontal)*unit;
      settle();
    };
    const pointerDown=(event:PointerEvent)=>{if(event.pointerType!=='touch'){dragging=true;arm()}};
    const pointerUp=(event:PointerEvent)=>{if(event.pointerType!=='touch'){dragging=false;settle()}};
    const touchStart=(event:TouchEvent)=>{
      if(event.touches.length!==1){reset();touchOrigin=null;dragging=false;return}
      const touch=event.touches[0];
      touchOrigin={x:touch.clientX,y:touch.clientY};
      dragging=true;
      arm();
    };
    const touchMove=(event:TouchEvent)=>{
      if(!touchOrigin||event.touches.length!==1)return;
      const dx=touchOrigin.x-event.touches[0].clientX;
      const dy=touchOrigin.y-event.touches[0].clientY;
      intent=Math.abs(dx)>Math.abs(dy)?(rtl?-dx:dx):0;
      settle();
    };
    const touchEnd=()=>{touchOrigin=null;dragging=false;settle()};
    const touchCancel=()=>{touchOrigin=null;dragging=false;reset()};
    const keyDown=(event:KeyboardEvent)=>{
      if(event.key!=='ArrowLeft'&&event.key!=='ArrowRight')return;
      event.preventDefault();
      if(event.repeat)return;
      arm();
      intent=(event.key==='ArrowRight'?1:-1)*(rtl?-16:16);
      selectAdjacent();
    };

    // Only a user gesture arms selection. Alignment after clicks or expansion
    // must not start a second selection and create a scroll/resize loop.
    element.addEventListener('wheel',wheel,{passive:true});
    element.addEventListener('pointerdown',pointerDown,{passive:true});
    element.addEventListener('touchstart',touchStart,{passive:true});
    element.addEventListener('touchmove',touchMove,{passive:true});
    element.addEventListener('keydown',keyDown);
    element.addEventListener('scroll',settle,{passive:true});
    window.addEventListener('pointerup',pointerUp,{passive:true});
    window.addEventListener('pointercancel',pointerUp,{passive:true});
    window.addEventListener('touchend',touchEnd,{passive:true});
    window.addEventListener('touchcancel',touchCancel,{passive:true});
    return()=>{
      reset();
      cancelPending.current=()=>{};
      element.removeEventListener('wheel',wheel);
      element.removeEventListener('pointerdown',pointerDown);
      element.removeEventListener('touchstart',touchStart);
      element.removeEventListener('touchmove',touchMove);
      element.removeEventListener('keydown',keyDown);
      element.removeEventListener('scroll',settle);
      window.removeEventListener('pointerup',pointerUp);
      window.removeEventListener('pointercancel',pointerUp);
      window.removeEventListener('touchend',touchEnd);
      window.removeEventListener('touchcancel',touchCancel);
    };
  },[track,category,onSelect]);

  return cancel;
}
