import React, {useCallback, useMemo} from 'react';
import {View} from 'react-native';
import {useTranslation} from 'react-i18next';
import {KeyboardAwareScrollView} from 'react-native-keyboard-controller';
import {FormProvider} from 'react-hook-form';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import {useMutation} from '@tanstack/react-query';
import {IconCheck, IconPoint} from '@tabler/icons-react-native';
import {
  Button,
  Typography,
  InputPasswordController,
  Title,
  Spinner,
} from '@components';
import {Navigation} from '@interfaces/navigation';
import {useLoginActions} from '@modules/login/hooks/useAuth';
import {
  UpdatePasswordForm,
  useUpdatePasswordForm,
} from '@modules/login/hooks/useUpdatePasswordForm';
import {CommunityHeader} from '@modules/login/components/CommunityHeader';
import {AmplitudeLoginTypes, PasswordRule} from '@modules/login/interfaces';
import {useGetPasswordCode} from '@modules/login/hooks/useGetPasswordCode';
import {updatePasswordWithCode} from '@modules/login/services';
import {UPDATE_PASSWORD_RULES} from '@modules/login/constants';
import {updatePassword} from '@services/user';
import {useTheme} from '@shared/theme';
import {Screens} from '@shared/constants';

import {styles} from './styles';

function UpdatePassword({
  route: {
    params: {loginResponse, from2fa, code},
  },
}: Navigation<Screens.UPDATE_PASSWORD>) {
  const {t} = useTranslation();
  const {theme} = useTheme();
  const {top = 32} = useSafeAreaInsets();
  const {dispatchLoginActions} = useLoginActions();
  const {codeInstance, isLoading: isLoadingCode} = useGetPasswordCode({code});
  const finalInstance = useMemo(
    () => codeInstance || loginResponse?.instance,
    [codeInstance, loginResponse],
  );
  const hasPasswordRules =
    finalInstance?.passwordType &&
    Object.values(finalInstance?.passwordType).some(Boolean);
  const methods = useUpdatePasswordForm(finalInstance?.passwordType ?? null);
  const {formState, handleSubmit, watch} = methods;
  const passwordErrors = (formState.errors.password?.types?.custom ||
    []) as PasswordRule[];

  // Create rule list by instance passwordType properties
  const rules = useMemo(
    () =>
      Object.keys(UPDATE_PASSWORD_RULES).reduce((prev, current) => {
        const rule = UPDATE_PASSWORD_RULES[current];
        if (finalInstance?.passwordType?.[rule.instanceProperty]) {
          prev.push({
            id: current as PasswordRule,
            label: rule.label,
          });
        }
        return prev;
      }, [] as {id: PasswordRule; label: string}[]),
    [finalInstance],
  );

  const {mutate: updatePasswordMutation, isPending} = useMutation({
    mutationFn: updatePassword,
    onSuccess: () => {
      dispatchLoginActions({
        tokens: loginResponse,
        loginType: from2fa
          ? AmplitudeLoginTypes.OTP
          : AmplitudeLoginTypes.REGULAR,
      });
    },
  });

  const onSubmit = useCallback(
    (formValues: UpdatePasswordForm) => {
      code
        ? updatePasswordWithCode({code, password: formValues.password})
        : updatePasswordMutation({
            password: formValues.password,
            token: loginResponse!.accessToken,
            id: loginResponse!.user.id,
          });
    },
    [code, loginResponse, updatePasswordMutation],
  );
  const passwordField = watch('password');

  return isLoadingCode ? (
    <View style={styles.loadingContainer}>
      <Spinner />
    </View>
  ) : (
    <KeyboardAwareScrollView
      contentContainerStyle={[
        styles.container,
        {backgroundColor: theme.background.layout.default, paddingTop: top},
      ]}
      showsVerticalScrollIndicator={false}
      bounces={false}
      alwaysBounceVertical={false}
      scrollEnabled={false}
      keyboardDismissMode="interactive"
      keyboardShouldPersistTaps="handled">
      {!!finalInstance && (
        <CommunityHeader
          logo={finalInstance.logo}
          instanceName={finalInstance.name}
        />
      )}
      <Title
        title={t('authentication.update.title')}
        titleNumberOfLines={2}
        size="l"
      />
      <FormProvider {...methods}>
        <View style={styles.form}>
          <InputPasswordController
            name="password"
            autoCapitalize="none"
            label={t('authentication.update.create_password')}
          />
          <InputPasswordController
            name="repeatPassword"
            autoCapitalize="none"
            label={t('authentication.update.repeat_password')}
          />
          {hasPasswordRules && (
            <>
              {rules.map(rule => {
                const passed = !passwordErrors.includes(
                  UPDATE_PASSWORD_RULES[rule.id].label as PasswordRule,
                );
                const color =
                  formState.isDirty && !passed
                    ? theme.text.feedback.error
                    : passed && passwordField
                    ? theme.text.feedback.success
                    : theme.text.neutral.lighter;
                return (
                  <View key={rule.id} style={styles.rule}>
                    {passed && formState.isDirty ? (
                      <IconCheck
                        color={theme.text.feedback.success}
                        size={20}
                      />
                    ) : (
                      <IconPoint color={color} size={20} />
                    )}
                    <Typography color={color}>{rule.label}</Typography>
                  </View>
                );
              })}
            </>
          )}
        </View>
        <Button
          text={t('authentication.update.submit')}
          onPress={handleSubmit(onSubmit)}
          isLoading={isPending}
        />
      </FormProvider>
    </KeyboardAwareScrollView>
  );
}

export default UpdatePassword;
