import React, { Fragment } from 'react'
import styled from 'styled-components'
import { th } from '@pubsweet/ui-toolkit'
import { omit, isBoolean, get } from 'lodash'
import { compose, withState, withHandlers } from 'recompose'

import {
  Row,
  Item,
  Label,
  Text,
  DragHandle,
  AuthorCard,
  ActionLink,
  SortableList,
  withFetching,
  handleError,
} from './'

const castToBool = author => ({
  ...author,
  isCorresponding: isBoolean(author.isCorresponding) && author.isCorresponding,
})

const setCorrespondingAuthor = authors => {
  const corresponding = authors.find(a => a.isCorresponding)
  return corresponding
    ? authors
    : authors.map(
        a =>
          a.isSubmitting
            ? {
                ...a,
                isCorresponding: true,
              }
            : a,
      )
}

const parseEditedAuthors = (editedAuthor, authors) => {
  const newAuthor = castToBool(editedAuthor)
  const newAuthors = authors.map(
    a =>
      a.id === newAuthor.id
        ? newAuthor
        : {
            ...a,
            isCorresponding: newAuthor.isCorresponding
              ? false
              : a.isCorresponding,
          },
  )

  return setCorrespondingAuthor(newAuthors)
}

const WizardAuthors = ({
  error,
  journal,
  moveAuthor,
  authors = [],
  isAuthorEdit,
  deleteAuthor,
  addNewAuthor,
  setAuthorEdit,
  saveNewAuthor,
  isAuthorsFetching,
  editExistingAuthor,
  authorEditorSubmit,
  isFetching,
}) => (
  <Fragment>
    <Row alignItems="center" justify="flex-start">
      <Item>
        <Label>Authors</Label>
        <ActionLink icon="plus" onClick={addNewAuthor}>
          ADD AUTHOR
        </ActionLink>
      </Item>
      <Item justify="flex-end">
        <ActionLink
          icon="link"
          iconPosition="right"
          to={get(
            journal,
            'submission.links.authorGuidelines',
            'https://www.hindawi.com/journals/',
          )}
        >
          Author Submission Guidelines
        </ActionLink>
      </Item>
    </Row>
    {authors.length > 0 && (
      <SortableContainer>
        <SortableList
          authorEditorSubmit={authorEditorSubmit}
          deleteAuthor={deleteAuthor}
          dragHandle={DragHandle}
          editExistingAuthor={editExistingAuthor}
          isAuthorEdit={isAuthorEdit}
          isAuthorsFetching={isAuthorsFetching}
          isFetching={isFetching}
          itemKey="id"
          items={authors}
          listItem={AuthorCard}
          moveItem={moveAuthor}
          onEdit={setAuthorEdit}
          saveNewAuthor={saveNewAuthor}
        />
      </SortableContainer>
    )}
    {error && (
      <Row justify="flex-start" mb={1} mt={1}>
        <Text error>{error}</Text>
      </Row>
    )}
  </Fragment>
)

export default compose(
  withFetching,
  withState('authors', 'setAuthors', ({ authors }) => authors),
  withHandlers({
    setFormAuthors: ({
      changeForm,
      setAuthors,
      setFetching,
      onAuthorEdit,
      formName = 'submission',
    }) => authors => {
      setAuthors(authors)
      setFetching(false)
      onAuthorEdit(null)
      changeForm(formName, 'authors', authors)
    },
  }),
  withHandlers({
    addNewAuthor: ({ authors = [], setAuthors, onAuthorEdit }) => () => {
      if (authors.some(a => a.id === 'newAuthor')) {
        return
      }
      onAuthorEdit(0)
      setAuthors([
        ...authors,
        { id: 'newAuthor', isCorresponding: false, isSubmitting: false },
      ])
    },
    moveAuthor: ({ authors, setFormAuthors }) => (dragIndex, hoverIndex) => {
      setFormAuthors(SortableList.moveItem(authors, dragIndex, hoverIndex))
    },
    setAuthorEdit: ({ authors, setAuthors, onAuthorEdit }) => index => {
      onAuthorEdit(index)
      setAuthors(authors.filter(a => a.id !== 'newAuthor'))
    },
    saveNewAuthor: ({ authors, setFormAuthors }) => author => {
      setFormAuthors(
        parseEditedAuthors(author, [
          ...authors.filter(a => a.id !== 'newAuthor'),
          author,
        ]),
      )
    },
    editExistingAuthor: ({ authors, setFormAuthors }) => editedAuthor => {
      const newAuthors = parseEditedAuthors(editedAuthor, authors)
      setFormAuthors(newAuthors)
    },
    deleteAuthor: ({
      authors,
      project,
      version,
      deleteAuthor,
      setFormAuthors,
    }) => author => ({ hideModal, setModalError }) =>
      deleteAuthor(project.id, version.id, author.id)
        .then(() => {
          const newAuthors = setCorrespondingAuthor(
            authors.filter(a => a.id !== author.id),
          )
          setFormAuthors(newAuthors)
          hideModal()
        })
        .catch(handleError(setModalError)),
  }),
  withHandlers({
    authorEditorSubmit: ({
      authors,
      project,
      version,
      addAuthor,
      setFetching,
      saveNewAuthor,
      editExistingAuthor,
    }) => (values, dispatch, { toggleEditMode }) => {
      if (values.id === 'newAuthor') {
        setFetching(true)
        return addAuthor(
          {
            ...omit(values, 'id'),
            isSubmitting: authors.length === 1,
          },
          project.id,
          version.id,
        ).then(saveNewAuthor)
      }
      editExistingAuthor(values)
      setTimeout(toggleEditMode, 10)
    },
  }),
)(WizardAuthors)

// #region styles
const SortableContainer = styled.div`
  background-color: ${th('colorBackground')};
  border-radius: ${th('borderRadius')};
  padding: ${th('gridUnit')};
  width: 100%;
`
// #endregion