import { useCallback, useEffect, useState } from 'react';
import { useMutation } from 'react-query';

import { StreamVideoClient, type User } from '@stream-io/video-react-sdk';

import { useAuth } from 'src/contexts/JWTContext';
import useCommunityFeature from 'src/hooks/useCommunityFeature';
import useGeneralError from 'src/hooks/useGeneralError';
import usePermissions from 'src/hooks/usePermissions';
import { getLivestreamToken, getVideoCallToken } from 'src/services/streaming';
import { CommunityFeature } from 'src/types/communityFeatures';
import { UserTypeStream } from 'src/types/stream';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { UserPermissions } from 'src/utils/permissions';
import { getUserId } from 'src/utils/stream';
import { getFullName } from 'src/utils/userUtils';

const apiKey = import.meta.env.VITE_GETSTREAM_KEY;

const { VIEW_LIVESTREAM } = UserPermissions;

const useGetStreamVideoClient = (role?: UserTypeStream) => {
  const [client, setClient] = useState<StreamVideoClient | null>(null);

  const { user: userHumand, isAuthenticated } = useAuth();
  const showGeneralError = useGeneralError();

  const { hasAny: canLiveStream } = usePermissions([VIEW_LIVESTREAM]);
  const canCall = useCommunityFeature(CommunityFeature.VIEW_CALL);
  const isProviderEnabled = canLiveStream || canCall;

  const { t } = useLokaliseTranslation('livestream');

  const tokenProviderMutation = useMutation(() => {
    const callback = (err: unknown) =>
      showGeneralError(err, t('ERROR_CONNECTION_STREAMING_SERVICE'));

    if (role === UserTypeStream.CALL) {
      return getVideoCallToken(callback);
    }
    return getLivestreamToken({ role, callback });
  });

  const tokenProvider = useCallback(async () => {
    return await tokenProviderMutation.mutateAsync();
  }, [tokenProviderMutation]);

  useEffect(() => {
    if (!userHumand || !isProviderEnabled || !isAuthenticated) return;

    const user: User = {
      id: getUserId(role, userHumand) || '',
      name: getFullName(userHumand),
      image: userHumand?.profilePicture ?? undefined,
    };

    const myClient = new StreamVideoClient({ apiKey, user, tokenProvider });
    setClient(myClient);

    return () => {
      myClient.disconnectUser();
      setClient(null);
    };
  }, [userHumand?.id, isProviderEnabled, isAuthenticated, role]);

  return client as StreamVideoClient;
};

export default useGetStreamVideoClient;
