import { useCallback, useEffect, useMemo, useState } from 'react';
import Debug from 'debug';

import type { AppleMusicAuthResultSuccess } from '../../services/useAppleMusicAuth';
import type { PresaveProviderProps } from '../types';

import { assertEnvVar } from '~/lib/utils/assert';
import ErrorText from '~/src/components/ErrorText';
import { useAppAlert } from '~/src/components/NextApp/lib/CoreUi';
import { presavePrerelease } from '~/src/lib/songwhipApi/prereleases/presave';
import { useSelector } from '~/src/store/redux';
import {
  selectUserCountry,
  selectUserLanguage,
} from '~/src/store/session/selectors';
import {
  useAppleMusicAuth,
  useResolveAppleMusicUserTokenFromUrl,
} from '../../services';
import useHash from '../../useHash';
import useWindowVisible from '../../useWindowVisible';

const debug = Debug('songwhip/useAppleMusicPresave');

const APPLE_MUSIC_KEY_ID = assertEnvVar(
  process.env.NEXT_PUBLIC_APPLE_MUSIC_KEY_ID,
  'NEXT_PUBLIC_APPLE_MUSIC_KEY_ID'
);

const useAppleMusicPresave = ({
  item,
  withNotificationEmail = false,

  onSuccess,
  onResult,
  onError,
}: PresaveProviderProps) => {
  const userTokenFromUrl = useResolveAppleMusicUserTokenFromUrl();
  const language = useSelector(selectUserLanguage);
  const country = useSelector(selectUserCountry);

  // when a user-token is found in the url we show loading state until handler is done
  const isLoadingInitial = userTokenFromUrl ? true : false;

  const [isLoading, setIsLoading] = useState(isLoadingInitial);
  const { hashParams } = useHash();
  const windowVisible = useWindowVisible();
  const appAlert = useAppAlert();

  // We must hide set `isLoading: false` when the window goes to the background
  // as we get no failure callback from musickit.authorize() or have
  // no way of knowing if the user just closes the apple popup. In either
  // of these events we can be left just showing a perpetual spinner.
  useEffect(() => {
    debug('windowVisible: %s', windowVisible);

    if (isLoading && !windowVisible) {
      debug('hide loading');
      setIsLoading(false);
    }
  }, [isLoading, windowVisible]);

  useEffect(() => {
    if (!userTokenFromUrl) return;

    debug('got auth callback result from hash');

    onUserToken({
      type: 'APPLE_MUSIC_AUTH_SUCCESS',

      // we supposed to add email to hash before starting the presave
      // to handle webview edge case when songwhip page is reloaded
      email: hashParams.email,
      token: userTokenFromUrl,
    });
  }, [userTokenFromUrl]);

  const onUserToken = useCallback(
    async (payload: AppleMusicAuthResultSuccess) => {
      try {
        setIsLoading(true);
        onResult?.();

        await presavePrerelease({
          item,
          data: {
            type: 'presave',
            service: 'itunes',
            serviceUserToken: payload.token,
            serviceAppId: APPLE_MUSIC_KEY_ID,
            userEmail: payload.email,
            locale: language,
            country: payload.country ?? country,
            withNotificationEmail:
              withNotificationEmail && Boolean(payload.email),
          },
        });

        onSuccess(payload);
      } catch (error) {
        appAlert({
          content: <ErrorText error={error} />,
        });

        onError?.(error.message);
      } finally {
        setIsLoading(false);
      }
    },
    []
  );

  const startAppleMusicAuth = useAppleMusicAuth({
    enabled: true,

    onSuccess: onUserToken,
    onError: (message) => {
      appAlert({
        title: message,
      });
    },
  });

  return useMemo(
    () => ({
      isLoading,
      start: startAppleMusicAuth,
    }),
    [isLoading]
  );
};

export default useAppleMusicPresave;
