import { useCallback, useContext, useEffect, useRef, useState } from 'react';
import { AxiosResponse } from 'axios';
import { axiosInstance } from '../../axiosApi';
import { AuthContext } from '../contexts/AuthContext';
import { planAllowsRag, SubscriptionMe } from '../utils/finance';

/**
 * Module-level cache so every component that calls useSubscription() during the
 * same session shares one /monetization/subscription/ request instead of each
 * mounting its own (e.g. Header2 + DocumentStoragePage on the same page).
 */
let cachedSubscription: SubscriptionMe | null = null;
let inFlightRequest: Promise<SubscriptionMe | null> | null = null;

async function loadSubscription(): Promise<SubscriptionMe | null> {
  if (cachedSubscription) {
    return cachedSubscription;
  }
  if (!inFlightRequest) {
    inFlightRequest = axiosInstance
      .get<SubscriptionMe>('/monetization/subscription/')
      .then((response: AxiosResponse<SubscriptionMe>) => {
        cachedSubscription = response.data || null;
        return cachedSubscription;
      })
      .catch(() => null)
      .finally(() => {
        inFlightRequest = null;
      });
  }
  return inFlightRequest;
}

/** Drops the cached subscription so the next useSubscription() call refetches (e.g. after sign-out or a plan change). */
export function resetSubscriptionCache(): void {
  cachedSubscription = null;
  inFlightRequest = null;
}

export type UseSubscriptionResult = {
  subscription: SubscriptionMe | null;
  loading: boolean;
  hasRag: boolean;
  refresh: () => Promise<void>;
};

/** Fetches /monetization/subscription/ once per session (shared across callers) and exposes plan-derived flags. */
export function useSubscription(): UseSubscriptionResult {
  const { authenticated } = useContext(AuthContext);
  const [subscription, setSubscription] = useState<SubscriptionMe | null>(cachedSubscription);
  const [loading, setLoading] = useState(!cachedSubscription);
  const mountedRef = useRef(true);

  const load = useCallback(async () => {
    if (!authenticated) {
      setSubscription(null);
      setLoading(false);
      return;
    }
    setLoading((prev) => prev || !cachedSubscription);
    const result = await loadSubscription();
    if (mountedRef.current) {
      setSubscription(result);
      setLoading(false);
    }
  }, [authenticated]);

  useEffect(() => {
    mountedRef.current = true;
    load();
    return () => {
      mountedRef.current = false;
    };
  }, [load]);

  useEffect(() => {
    if (!authenticated) {
      resetSubscriptionCache();
    }
  }, [authenticated]);

  const refresh = useCallback(async () => {
    resetSubscriptionCache();
    await load();
  }, [load]);

  return {
    subscription,
    loading,
    hasRag: planAllowsRag(subscription),
    refresh,
  };
}
