import { computed, onBeforeUnmount, ref } from 'vue';
import { useRouter } from 'vue-router';

import { preferences } from '@easyflow/preferences';

interface NetworkConnectionLike {
  addEventListener?: (event: 'change', listener: () => void) => void;
  effectiveType?: string;
  removeEventListener?: (event: 'change', listener: () => void) => void;
  saveData?: boolean;
}

function getNetworkConnection() {
  if (typeof navigator === 'undefined') {
    return undefined;
  }
  const nav = navigator as Navigator & {
    connection?: NetworkConnectionLike;
    mozConnection?: NetworkConnectionLike;
    webkitConnection?: NetworkConnectionLike;
  };
  return nav.connection ?? nav.mozConnection ?? nav.webkitConnection;
}

function isSlowNetworkConnection() {
  const connection = getNetworkConnection();
  if (!connection) {
    return false;
  }
  if (connection.saveData) {
    return true;
  }
  return ['2g', '3g', 'slow-2g'].includes(connection.effectiveType ?? '');
}

function useContentSpinner() {
  const spinning = ref(false);
  const startTime = ref(0);
  const router = useRouter();
  const showDelay = 120; // 超过该时长才展示loading，避免快速切换闪烁
  const minVisibleTime = 180; // 展示后最小可见时长，避免抖动
  const enableLoading = computed(() => preferences.transition.loading);
  const slowNetwork = ref(isSlowNetworkConnection());
  const enableOverlayLoading = computed(
    () => enableLoading.value && slowNetwork.value,
  );
  const showTimer = ref<ReturnType<typeof setTimeout>>();
  const hideTimer = ref<ReturnType<typeof setTimeout>>();
  const networkConnection = getNetworkConnection();

  const handleNetworkChange = () => {
    slowNetwork.value = isSlowNetworkConnection();
    if (!slowNetwork.value) {
      onEnd();
    }
  };

  function clearShowTimer() {
    if (!showTimer.value) {
      return;
    }
    clearTimeout(showTimer.value);
    showTimer.value = undefined;
  }

  function clearHideTimer() {
    if (!hideTimer.value) {
      return;
    }
    clearTimeout(hideTimer.value);
    hideTimer.value = undefined;
  }

  // 结束加载动画
  const onEnd = () => {
    clearShowTimer();

    if (!enableOverlayLoading.value) {
      clearHideTimer();
      spinning.value = false;
      return;
    }

    if (!spinning.value) {
      return;
    }

    const visibleTime = performance.now() - startTime.value;
    const remainTime = Math.max(0, minVisibleTime - visibleTime);
    clearHideTimer();
    hideTimer.value = setTimeout(() => {
      spinning.value = false;
      hideTimer.value = undefined;
    }, remainTime);
  };

  // 路由前置守卫
  router.beforeEach((to) => {
    if (to.meta.loaded || !enableOverlayLoading.value || to.meta.iframeSrc) {
      onEnd();
      return true;
    }

    clearHideTimer();

    if (spinning.value) {
      return true;
    }

    clearShowTimer();
    showTimer.value = setTimeout(() => {
      startTime.value = performance.now();
      spinning.value = true;
      showTimer.value = undefined;
    }, showDelay);
    return true;
  });

  // 路由后置守卫
  router.afterEach((to) => {
    if (to.meta.loaded || !enableOverlayLoading.value || to.meta.iframeSrc) {
      return true;
    }
    onEnd();
    return true;
  });

  networkConnection?.addEventListener?.('change', handleNetworkChange);

  onBeforeUnmount(() => {
    networkConnection?.removeEventListener?.('change', handleNetworkChange);
    clearShowTimer();
    clearHideTimer();
  });

  return { spinning };
}

export { useContentSpinner };
