import { useEffect, useState } from 'react';
import { Helmet } from 'react-helmet-async';
import { useMutation, useQueryClient } from 'react-query';
import { useNavigate } from 'react-router';
import { useSearchParams } from 'react-router-dom';

import Stack from '@material-hu/mui/Stack';

import HuTaskFocusHeader from '@material-hu/components/design-system/Header/TaskFocus';
import HuTitle from '@material-hu/components/design-system/Title';

import { useAuth } from 'src/contexts/JWTContext';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import { formatTitle } from 'src/utils/helmetUtils';
import { useLokaliseTranslation } from 'src/utils/i18n';

import NotificationChannels from '../components/NotificationChannels';
import NotificationModuleCard from '../components/NotificationModuleCard';
import NotificationsConfigLoading from '../components/NotificationsConfigLoading';
import {
  NotificationChannelCodes,
  NotificationModuleCodes,
} from '../constants';
import { useNotificationsConfigPageQueries, useThrottle } from '../hooks';
import { notificationsKeys } from '../queries';
import {
  updateChannelsPreferences,
  updateFeedNotificationConfiguration,
} from '../services';
import {
  FeedNotificationConfigurationMode,
  type NotificationModuleConfig,
} from '../types';
import {
  getConfigPageTitleAndDescription,
  getEnabledModules,
  getNotificationChannelsConfig,
  isModuleVisible,
  nonNullable,
} from '../utils';

const NOTIFICATIONS_MODULE_QUERY_PARAM = 'module';

const getModuleFromSearchParams = (
  searchParams: URLSearchParams,
): NotificationModuleCodes | undefined => {
  const moduleParam = searchParams
    .get(NOTIFICATIONS_MODULE_QUERY_PARAM)
    ?.trim()
    .toUpperCase();

  return Object.values(NotificationModuleCodes).find(
    moduleCode => moduleCode === moduleParam,
  );
};

