/* eslint-disable no-restricted-globals */
import { useEffect, useState } from 'react';

type UrlChangeCallback = (location: Location) => void;

const subscribers = new Set<UrlChangeCallback>();
let patched = false;
let lastHref = '';

// 检查是否在浏览器环境中
const isBrowser = typeof window !== 'undefined';

function notifyIfChanged() {
  if (!isBrowser) return;

  const currentHref = window.location.href;
  if (currentHref !== lastHref) {
    lastHref = currentHref;
    subscribers.forEach((cb) => cb(window.location));
  }
}

function patchHistoryOnce() {
  if (!isBrowser || patched) return;
  patched = true;

  const originalPushState = history.pushState;
  history.pushState = function patchedPushState(...args) {
    const result = originalPushState.apply(this, args);
    notifyIfChanged();
    return result;
  };

  const originalReplaceState = history.replaceState;
  history.replaceState = function patchedReplaceState(...args) {
    const result = originalReplaceState.apply(this, args);
    notifyIfChanged();
    return result;
  };

  window.addEventListener('popstate', notifyIfChanged);
  window.addEventListener('hashchange', notifyIfChanged);
}

function subscribeUrlChange(callback: UrlChangeCallback): () => void {
  if (isBrowser) {
    patchHistoryOnce();
    subscribers.add(callback);
  }
  return () => {
    subscribers.delete(callback);
  };
}

export interface LocationLike {
  href: string;
  origin: string;
  host: string;
  hostname: string;
  port: string;
  protocol: string;
  pathname: string;
  search: string;
  hash: string;
}

function extractLocation(location: Location): LocationLike {
  return {
    href: location.href,
    origin: location.origin,
    host: location.host,
    hostname: location.hostname,
    pathname: location.pathname,
    port: location.port,
    protocol: location.protocol,
    search: location.search,
    hash: location.hash,
  };
}

const defaultLocation: LocationLike = {
  href: '',
  origin: '',
  host: '',
  hostname: '',
  port: '',
  protocol: '',
  pathname: '',
  search: '',
  hash: '',
};

/**
 * 监听 location 变化，返回当前 location 状态
 */
export function useLocationState(): LocationLike {
  const [location, setLocation] = useState<LocationLike>(() => {
    if (!isBrowser) {
      return defaultLocation;
    }
    return extractLocation(window.location);
  });

  useEffect(() => {
    if (!isBrowser) {
      return undefined;
    }

    return subscribeUrlChange((newLocation) => {
      setLocation(extractLocation(newLocation));
    });
  }, []);

  return location;
}

export default useLocationState;
