import { useQuery } from '@tanstack/react-query';

import { ApiClient, useApiClient } from '@/lib/apiClient';
import { sleep } from '@/utils/utils';

import fetchKey from '../fetchers/fetchKey';

const pollKeyFetch = async (
  fetchFn: () => ReturnType<typeof fetchKey>,
  firstRequestTime: number = Date.now()
): Promise<string | null> => {
  const result = await fetchFn();
  if (Date.now() - firstRequestTime > 1000 * 60 * 5) {
    // stop trying after 5 minutes
    throw new Error('Timeout');
  }
  if (result.data?.state === 'running') {
    await sleep(2500);
    return pollKeyFetch(fetchFn, firstRequestTime);
  } else if (result.data?.state === 'complete') {
    return result.data.key || null;
  } else {
    console.error(result.error);
    throw new Error(result.error || 'Unknown error');
  }
};

export async function fetchAndPollKey(
  apiClient: ApiClient,
  clipId: string
): Promise<string | null> {
  return await pollKeyFetch(() => fetchKey(apiClient, clipId));
}

const keyFetchPromises: Partial<{
  [key: string]: Promise<string | null>;
}> = {};

export function getCachedKey(clipId: string): string | null {
  const cachedKey = localStorage.getItem(`march-30-2025-clipKey-${clipId}`);
  return cachedKey ? JSON.parse(cachedKey) : null;
}

const setCachedKey = (clipId: string, key: string | null) => {
  localStorage.setItem(`march-30-2025-clipKey-${clipId}`, JSON.stringify(key));
};

export async function cachedFetchAndPollKey(
  apiClient: ApiClient,
  clipId: string
): Promise<string | null> {
  if (keyFetchPromises[clipId]) {
    return keyFetchPromises[clipId];
  }
  const cachedKey = getCachedKey(clipId);
  if (cachedKey) {
    return cachedKey;
  }
  keyFetchPromises[clipId] = fetchAndPollKey(apiClient, clipId);

  const key = await keyFetchPromises[clipId];

  setCachedKey(clipId, key);
  return key;
}

export const useKeyQuery = (clipId: string | null) => {
  const apiClient = useApiClient();
  return useQuery({
    queryKey: ['key', clipId],
    queryFn: () => cachedFetchAndPollKey(apiClient, clipId!),
    enabled: !!clipId,
  });
};