const NotificationsConfig = () => {
  const HuGoThemeProvider = useHuGoTheme();
  const { permissions: userPermissions, communityFeatures } = useAuth();
  const { t } = useLokaliseTranslation([
    'notifications_center',
    'apps',
    'general',
    'post',
  ]);
  const navigate = useNavigate();
  const [searchParams, setSearchParams] = useSearchParams();
  const queryClient = useQueryClient();

  const [modulesConfig, setModulesConfig] = useState<NotificationModuleConfig>(
    {},
  );

  const [selectedModule, setSelectedModule] = useState<
    NotificationModuleCodes | undefined
  >(() => getModuleFromSearchParams(searchParams));

  const updateChannelsPreferencesMutation = useMutation(
    ({
      channelCode,
      moduleCode,
      enabled,
    }: {
      channelCode: NotificationChannelCodes;
      moduleCode: NotificationModuleCodes;
      enabled: boolean;
    }) => updateChannelsPreferences(channelCode, moduleCode, enabled),
  );

  const updateFeedNotificationConfigurationMutation = useMutation(
    ({ enabled }: { enabled: boolean }) =>
      updateFeedNotificationConfiguration(
        FeedNotificationConfigurationMode.EMAIL,
        enabled,
      ),
  );

  const {
    modulesPreferences,
    disabledModules,
    feedEmailNotificationsEnabled,
    isLoading,
  } = useNotificationsConfigPageQueries();

  useEffect(() => {
    if (modulesPreferences) {
      const feedNotificationModule =
        modulesPreferences[NotificationModuleCodes.FEED];

      if (!feedNotificationModule) {
        setModulesConfig(modulesPreferences);
        return;
      }

      setModulesConfig({
        ...modulesPreferences,
        [NotificationModuleCodes.FEED]: {
          ...feedNotificationModule,
          channels: {
            ...feedNotificationModule.channels,
            [NotificationChannelCodes.MAIL]:
              feedEmailNotificationsEnabled ??
              feedNotificationModule.channels[NotificationChannelCodes.MAIL] ??
              false,
          },
        },
      });
    }
  }, [modulesPreferences, feedEmailNotificationsEnabled]);

  useEffect(() => {
    setSelectedModule(getModuleFromSearchParams(searchParams));
  }, [searchParams]);

  const handleModuleSelect = (moduleName: NotificationModuleCodes) => {
    setSelectedModule(moduleName);
    setSearchParams(
      prev => {
        prev.set(NOTIFICATIONS_MODULE_QUERY_PARAM, moduleName.toLowerCase());
        return prev;
      },
      { replace: true },
    );
  };

  const handleBack = () => {
    if (selectedModule) {
      setSelectedModule(undefined);
      setSearchParams(
        prev => {
          prev.delete(NOTIFICATIONS_MODULE_QUERY_PARAM);
          return prev;
        },
        { replace: true },
      );
      return;
    }

    navigate(-1);
  };

  const handleChannelToggle = useThrottle(
    (channelCode: NotificationChannelCodes, isEnabled: boolean) => {
      if (!selectedModule) return;

      const previousConfig =
        modulesConfig[selectedModule].channels[channelCode];

      setModulesConfig(prevConfig => ({
        ...prevConfig,
        [selectedModule]: {
          ...prevConfig[selectedModule],
          channels: {
            ...prevConfig[selectedModule].channels,
            [channelCode]: isEnabled,
          },
        },
      }));

      const isFeedEmailPreference =
        selectedModule === NotificationModuleCodes.FEED &&
        channelCode === NotificationChannelCodes.MAIL;

      if (isFeedEmailPreference) {
        updateFeedNotificationConfigurationMutation.mutate(
          {
            enabled: isEnabled,
          },
          {
            onSuccess: () => {
              queryClient.invalidateQueries(
                notificationsKeys.getFeedEmailNotificationConfiguration(),
              );
            },
            onError: () => {
              // Revert the state change if mutation fails
              setModulesConfig(prevConfig => ({
                ...prevConfig,
                [selectedModule]: {
                  ...prevConfig[selectedModule],
                  channels: {
                    ...prevConfig[selectedModule].channels,
                    [channelCode]: previousConfig,
                  },
                },
              }));
            },
          },
        );
        return;
      }

      updateChannelsPreferencesMutation.mutate(
        {
          channelCode,
          moduleCode: selectedModule,
          enabled: isEnabled,
        },
        {
          onError: () => {
            // Revert the state change if mutation fails
            setModulesConfig(prevConfig => ({
              ...prevConfig,
              [selectedModule]: {
                ...prevConfig[selectedModule],
                channels: {
                  ...prevConfig[selectedModule].channels,
                  [channelCode]: previousConfig,
                },
              },
            }));
          },
        },
      );
    },
    500,
  );

  const { title, description } = getConfigPageTitleAndDescription(
    selectedModule,
    t,
  );

  if (
    !nonNullable(modulesPreferences) ||
    !nonNullable(disabledModules) ||
    isLoading ||
    Object.keys(modulesConfig).length === 0
  ) {
    return (
      <NotificationsConfigLoading
        title={title}
        description={description}
      />
    );
  }

  const enabledModules = getEnabledModules(disabledModules).filter(moduleName =>
    isModuleVisible(moduleName, userPermissions, communityFeatures),
  );

  return (
    <HuGoThemeProvider>
      <Stack sx={{ height: '100%' }}>
        <Helmet>
          <title>{formatTitle(t('general:settings'))}</title>
        </Helmet>
        <HuTaskFocusHeader
          title={
            selectedModule
              ? t(`modules.${selectedModule}`)
              : t('general:settings')
          }
          onBack={handleBack}
        />
        <Stack
          sx={{
            backgroundColor: theme =>
              theme.palette.new.background.layout.default,
            height: '100%',
            p: 3,
            gap: 3,
            alignItems: 'center',
          }}
        >
          <Stack sx={{ width: '70%', maxWidth: '1040px', gap: 2 }}>
            <HuTitle
              variant="L"
              title={title}
              description={description}
            />
            {nonNullable(selectedModule) && (
              <NotificationChannels
                notificationChannelsConfig={getNotificationChannelsConfig(
                  modulesConfig[selectedModule].channels,
                  selectedModule,
                  t,
                )}
                onChannelToggle={handleChannelToggle}
              />
            )}
            {!nonNullable(selectedModule) && (
              <Stack
                sx={{
                  display: 'grid',
                  gridTemplateColumns: {
                    xs: '1fr',
                    sm: 'repeat(2, 1fr)',
                  },
                  gap: 2,
                  mb: 2,
                  width: '100%',
                }}
              >
                {enabledModules.map(moduleName => {
                  return (
                    <NotificationModuleCard
                      key={moduleName}
                      moduleName={moduleName}
                      channelsPreferences={modulesConfig[moduleName].channels}
                      isLoading={false}
                      onSelect={handleModuleSelect}
                    />
                  );
                })}
              </Stack>
            )}
          </Stack>
        </Stack>
      </Stack>
    </HuGoThemeProvider>
  );
};

export default NotificationsConfig;
