'use client';

const LOCATION_CHANGE_EVENT = 'rm:locationchange';
const PATCH_FLAG = '__rmLocationObserverPatched';

function dispatchLocationChange(): void {
  window.dispatchEvent(new Event(LOCATION_CHANGE_EVENT));
}

function patchHistoryMethods(): void {
  const historyWithFlag = window.history as History & { [PATCH_FLAG]?: boolean };
  if (historyWithFlag[PATCH_FLAG]) return;

  const originalPushState = window.history.pushState.bind(window.history);
  const originalReplaceState = window.history.replaceState.bind(window.history);

  window.history.pushState = function pushState(...args) {
    originalPushState(...args);
    dispatchLocationChange();
  };

  window.history.replaceState = function replaceState(...args) {
    originalReplaceState(...args);
    dispatchLocationChange();
  };

  window.addEventListener('popstate', dispatchLocationChange);
  historyWithFlag[PATCH_FLAG] = true;
}

export function subscribeToLocationChanges(callback: () => void): () => void {
  if (typeof window === 'undefined') return () => undefined;

  patchHistoryMethods();
  window.addEventListener(LOCATION_CHANGE_EVENT, callback);

  return () => {
    window.removeEventListener(LOCATION_CHANGE_EVENT, callback);
  };
}

export function getCurrentPathWithSearch(): string {
  if (typeof window === 'undefined') return '';
  return `${window.location.pathname}${window.location.search || ''}`;
}

export function getCurrentSearchParam(name: string): string | null {
  if (typeof window === 'undefined') return null;
  return new URLSearchParams(window.location.search).get(name);
}
