'use client';

import { useEffect, useRef } from 'react';
import { captureCaught } from '@/lib/observability';

const STORAGE_PREFIX = 'multideal:list-scroll:';
const RESTORE_RETRY_FRAMES = 12;

export interface ListScrollRestorationOptions {
  routeKey: string | null;
  ready: boolean;
  getElement: () => HTMLElement | null;
}

function storageKey(routeKey: string): string {
  return `${STORAGE_PREFIX}${routeKey}`;
}

function readSavedTop(routeKey: string): number | null {
  if (typeof sessionStorage === 'undefined') return null;
  try {
    const raw = sessionStorage.getItem(storageKey(routeKey));
    if (!raw) return null;
    const parsed = JSON.parse(raw) as { top?: unknown };
    return typeof parsed.top === 'number' && Number.isFinite(parsed.top) ? parsed.top : null;
  } catch (err) {
    captureCaught(err, { scope: 'lib.hooks.useListScrollRestoration.read', severity: 'info' });
    return null;
  }
}

function writeSavedTop(routeKey: string, top: number): void {
  if (typeof sessionStorage === 'undefined') return;
  try {
    sessionStorage.setItem(storageKey(routeKey), JSON.stringify({ top }));
  } catch (err) {
    captureCaught(err, { scope: 'lib.hooks.useListScrollRestoration.write', severity: 'info' });
  }
}

export function useListScrollRestoration({
  routeKey,
  ready,
  getElement,
}: ListScrollRestorationOptions): void {
  const restoredRouteRef = useRef<string | null>(null);

  useEffect(() => {
    restoredRouteRef.current = null;
  }, [routeKey]);

  useEffect(() => {
    if (!routeKey) return;
    const element = getElement();
    if (!element) return;

    const handleScroll = () => {
      writeSavedTop(routeKey, element.scrollTop);
    };

    element.addEventListener('scroll', handleScroll, { passive: true });
    return () => element.removeEventListener('scroll', handleScroll);
  }, [getElement, routeKey]);

  useEffect(() => {
    if (!routeKey || !ready) return;
    if (restoredRouteRef.current === routeKey) return;

    const savedTop = readSavedTop(routeKey);
    if (savedTop == null) {
      restoredRouteRef.current = routeKey;
      return;
    }

    let cancelled = false;
    let frame = 0;
    let rafId = 0;

    const restore = () => {
      if (cancelled) return;
      const element = getElement();
      if (!element) return;

      const maxScrollTop = Math.max(0, element.scrollHeight - element.clientHeight);
      if (frame < RESTORE_RETRY_FRAMES && maxScrollTop < savedTop) {
        frame += 1;
        rafId = requestAnimationFrame(restore);
        return;
      }

      element.scrollTop = Math.min(savedTop, maxScrollTop);
      restoredRouteRef.current = routeKey;
    };

    rafId = requestAnimationFrame(() => {
      rafId = requestAnimationFrame(restore);
    });

    return () => {
      cancelled = true;
      cancelAnimationFrame(rafId);
    };
  }, [getElement, ready, routeKey]);
}
