import { type FC, useEffect, useMemo } from 'react';
import { FormProvider, useForm, useWatch } from 'react-hook-form';
import { useMutation } from 'react-query';
import { useNavigate } from 'react-router-dom';

import { logEvent } from '@amplitude/analytics-browser';
import Stack from '@material-hu/mui/Stack';
import useTheme from '@material-hu/mui/styles/useTheme';
import Typography from '@material-hu/mui/Typography';

import FormRadioGroup from '@material-hu/components/composed-components/RadioGroup/form';
import Button from '@material-hu/components/design-system/Buttons/Button';
import useSnackbar from '@material-hu/components/design-system/Snackbar';
import FormSwitcher from '@material-hu/components/design-system/Switcher/form';

import { useAuth } from 'src/contexts/JWTContext';
import useGeneralError from 'src/hooks/useGeneralError';
import usePermissions from 'src/hooks/usePermissions';
import useRequiredParams from 'src/hooks/useRequiredParams';
import { signedUpload } from 'src/pages/dashboard/serviceManagement/utils';
import { editGroup } from 'src/services/groups';
import { EventName } from 'src/types/amplitude';
import {
  type Group,
  type GroupBody,
  GroupMembersPolicies,
  GroupPrivacyPolicies,
  GroupPublicationPolicies,
} from 'src/types/groups';
import { IconTypes } from 'src/types/icons';
import { insertIf } from 'src/utils/arrays';
import { preprocessImage, revokeLocalUrl } from 'src/utils/files';
import { useLokaliseTranslation as useTranslation } from 'src/utils/i18n';
import { formatOutgoingIcon } from 'src/utils/icons';
import { UserPermissions } from 'src/utils/permissions';

import { FixedActionFooter } from 'src/components/FixedActionFooter';
import {
  FormCoverPicture,
  FormImageMenu,
  FormSelect,
  FormTextField,
} from 'src/components/FormInputs';

import ConfigurationSection, {
  type ConfigurationSectionProps,
} from '../../components/ConfigurationSection';
import MembersCanLeaveConfig from '../../components/MembersCanLeaveConfig';
import {
  GROUP_MANAGEMENT_FOOTER_HEIGHT,
  GROUP_MANAGEMENT_SIDEBAR_WIDTH,
  GroupAprovalPolicyKeys,
  GroupPrivacyPoliciesKeys,
  GroupPublicationPoliciesKeys,
  getPrivacyIcon,
} from '../../constants';
import { groupsRoutes } from '../../routes';
import { GROUP_DETAIL_PAGE_BANNER_DIMENSIONS } from '../../utils';

type ManageConfigurationProps = {
  group: Group;
};

