import React, { useState } from 'react';
import {
  Alert,
  Button,
  Col,
  ControlLabel,
  Form,
  FormControl,
  FormGroup,
  Glyphicon,
  HelpBlock,
  Row,
} from 'react-bootstrap';
import { useForm, FormProvider } from 'react-hook-form';
import { LinkContainer } from 'react-router-bootstrap';
import { useResource } from 'rest-hooks';
import AddressResource from '../../resources/address';
import { addressFormatter } from '../Address/utils';
import FieldAlert from '../Form/FieldAlert';
import TextFieldGroup from '../Form/TextFieldGroup';
import CreateAddress from './CreateAddress';
import styles from './ShippingForm.module.css';
import { addAddressIfAbsent } from '../../helpers';

const FORM_LAYOUT = { labelCol: { sm: 4 }, fieldCol: { sm: 8 } };

function ShippingForm(props) {
  const {
    investigation,
    shipment,
    defaultShippingAddress,
    defaultReturnAddress,
    onSubmitAsync,
  } = props;
  const { id: investigationId, name: investigationName } = investigation;

  const methods = useForm({
    defaultValues: {
      name: 'shipment',
      ...shipment,
      defaultShippingAddress: defaultShippingAddress?._id,
      defaultReturnAddress: defaultReturnAddress && defaultReturnAddress._id,
    },
  });

  const { handleSubmit, errors, register, setValue, watch } = methods;
  const { isSubmitting } = methods.formState;

  const watchedShippingAddressId = watch('defaultShippingAddress');
  const watchedReturnAddressId = watch('defaultReturnAddress') || null;

  const userAddresses = useResource(AddressResource.listShape(), {});
  const shippingAddressOptions = addAddressIfAbsent(
    userAddresses,
    defaultShippingAddress
  );
  const returnAddressOptions = addAddressIfAbsent(
    userAddresses,
    defaultReturnAddress
  );

  const [alert, setAlert] = useState();

  async function handleFormSubmit(values) {
    try {
      setAlert(undefined);
      await onSubmitAsync({
        ...values,
        defaultReturnAddress: values.defaultReturnAddress || null,
      });
    } catch (error) {
      setAlert({ type: 'danger', message: `An error occurred while saving.` });
      console.error(error.response);
    }
  }

  return (
    <>
      {alert && (
        <Alert bsStyle={alert.type} onDismiss={() => setAlert(undefined)}>
          {alert.message}
        </Alert>
      )}
      <Form horizontal>
        {shipment && <input name="_id" type="hidden" ref={register} />}
        <input name="name" type="hidden" ref={register} />
        <input
          name="investigationId"
          type="hidden"
          defaultValue={investigationId}
          ref={register}
        />
        <input
          name="investigationName"
          type="hidden"
          defaultValue={investigationName}
          ref={register}
        />

        <p className={styles.text}>
          The addresses you provide below will be used as defaults for new
          parcels.
        </p>

        <FormGroup controlId="defaultShippingAddress">
          <Col {...FORM_LAYOUT.labelCol}>
            <ControlLabel>
              Default sender's address{' '}
              <span className={styles.hint}>– required</span>
            </ControlLabel>
          </Col>
          <Col {...FORM_LAYOUT.fieldCol}>
            <FormControl
              name="defaultShippingAddress"
              componentClass="select"
              inputRef={register({ required: true })}
            >
              <option value="">Select default sender's address...</option>
              {shippingAddressOptions.map((addr) => (
                <option key={addr._id} value={addr._id}>
                  {addressFormatter(addr)}
                </option>
              ))}
              )
            </FormControl>
            {shipment &&
              watchedShippingAddressId &&
              shipment.defaultShippingAddress !== watchedShippingAddressId && (
                <HelpBlock>
                  <Glyphicon glyph="warning-sign" /> The new default address
                  will not be applied to existing parcels automatically
                </HelpBlock>
              )}
            {errors.defaultShippingAddress && (
              <FieldAlert
                fieldLabel="Default sender's address"
                error={errors.defaultShippingAddress}
              />
            )}
            <HelpBlock>
              {shippingAddressOptions.length === 0 && 'No addresses found! '}
              <CreateAddress
                investigation={investigation}
                onCreate={(id) => {
                  setValue('defaultShippingAddress', id);
                }}
              />
            </HelpBlock>
          </Col>
        </FormGroup>

        <FormGroup controlId="defaultReturnAddress">
          <Col {...FORM_LAYOUT.labelCol}>
            <ControlLabel>
              Default return address{' '}
              <span className={styles.hint}>– optional</span>
            </ControlLabel>
            <p className={styles.info}>
              The <em>return address</em> is the address to which you would like
              a parcel to be returned at the end of the investigation. Parcels
              without a return address are discarded at the end of the
              investigation.
            </p>
          </Col>
          <Col {...FORM_LAYOUT.fieldCol}>
            <FormControl
              name="defaultReturnAddress"
              componentClass="select"
              inputRef={register}
            >
              <option value="">No default return address</option>
              {returnAddressOptions.map((addr) => (
                <option key={addr._id} value={addr._id}>
                  {addressFormatter(addr)}
                </option>
              ))}
            </FormControl>
            {shipment &&
              shipment.defaultReturnAddress !== watchedReturnAddressId && (
                <HelpBlock>
                  <Glyphicon glyph="warning-sign" />
                  The new default address will not be applied to existing
                  parcels automatically
                </HelpBlock>
              )}
            {errors.defaultReturnAddress && (
              <FieldAlert
                fieldLabel="Default return address"
                error={errors.defaultReturnAddress}
              />
            )}
            <HelpBlock>
              {returnAddressOptions.length === 0 && 'No addresses found! '}
              <CreateAddress
                investigation={investigation}
                onCreate={(id) => {
                  setValue('defaultReturnAddress', id);
                }}
              />
            </HelpBlock>
          </Col>
        </FormGroup>
        <FormProvider {...methods}>
          <TextFieldGroup
            name="comments"
            type="textarea"
            layout={FORM_LAYOUT}
          />
        </FormProvider>

        <Row>
          <Col {...FORM_LAYOUT.fieldCol} smOffset={FORM_LAYOUT.labelCol.sm}>
            <Button
              bsStyle="primary"
              disabled={isSubmitting}
              onClick={handleSubmit(handleFormSubmit)}
            >
              {isSubmitting ? 'Saving...' : 'Save'}
            </Button>
            <LinkContainer to={`/investigation/${investigation.id}/shipping`}>
              <Button bsStyle="link">Cancel</Button>
            </LinkContainer>
          </Col>
        </Row>
      </Form>
    </>
  );
}

export default ShippingForm;
