import { useEffect, useRef, useState } from 'react';
import { MatrixClient, MatrixEvent, Room, RoomEvent, IRoomTimelineData } from 'matrix-js-sdk';

/**
 * Hook that tracks timeline events across all rooms to trigger re-sorting of room lists.
 * Returns a counter that increments whenever a message is sent or received in any room.
 * This can be used as a dependency in useMemo to trigger re-sorting of room lists.
 * 
 * @param mx - The Matrix client instance
 * @param roomIds - Optional array of room IDs to track. If not provided, tracks all rooms.
 * @returns A number that increments on each timeline event
 */
export const useRoomListReorder = (mx: MatrixClient, roomIds?: string[]): number => {
  const [updateCounter, setUpdateCounter] = useState(0);

  useEffect(() => {
    const handleTimelineEvent = (
      mEvent: MatrixEvent,
      room: Room | undefined,
      toStartOfTimeline: boolean | undefined,
      removed: boolean,
      data: IRoomTimelineData
    ) => {
      if (!room || !data.liveEvent) return;
      if (toStartOfTimeline) return;
      
      if (roomIds && !roomIds.includes(room.roomId)) return;
      
      setUpdateCounter((prev) => prev + 1);
    };

    mx.on(RoomEvent.Timeline, handleTimelineEvent);
    
    return () => {
      mx.removeListener(RoomEvent.Timeline, handleTimelineEvent);
    };
  }, [mx, roomIds]);

  return updateCounter;
};

/**
 * Hook that implements FLIP (First, Last, Invert, Play) animation for list reordering.
 * Tracks element positions before and after reorder, then animates the difference.
 * 
 * @param items - Array of item IDs in their current order
 * @returns Ref callback to attach to the list container
 */
export const useListReorderAnimation = <T extends string>(
  items: T[]
): React.RefCallback<HTMLElement> => {
  const positionsRef = useRef<Map<T, number>>(new Map());
  const containerRef = useRef<HTMLElement | null>(null);

  useEffect(() => {
    if (!containerRef.current) return;

    const currentPositions = new Map<T, number>();
    const elements = new Map<T, HTMLElement>();

    items.forEach((itemId) => {
      const element = containerRef.current!.querySelector(`[data-room-id="${itemId}"]`) as HTMLElement;
      if (element) {
        currentPositions.set(itemId, element.offsetTop);
        elements.set(itemId, element);
      }
    });

    if (positionsRef.current.size === 0) {
      positionsRef.current = currentPositions;
      return;
    }

    const animations: Array<{ element: HTMLElement; deltaY: number }> = [];

    items.forEach((itemId) => {
      const element = elements.get(itemId);
      const oldPos = positionsRef.current.get(itemId);
      const newPos = currentPositions.get(itemId);

      if (element && oldPos !== undefined && newPos !== undefined) {
        const deltaY = oldPos - newPos;

        if (Math.abs(deltaY) > 1) {
          animations.push({ element, deltaY });
        }
      }
    });

    if (animations.length > 0) {
      animations.forEach(({ element, deltaY }) => {
        element.style.transform = `translateY(${deltaY}px)`;
        element.style.transition = 'none';
      });

      requestAnimationFrame(() => {
        animations.forEach(({ element }) => {
          element.style.transition = 'transform 300ms cubic-bezier(0.4, 0, 0.2, 1)';
          element.style.transform = '';
        });
      });
    }

    positionsRef.current = currentPositions;
  }, [items]);

  return (container: HTMLElement | null) => {
    containerRef.current = container;
  };
};
