import { useCallback, useEffect, useRef } from 'react';
import Toast from '@arcblock/ux/lib/Toast';
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import { useRequest, useSetState } from 'ahooks';
import { api } from '@blocklet/payment-react';
import type { TPaymentCurrency } from '@blocklet/payment-types';

export function useUnpaidInvoicesCheckForSubscription(subscriptionId: string, manualCheck: boolean = false) {
  const { t } = useLocaleContext();

  const { data = { count: 0 }, runAsync } = useRequest<any, any[]>(
    () => api.get(`/api/subscriptions/${subscriptionId}/unpaid-invoices`).then((res: any) => res.data),
    {
      manual: manualCheck,
    }
  );

  const checkUnpaidInvoices = useCallback(async () => {
    const { count } = await runAsync();
    if (count > 0) {
      Toast.warning(t('customer.unpaidInvoicesWarning'));
      return true;
    }
    return false;
  }, []);

  return {
    checkUnpaidInvoices,
    hasUnpaid: data?.count > 0,
  };
}

export function usePendingAmountForSubscription(subscriptionId: string, paymentCurrency?: TPaymentCurrency) {
  const { data: pendingAmountSummary, run: checkPendingAmount } = useRequest(
    async () => {
      if (!subscriptionId || !paymentCurrency?.id) return null;

      const response = await api.get('/api/meter-events/pending-amount', {
        params: {
          subscription_id: subscriptionId,
          currency_id: paymentCurrency.id,
        },
      });

      return response.data;
    },
    {
      ready: !!subscriptionId && !!paymentCurrency?.id,
      refreshDeps: [subscriptionId, paymentCurrency?.id],
      pollingInterval: 30000, // 每30秒检查一次
    }
  );

  // pendingAmountSummary 是 GroupedBN 格式: { [currencyId: string]: string }
  const pendingAmount = pendingAmountSummary && paymentCurrency?.id ? pendingAmountSummary[paymentCurrency.id] : null;

  const hasPendingAmount = pendingAmount && pendingAmount !== '0';

  return {
    pendingAmount,
    hasPendingAmount,
    checkPendingAmount,
  };
}

type SubscriptionExchangeRateInfo = {
  rate?: string;
  provider_id?: string;
  provider_name?: string;
  base_currency?: string;
  timestamp_ms?: number;
  fetched_at?: number;
};

type UseSubscriptionExchangeRateOptions = {
  subscriptionId?: string;
  currencyId?: string;
  enabled?: boolean;
  pollingInterval?: number;
};

export function useSubscriptionExchangeRate({
  subscriptionId,
  currencyId,
  enabled = false,
  pollingInterval = 30000,
}: UseSubscriptionExchangeRateOptions) {
  const [state, setState] = useSetState<{
    liveRateInfo?: SubscriptionExchangeRateInfo;
    liveRateUnavailable: boolean;
    liveRateError?: string;
  }>({
    liveRateInfo: undefined,
    liveRateUnavailable: false,
    liveRateError: undefined,
  });
  const liveRateRefreshRef = useRef(false);

  useEffect(() => {
    if (!enabled || !subscriptionId || !currencyId) {
      setState({
        liveRateInfo: undefined,
        liveRateUnavailable: false,
        liveRateError: undefined,
      });
      return undefined;
    }

    let cancelled = false;
    let timer: ReturnType<typeof setInterval> | null = null;

    const fetchRate = async (isManualRetry = false) => {
      if (typeof document !== 'undefined' && document.hidden && !isManualRetry) {
        return;
      }
      if (typeof navigator !== 'undefined' && !navigator.onLine) {
        return;
      }
      if (liveRateRefreshRef.current) {
        return;
      }
      liveRateRefreshRef.current = true;
      try {
        const { data } = await api.get(`/api/subscriptions/${subscriptionId}/exchange-rate`, {
          params: { currency_id: currencyId },
        });
        if (cancelled) {
          return;
        }
        setState({
          liveRateInfo: data,
          liveRateUnavailable: false,
          liveRateError: undefined,
        });
        scheduleNext();
      } catch (err: any) {
        if (cancelled) {
          return;
        }
        console.error('[Subscription Exchange Rate Fetch Error]', {
          subscriptionId,
          currencyId,
          message: err?.message,
        });
        setState({
          liveRateUnavailable: true,
          liveRateError: err?.response?.data?.error || err?.message,
        });
      } finally {
        liveRateRefreshRef.current = false;
      }
    };

    const scheduleNext = () => {
      if (!timer) {
        // no existing timer
      } else {
        clearInterval(timer);
      }
      if (typeof window === 'undefined') {
        return;
      }
      timer = setInterval(() => {
        fetchRate(false);
      }, pollingInterval);
    };

    fetchRate(false);
    const handleVisibilityChange = () => {
      if (typeof document !== 'undefined' && !document.hidden) {
        fetchRate(false);
      }
    };
    if (typeof document !== 'undefined') {
      document.addEventListener('visibilitychange', handleVisibilityChange);
    }
    return () => {
      cancelled = true;
      if (timer) {
        clearInterval(timer);
      }
      if (typeof document !== 'undefined') {
        document.removeEventListener('visibilitychange', handleVisibilityChange);
      }
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [subscriptionId, currencyId, enabled, pollingInterval]);

  return {
    liveRateInfo: state.liveRateInfo,
    liveRateUnavailable: state.liveRateUnavailable,
    liveRateError: state.liveRateError,
  };
}
