import * as React from 'react';
import { InjectedFormikProps, Form, Field, withFormik } from 'formik';
import { useIntl, FormattedMessage } from 'gatsby-plugin-intl';
import { firebase, firestore, useAuth } from 'gatsby-theme-firebase';
import {
  FormControl,
  FormLabel,
  Input,
  Button,
  Spinner,
  FormHelperText,
  Stack,
  Box,
  useToastOptions,
  useToast,
  Checkbox,
  CheckboxGroup,
  InputGroup,
  InputLeftAddon
} from '@chakra-ui/core';
import withPerson from '../../hooks/withPerson';
import useAnalytics from '../../hooks/useAnalytics';

interface FormValues {
  displayName: string;
  should_show_profileURL: boolean;
  preferences: any;
  smsNumber: string;
}

const InnerForm: React.FC<InjectedFormikProps<
  SettingsFormProps,
  FormValues
>> = (props) => {
  const {
    touched,
    errors,
    isSubmitting,
    setFieldValue,
    initialDisplayName
  } = props;
  const intl = useIntl();
  return (
    <Form>
      <Stack spacing={6}>
        <Box>
          <Field name="displayName">
            {(field: { name: string }) => (
              <FormControl
                isInvalid={errors[field.name] && touched[field.name]}
              >
                <FormLabel htmlFor={field.name}>
                  {intl.formatMessage({
                    id: 'Settings.Display Name'
                  })}
                </FormLabel>
                <Input value={initialDisplayName} isReadOnly />
                <FormHelperText id="email-helper-text">
                  {intl.formatMessage({ id: 'Settings.help' })}
                </FormHelperText>
              </FormControl>
            )}
          </Field>
        </Box>
        <Box>
          <Field name="preferences">
            {() => (
              <FormControl>
                <FormLabel>
                  {intl.formatMessage({
                    id: 'Settings.Notifications Prefs'
                  })}
                </FormLabel>
                <CheckboxGroup
                  name="preferences"
                  onChange={() => {
                    // check if sms deselected and sms is available, clear sms number
                    if (
                      props.values.preferences.contact_via_sms &&
                      props.values.smsNumber
                    ) {
                      setFieldValue('smsNumber', '');
                    }
                    setFieldValue(
                      'preferences.contact_via_sms',
                      !props.values.preferences?.contact_via_sms
                    );
                  }}
                >
                  <Checkbox isDisabled defaultIsChecked>
                    {intl.formatMessage({ id: 'Settings.Email' })}
                  </Checkbox>

                  <Checkbox
                    defaultIsChecked={props.values.preferences?.contact_via_sms}
                  >
                    {intl.formatMessage({ id: 'Settings.SMS' })}
                    {props.values.preferences?.contact_via_sms ? (
                      <Field name="smsNumber">
                        {({ field }) => (
                          <FormControl>
                            <InputGroup>
                              <InputLeftAddon>"+"</InputLeftAddon>
                              <Input
                                type="tel"
                                roundedLeft="0"
                                defaultValue={props.initialSmsNumber}
                                placeholder="44XXXXXX"
                                {...field}
                              />
                            </InputGroup>
                          </FormControl>
                        )}
                      </Field>
                    ) : (
                      ''
                    )}
                  </Checkbox>
                </CheckboxGroup>
              </FormControl>
            )}
          </Field>
        </Box>
        <Box>
          <Button
            mt={4}
            variantColor="teal"
            isLoading={isSubmitting}
            type="submit"
          >
            {intl.formatMessage({ id: 'Settings.save' })}
          </Button>
        </Box>
      </Stack>
    </Form>
  );
};

interface SettingsFormProps {
  initialDisplayName: string;
  initialPreferences: {};
  initialSmsNumber: string;
}

interface SettingsFormInnerProps extends SettingsFormProps {
  saveDisplayName: () => void;
  toast: (toast: useToastOptions) => void;
  uid: string;
}

const WithFormik = withFormik<SettingsFormInnerProps, FormValues>({
  // Transform outer props into form values
  mapPropsToValues: (props) => ({
    displayName: props.initialDisplayName,
    preferences: props.initialPreferences,
    smsNumber: props.initialSmsNumber,
    should_show_profileURL: false
  }),

  handleSubmit: async (values, actions) => {
    const { settingsChanged } = useAnalytics();

    //Check if notification preference is set to SMS and contact number is not null
    if (values.preferences.contact_via_sms && !values.smsNumber) {
      actions.props.toast({
        position: 'bottom-right',
        title: <FormattedMessage id="Settings.SMS-missing" />,
        description: <FormattedMessage id="Settings.SMS-desc" />,
        status: 'error',
        isClosable: true
      });
      actions.setSubmitting(false);
      return;
    }

    try {
      //  Public Profile
      await firebase.database().ref(`profiles/${actions.props.uid}/`).update({
        displayName: values.displayName
      });

      //  Settings
      await firebase
        .firestore()
        .collection('accounts')
        .doc(actions.props.uid)
        .update({
          smsNumber: values.smsNumber.length > 0 ? values.smsNumber : null,
          'preferences.contact_via_sms': values.smsNumber.length > 0
        });

      actions.props.toast({
        position: 'bottom-right',
        title: <FormattedMessage id="Settings.saved" />,
        description: <FormattedMessage id="Settings.msg" />,
        status: 'success',
        isClosable: true
      });

      settingsChanged();
      actions.setSubmitting(false);
    } catch (e) {
      actions.props.toast({
        position: 'bottom-right',
        title: <FormattedMessage id="Settings.error" />,
        description: e.message,
        status: 'error',
        isClosable: true
      });
      actions.setSubmitting(false);
    }
  }
})(InnerForm);

// Wrap our form with the withFormik HoC
const SettingsForm: React.FC<SettingsFormProps> = (props) => {
  const toast = useToast();
  const { profile } = useAuth();

  const [account, setAccount] = React.useState();
  React.useEffect(() => {
    if (profile?.uid) {
      firestore
        .collection('accounts')
        .doc(profile?.uid)
        .get()
        .then((doc) => {
          if (!doc.exists) {
            // TODO: Should have some kind of error handling/alerting in place
            console.log('No such document!');
          } else {
            const data = doc.data();
            if (data) {
              setAccount(data);
            }
          }
        });
    }
  }, [profile, setAccount]);

  const { person: me, loading: loadingMe } = withPerson({
    uid: profile ? profile.uid : ''
  });

  return (
    <>
      {(!account || loadingMe) && <Spinner />}
      {me && account && (
        <WithFormik
          toast={toast}
          uid={me.uid}
          saveDisplayName={() => me.displayName}
          initialDisplayName={me.displayName}
          initialPreferences={account.preferences}
          initialSmsNumber={account.smsNumber}
          {...props}
        />
      )}
    </>
  );
};

export default SettingsForm;