import { useEffect, useRef } from 'react';
import { useSearchParams } from 'react-router-dom';
import { useComparisonBasket } from './useComparisonBasket';

const PARAM = 'compare';

const serialise = (keys: string[]): string => keys.join(',');
const deserialise = (raw: string | null): string[] =>
  raw
    ? raw
        .split(',')
        .map((s) => s.trim())
        .filter(Boolean)
    : [];

/**
 * Two-way sync between the basket store and the `?compare=a:b,c:d` search param.
 *
 * Mount once near the router root. URL is the source of truth on initial load
 * (so a shared link restores the basket); after that, store changes write
 * through to the URL and external URL changes (back/forward, manual edits)
 * push back into the store.
 */
export function useBasketUrlSync(): void {
  const [searchParams, setSearchParams] = useSearchParams();
  const initialised = useRef(false);

  useEffect(() => {
    const urlKeys = deserialise(searchParams.get(PARAM));
    const storeKeys = useComparisonBasket.getState().packageKeys;

    if (!initialised.current) {
      initialised.current = true;
      if (urlKeys.length > 0 && serialise(urlKeys) !== serialise(storeKeys)) {
        useComparisonBasket.getState().setAll(urlKeys);
      }
      return;
    }

    if (serialise(urlKeys) !== serialise(storeKeys)) {
      useComparisonBasket.getState().setAll(urlKeys);
    }
  }, [searchParams]);

  useEffect(() => {
    return useComparisonBasket.subscribe((state, prev) => {
      if (serialise(state.packageKeys) === serialise(prev.packageKeys)) return;
      setSearchParams(
        (current) => {
          const next = new URLSearchParams(current);
          if (state.packageKeys.length === 0) next.delete(PARAM);
          else next.set(PARAM, serialise(state.packageKeys));
          return next;
        },
        { replace: true },
      );
    });
  }, [setSearchParams]);
}
