import { useEffect, useMemo } from 'react';
import { useQuery } from 'react-query';

import { useTheme } from '@material-hu/mui/styles';

import { useAuth } from 'src/contexts/JWTContext';
import { getChatbotConfig } from 'src/services/aiChatbot';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { getFullName } from 'src/utils/userUtils';

const VOICEFLOW_CHATBOT_URL = 'https://general-runtime.voiceflow.com';

// Helper function to properly encode UTF-8 strings to base64, otherwise accents were not working
const utf8ToBase64 = (str: string): string => {
  return btoa(
    encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (_, p1) => {
      return String.fromCharCode(parseInt(p1, 16));
    }),
  );
};

// TODO: Pending style fixes
// Styles not applied to the User message bubble --> .vfrc-user-response .vfrc-message
// Styles not applied to the Input container (focus-within) --> .vfrc-input-container:focus-within
const getChatbotStyles = (
  t: Function,
  colors: {
    instance: string;
    base: string;
  },
) =>
  utf8ToBase64(`
      .vfrc-header {
        background-color: ${colors.instance} !important;
      }
      .vfrc-header .vfrc-icon {
        color: ${colors.base} !important;
      }
      .vfrc-user-response .vfrc-message {
        background-color: ${colors.instance} !important;
        color: ${colors.base} !important;
      }
      .vfrc-input-container:focus-within {
        border-color: ${colors.instance} !important;
      }
      .vfrc-prompt button.vfrc-button {
        color: transparent !important;
        position: relative;
      }
      .vfrc-prompt button.vfrc-button::after {
        align-items: center;
        color: ${colors.base} !important;
        display: flex;
        inset: 0;
        justify-content: center;
        position: absolute;
      }
      .vfrc-prompt button.vfrc-button[label='Start new chat']::after {
        background-color: ${colors.instance} !important;
        color: ${colors.base} !important;
        content: '${t('RESTART_CONVERSATION')}';
      }
      .vfrc-prompt button.vfrc-button[label='Cancel']::after {
        background-color: ${colors.base} !important;
        color: ${colors.instance} !important;
        content: '${t('CANCEL')}';
      }
    `);

export type VoiceflowWindow = Window & {
  voiceflow?: {
    chat?: {
      load: (config: {
        verify: { projectID: string };
        url: string;
        versionID: string;
        assistant: {
          persistence: string;
          stylesheet?: string;
        };
        autostart: boolean;
        userID: string;
        launch: {
          event: {
            type: string;
            payload: Record<string, unknown>;
          };
        };
      }) => Promise<void>;
      open: () => void;
    };
  };
};

export const useVoiceflowChatbot = () => {
  const { t } = useLokaliseTranslation();
  const theme = useTheme();
  const { user, instance } = useAuth();

  const {
    data: chatbotConfig,
    isLoading: isChatbotConfigLoading,
    isError: isChatbotConfigError,
  } = useQuery(['chatbotConfig'], () => getChatbotConfig(), {
    onError: () => {
      // Prevent global error handling (Error Toast)
    },
    select: data => data.data,
    // Prevent refetching since this value won't change
    refetchOnMount: false,
    refetchOnWindowFocus: false,
    refetchOnReconnect: false,
    cacheTime: Infinity,
    staleTime: Infinity,
  });

  const assistantData = useMemo(() => {
    return {
      stylesheet: `data:text/css;base64,${getChatbotStyles(t, {
        instance: instance?.color ?? '#496BE3', // Blue brand 400 by default
        base: theme.palette.new.background.layout.default ?? '#FAFAFC',
      })}`,
      persistence: 'memory',
    };
  }, [instance, t, theme]);

  useEffect(() => {
    if (
      !user ||
      !instance ||
      !chatbotConfig ||
      isChatbotConfigError ||
      isChatbotConfigLoading
    )
      return;

    const vfWindow = window as VoiceflowWindow;

    const script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = 'https://cdn.voiceflow.com/widget-next/bundle.mjs';

    script.onload = () => {
      const interval = setInterval(() => {
        if (vfWindow.voiceflow?.chat?.load) {
          clearInterval(interval);

          vfWindow.voiceflow.chat.load({
            verify: { projectID: chatbotConfig.aiChatbotId },
            url: VOICEFLOW_CHATBOT_URL,
            versionID: 'production',
            assistant: assistantData,
            autostart: true,
            userID: user.id.toString(),
            launch: {
              event: {
                type: 'launch',
                payload: {
                  user_name: getFullName(user),
                  system_language: instance.language,
                  user_segmentations:
                    chatbotConfig.userSegmentationItemIdsByGroupId,
                  user_id: user.id,
                  instance_id: instance.id,
                },
              },
            },
          });
        }
      }, 1000);
    };
    document.body.appendChild(script);
  }, [
    user,
    instance,
    chatbotConfig,
    isChatbotConfigError,
    isChatbotConfigLoading,
    assistantData,
  ]);
};
