import { useEffect, useState } from 'react';
import { useMutation, useQuery } from '@apollo/client';
import { FACEBOOK_SETTINGS } from 'components/facebook/schema/queries';
import { UPDATE_FACEBOOK_STATUS } from 'components/facebook/schema/mutations';
import {
  FacebookSettingsQuery,
  UpdateFacebookStatusMutation,
  UpdateFacebookStatusMutationVariables,
} from 'types/graphql';
import { useFacebookSDK } from 'components/facebook/useFacebookSDK';

import { useModal } from 'components/layers';

import { Box, Button, Spinner, Text } from 'components/common';
import { DisconnectFacebookModal } from 'components/facebook/modals';
import { AdAccountsList } from 'components/facebook/AdAccountsList';

import { sentryCaptureMessage } from 'lib/sentry';

const { REACT_APP_FACEBOOK_APP_ID } = process.env;

const MESSAGE =
  'Connect your Facebook Business Manager to list your available Facebook Ad Accounts. You can then share audiences with these ad accounts directly from FanSifter.';

function compareScopes(required: string[], granted: string[]) {
  // return required.filter((item) => granted.indexOf(item) === -1);
  return required.every((item) => granted.indexOf(item) !== -1);
}

interface FacebookSDKProps {
  user: {
    id: string | null;
    status: string;
    grantedScopes: string[];
  };
  scopes?: string[];
}

export const FacebookSDK = ({ user, scopes = [] }: FacebookSDKProps) => {
  const fb = useFacebookSDK(REACT_APP_FACEBOOK_APP_ID || '');

  useEffect(() => {
    if (fb.error) {
      console.log('Facebook SDK', fb.error);
      sentryCaptureMessage(fb.error);
    }
  }, [fb.error]);

  const [submit, mutation] = useMutation<
    UpdateFacebookStatusMutation,
    UpdateFacebookStatusMutationVariables
  >(UPDATE_FACEBOOK_STATUS, {
    refetchQueries: [{ query: FACEBOOK_SETTINGS }],
    awaitRefetchQueries: true,
  });

  const [loading, setLoading] = useState(false);

  const handleConnect = async () => {
    try {
      setLoading(true);
      const scope = scopes.join(',');
      const res = await fb.login({ scope });

      if (res.status === 'connected') {
        await submit({
          variables: {
            status: res.status,
            response: {
              accessToken: res.authResponse.accessToken,
              grantedScopes: res.authResponse.grantedScopes || '',
              userID: res.authResponse.userID,
            },
          },
        });
      }
      setLoading(false);
    } catch (error) {
      console.log(error);
      setLoading(false);
    }
  };

  const handleReconnect = async () => {
    try {
      setLoading(true);
      const scope = scopes.join(',');
      const res = await fb.login({ scope, auth_type: 'rerequest' });

      if (res.status === 'connected') {
        await submit({
          variables: {
            status: res.status,
            response: {
              accessToken: res.authResponse.accessToken,
              grantedScopes: res.authResponse.grantedScopes || '',
              userID: res.authResponse.userID,
            },
          },
        });
      }
      setLoading(false);
    } catch (error) {
      console.log(error);
      setLoading(false);
    }
  };

  const disconnectFacebookModal = useModal(DisconnectFacebookModal);

  const renderButton = (
    user: FacebookSDKProps['user'],
    scopes: FacebookSDKProps['scopes']
  ) => {
    if (user && scopes) {
      const { status, grantedScopes } = user;

      const isNotAvailable = !fb.ready || fb.error;

      if (status !== 'connected') {
        return (
          <Button
            onClick={handleConnect}
            disabled={isNotAvailable || loading || mutation.loading}
          >
            Connect
          </Button>
        );
      } else {
        if (compareScopes(scopes, grantedScopes) === false) {
          return (
            <Button
              onClick={handleReconnect}
              title="Additional permissions are required"
              disabled={isNotAvailable || loading || mutation.loading}
            >
              Reconnect
            </Button>
          );
        } else {
          return (
            <Button
              color="red"
              onClick={() => disconnectFacebookModal.show()}
              disabled={loading || mutation.loading}
            >
              Disconnect
            </Button>
          );
        }
      }
    }
  };

  return (
    <>
      <Box className="flex alignCenter justifyBetween paddingX4">
        <Text size="s">Facebook Business Manager</Text>
        {renderButton(user, scopes)}
        <Spinner show={mutation.loading} />
      </Box>
      {mutation.error && (
        <Box paddingX={4}>
          <Text size="s" className="c-red">
            {mutation.error.message}
          </Text>
        </Box>
      )}
    </>
  );
};

export const FacebookSettings = () => {
  const { data, loading } = useQuery<FacebookSettingsQuery>(FACEBOOK_SETTINGS);

  const isConnected = data?.facebook.status === 'connected';

  return (
    <Box>
      {data && (
        <Box spacingY={4}>
          <FacebookSDK user={data.facebook} scopes={data.scopes} />
          {isConnected ? (
            <Box>
              <Box paddingX={4} paddingY={2}>
                <Text size="s">Facebook Ad Accounts</Text>
              </Box>
              <AdAccountsList data={data.accounts} />
            </Box>
          ) : (
            <Box className="rounded4 hover" padding={4}>
              <Text size="s">{MESSAGE}</Text>
            </Box>
          )}
        </Box>
      )}
      <Spinner show={loading} />
    </Box>
  );
};