const ManageConfiguration: FC<ManageConfigurationProps> = props => {
  const { group } = props;
  const { id: groupId } = useRequiredParams(['id']);
  const { t } = useTranslation(['group']);
  const navigate = useNavigate();
  const { enqueueSnackbar } = useSnackbar();
  const { user } = useAuth();
  const theme = useTheme();

  const showGeneralError = useGeneralError();
  const { hasAll: canCreateMultiCompanyGroups } = usePermissions([
    UserPermissions.CREATE_MULTICOMPANY_GROUPS,
    UserPermissions.VIEW_MULTICOMPANY_GROUPS,
  ]);

  const form = useForm({
    defaultValues: {
      title: group.title || '',
      description: group.description || '',
      banner: { url: group?.bannerUrl, file: null },
      icon: group.icon || null,
      privacyPolicy: group.privacyPolicy || null,
      approvalPolicy: group.approvalPolicy || null,
      publicationPolicy: group.publicationPolicy || null,
      isMultiCompany: group.isMultiCompany || false,
      membersCanLeave: group.membersCanLeave ?? false,
    },
    mode: 'onChange',
  });

  const [isMultiCompany, publicationPolicy] = useWatch({
    control: form.control,
    name: ['isMultiCompany', 'publicationPolicy'],
  });

  // Automatically set privacy to SECRET when multi-company is turned on
  useEffect(() => {
    if (isMultiCompany) {
      form.setValue('privacyPolicy', GroupPrivacyPolicies.SECRET);
    }
  }, [isMultiCompany, form]);

  const privacyOptions = useMemo(
    () =>
      GroupPrivacyPoliciesKeys.map(type => {
        const disabled = isMultiCompany;
        return {
          value: type,
          label: t(`group:group_option_${type.toLowerCase()}`),
          icon: getPrivacyIcon(type as GroupPrivacyPolicies, disabled),
          disabled,
        };
      }),
    [isMultiCompany, t],
  );

  const publicationOptions = GroupPublicationPoliciesKeys.map(value => ({
    value,
    label: t(`group:post_${value.toLowerCase()}`),
    helperText: t(`group:post_${value.toLowerCase()}_info`),
  }));

  const approvalPolicyOptions = GroupAprovalPolicyKeys.map(value => ({
    value,
    label: t(`group:approval_policy_${value.toLowerCase()}`),
    helperText: t(`group:approval_policy_${value.toLowerCase()}_info`),
  }));

  const { handleSubmit, watch } = form;
  const { icon } = watch();

  const sections: ConfigurationSectionProps[] = useMemo(
    () => [
      {
        titleKey: 'group:group_name',
        gap: 2,
        renderContent: () => (
          <FormTextField
            label={t('group:group_name')}
            name="title"
            placeholder={t('group:group_name_placeholder')}
            inputProps={{ maxLength: 50 }}
            rules={{ required: true }}
          />
        ),
      },
      {
        titleKey: 'group:icon_web',
        gap: 2,
        renderContent: () => (
          <FormImageMenu
            name="icon"
            defaultIcon={icon}
          />
        ),
      },
      {
        titleKey: 'group:banner_image_web',
        gap: 2,
        renderContent: () => (
          <FormCoverPicture
            name="banner"
            recommendedWidth={GROUP_DETAIL_PAGE_BANNER_DIMENSIONS.WIDTH}
            recommendedHeight={GROUP_DETAIL_PAGE_BANNER_DIMENSIONS.HEIGHT}
          />
        ),
      },
      {
        titleKey: 'group:group_description_web',
        gap: 2,
        renderContent: () => (
          <FormTextField
            label={t('group:group_description_web')}
            name="description"
            multiline
            showCounter
            max={250}
            placeholder={t('group:group_description_placeholder_web')}
            inputProps={{ maxLength: 250, sx: { minHeight: '120px' } }}
          />
        ),
      },
      ...insertIf(canCreateMultiCompanyGroups, {
        gap: 2,
        renderContent: () => (
          <FormSwitcher
            name="isMultiCompany"
            switcherProps={{
              title: t('group:multi_company_create_group'),
              description: t('group:multi_company_create_group_description'),
              disabled: true,

              sx: {
                // Custom track bg when disabled and on (light blue)
                '& .MuiSwitch-switchBase.Mui-disabled.Mui-checked + .MuiSwitch-track':
                  {
                    backgroundColor:
                      theme.palette.new.action.background.brand.selected,
                    opacity: 1,
                  },

                // Custom thumb white when disabled (looks like non-disabled)
                '& .MuiSwitch-switchBase.Mui-disabled .MuiSwitch-thumb': {
                  backgroundColor: 'common.white',
                },
              },
            }}
          />
        ),
      }),
      {
        titleKey: 'group:privacy_web',
        gap: 2,
        renderContent: () => (
          <FormSelect
            variant="outlined"
            name="privacyPolicy"
            label={t('group:privacy_type_web')}
            options={privacyOptions}
            disabled={isMultiCompany}
            selectProps={{
              inputProps: {
                sx: {
                  display: 'flex',
                  flexDirection: 'row',
                  alignItems: 'center',
                  gap: 1,
                  // TODO: match color - neutralBgTransparent has no direct equivalent in new palette
                  backgroundColor: isMultiCompany
                    ? theme.palette.new.action.background.neutral.hover
                    : undefined,
                  '& .MuiListItemIcon-root': {
                    minWidth: 0,
                  },
                },
              },
            }}
            MenuProps={{
              PaperProps: {
                style: {
                  maxWidth: '650px',
                },
              },
            }}
          />
        ),
      },
      {
        titleKey: 'group:post_policy',
        gap: 1,
        renderContent: () => (
          <FormRadioGroup
            name="publicationPolicy"
            options={publicationOptions}
          />
        ),
      },
      ...(publicationPolicy === GroupPublicationPolicies.ONLY_ADMINS
        ? []
        : [
            {
              titleKey: 'group:approval_policy_setting_web',
              gap: 2,
              renderContent: () => (
                <FormRadioGroup
                  name="approvalPolicy"
                  options={approvalPolicyOptions}
                />
              ),
            },
          ]),
      {
        titleKey: 'group:members_can_leave_title',
        gap: 1.5,
        renderContent: () => <MembersCanLeaveConfig />,
      },
    ],
    [
      canCreateMultiCompanyGroups,
      icon,
      t,
      privacyOptions,
      publicationOptions,
      approvalPolicyOptions,
      publicationPolicy,
    ],
  );

  const { mutate: editGroupMutation, isLoading: isEditing } = useMutation(
    async ({ banner = { file: null, url: null }, ...body }: GroupBody) => {
      const bannerUrl = await preprocessImage(banner);
      const editGroupBody = { ...body, bannerUrl, isMultiCompany };

      if (editGroupBody.icon.file) {
        // Replace blob url with uploaded s3 url
        revokeLocalUrl(editGroupBody.icon.value);
        const logoUrl = await uploadLogo.mutateAsync(editGroupBody.icon.file);
        editGroupBody.icon = { value: logoUrl, type: IconTypes.IMAGE };
      }

      editGroupBody.icon = formatOutgoingIcon(editGroupBody.icon);
      return editGroup(groupId, editGroupBody);
    },
    {
      onSuccess: ({ data }) => {
        enqueueSnackbar({
          title: t('group:groups_group_edit_success'),
          variant: 'success',
        });
        logEvent(EventName.GROUPS_GROUP_UPDATED, {
          userId: user?.id,
          groupId,
          newState: data,
        });
        navigate(groupsRoutes.detail(groupId));
      },
      onError: err => showGeneralError(err),
    },
  );

  const uploadLogo = useMutation((file: File) => signedUpload(file, true), {
    onError: err => showGeneralError(err),
  });

  const handleSave = () => {
    const formValues = form.getValues();

    const description = formValues?.description;
    const { ...restFormValues } = formValues;

    editGroupMutation({
      ...restFormValues,
      description: description || undefined,
      banner: formValues?.banner,
      membersPolicy: GroupMembersPolicies.TARGETED_USERS,
    });
  };

  const isLoading = isEditing || uploadLogo.isLoading;
  const isDisabled =
    isLoading || !form.formState.isValid || !form.formState.isDirty;

  return (
    <FormProvider {...form}>
      <form
        noValidate
        onSubmit={handleSubmit(handleSave)}
      >
        <Stack sx={{ gap: 2, mb: `${GROUP_MANAGEMENT_FOOTER_HEIGHT}px` }}>
          <Stack>
            <Typography
              variant="globalL"
              fontWeight="fontWeightSemiBold"
            >
              {t('group:configuration')}
            </Typography>
            <Typography
              variant="globalS"
              color={theme => theme.palette.new.text.neutral.lighter}
            >
              {t('group:configure_info')}
            </Typography>
          </Stack>
          {sections.map(section => (
            <ConfigurationSection
              key={section.titleKey || 'multi-company'}
              {...section}
            />
          ))}
        </Stack>

        <FixedActionFooter
          left={GROUP_MANAGEMENT_SIDEBAR_WIDTH}
          actions={
            <Button
              variant="contained"
              type="submit"
              disabled={isDisabled}
              sx={{ ml: 'auto' }}
            >
              {t('group:finish')}
            </Button>
          }
        />
      </form>
    </FormProvider>
  );
};

const ManageConfigurationGuard = (props: Partial<ManageConfigurationProps>) => {
  const { group } = props;
  if (!group) {
    return null;
  }

  return <ManageConfiguration group={group} />;
};

export default ManageConfigurationGuard;
