import React, {Component} from 'react'
import {connect} from 'react-redux'
import classNames from 'classnames/bind'
import {
  MdError, MdWarning, MdCheck, MdCheckBox, MdCheckBoxOutlineBlank, MdFileUpload,
  MdKeyboardArrowLeft, MdKeyboardArrowRight,
} from 'react-icons/lib/md'
import Menu from './menu'
import Button from 'components/utils/button'
import UserTable from './user_table'
import FieldCategoriesSelector from './field_categories_selector'
import {
  array_from_hash, array_from_set, set_from_array, human_plural, human_join, deep_merge, for_all,
  create_hash, hash_key_with_value,  hash_with_key, map_hash, array_contains, group_hash_by_value,
  filter_hash,
} from '../common/utilities'
import request from '../common/request'
import store from '../common/store'
import {color} from '../common/constants'
import {
  action_create_field, action_create_value,
} from '../common/fields'
import {action_invite_users, get_user_status, make_user_status} from '../common/users'
import {alert_info, alert_success} from '../actions/display'
import {update_users} from '../actions/users'
import {
  update_user_comments, add_users_value, remove_users_value,
  update_exclusive_entity_value, clear_exclusive_entity_value,
} from '../actions/fields'
import {combined_actions} from 'actions/base'
import {get_users} from '../selectors/users'

let cx = classNames.bind(require('../styles/upload_results.scss'))

const get_uploaded_users = (upload_users, props_users) => {
  return map_hash(upload_users, (user) => ({
    ...user,
    status: user.existing ? get_user_status(props_users[user.existing]) : make_user_status('new'),
  }))
}

class UploadResultsStatic extends Component {
  constructor(props) {
    super(props)
    this.state = {
      active_field_type: 'summary',
      active_field: null,
      messages: {
        summary: [],
        invitations: [],
        instant_job_field: {},
        agency_field: {},
      },
      invitations: true,
      importing: {
        instant_job_field: {},
        agency_field: {},
      },
      imported: {
        instant_job_field: {},
        agency_field: {},
      },
      statistics: 'old',
    }
    this.render_page = this.render_page.bind(this)
    this.send_invitations = this.send_invitations.bind(this)
    this.import_users = this.import_users.bind(this)
    this.import_field = this.import_field.bind(this)
    this.render_navigation = this.render_navigation.bind(this)
  }

  componentWillUnmount() {
    this.mounted = false
  }

  componentDidMount() {
    this.mounted = true
    let summary = [], invitations = [], instant_job_field = {}, agency_field = {}
    let {
      users,
      fields,
      values,
      instant_job_fields_present,
      new_users_count,
      old_users_count,
      duplicate_users_count,
      invalid_emails,
    } = this.props.upload_results
    if (new_users_count > 0) {
      this.setState({statistics: 'new'})
    }
    let new_field_names = Object.keys(fields)
    .map((id) => fields[id])
    .filter((field) => !field.existing)
    .map((field) => field.name)
    let total_fields_count = Object.keys(fields).length + array_from_set(instant_job_fields_present).length
    summary.new_fields = {
      new_field_names,
      total_fields_count,
      component: MessageFieldsCount,
    }
    if (duplicate_users_count > 0) {
      summary.duplicate_users = {
        duplicate_users_count,
        component: MessageDuplicateUsers,
      }
    }
    if (invalid_emails.length > 0) {
      summary.duplicate_users = {
        invalid_emails,
        component: MessageInvalidEmails,
      }
    }
    if (new_users_count == 0 && old_users_count == 0) {
      summary.empty_file = {
        component: MessageEmptyFile,
      }
    }
    if (new_users_count > 0) {
      invitations.new_users = {
        validated: false,
        all_users: Object.keys(users).length,
        new_users: new_users_count,
        component: MessageInviteUsers,
        onClick: () => this.setState(deep_merge(this.state, {
          messages: {invitations: {new_users: {validated: !this.state.messages.invitations.new_users.validated}}}
        })),
      }
    }
    let absent_fields = array_from_hash(filter_hash(
      group_hash_by_value(this.props.instant_job_fields),
      (labels) => for_all(labels, (label) => !instant_job_fields_present[label])
    )).map((labels) => labels[0])
    if (absent_fields.length > 0) {
      invitations.absent_fields = {
        validated: false,
        absent_fields,
        component: MessageAbsentFields,
        onClick: () => this.setState(deep_merge(this.state, {
          messages: {invitations: {absent_fields: {validated: !this.state.messages.invitations.absent_fields.validated}}}
        })),
      }
    }
    array_from_set(instant_job_fields_present).forEach((field_label) => {
      let field_name = this.props.instant_job_fields[field_label]
      if (new_users_count > 0) {
        instant_job_field[field_name] = deep_merge(instant_job_field[field_name], {new: {valid: {
          component: MessageInstantJobFieldNew,
          informational: true,
        }}})
      }
      if (old_users_count > 0) {
        let conflicting_users = array_from_hash(users).filter((user) => {
          if (user.existing) {
            return (user[field_name] || "") != (this.props.users[user.existing][field_name] || "")
          } else {
            return false
          }
        })
        let conflicting_users_with_app_count = conflicting_users.filter((user) => this.props.users[user.existing].app_name).length
        let conflicting_users_without_app_count = conflicting_users.length - conflicting_users_with_app_count
        if (conflicting_users.length > 0) {
          if (conflicting_users_without_app_count > 0) {
            instant_job_field[field_name] = deep_merge(instant_job_field[field_name], {old: {conflict: {
              component: MessageFieldConflict,
              conflicting_users_count: conflicting_users_without_app_count,
              selected: null,
              exists_new_user: false,
              on_select: (selected) => this.setState(deep_merge(this.state, {
                messages: {instant_job_field: {[field_name]: {old: {conflict: {selected}}}}}
              })),
            }}})
          }
          if (conflicting_users_with_app_count > 0) {
            instant_job_field[field_name] = deep_merge(instant_job_field[field_name], {old: {conflict_with_app: {
              component: MessageInstantJobAppUserConflict,
              conflicting_users_count: conflicting_users_with_app_count,
              informational: true,
            }}})
          }
        } else {
          instant_job_field[field_name] = deep_merge(instant_job_field[field_name], {old: {identical: {
            component: MessageFieldIdentical,
            informational: true,
          }}})
        }
      }
    })
    array_from_hash(fields).forEach((field) => {
      if (field.existing) {
        let conflicting_users_count, new_values_old_users
        const field_values = array_from_set(field.values).map((id) => values[id])
        switch (field.category) {
          case 'non_exclusive':
            if (new_users_count > 0) {
              let new_values_new_users = field_values.filter((value) => !value.existing && value.created_by_new_users).map((value) => value.name)
              if (new_values_new_users.length > 0) {
                agency_field[field.id] = deep_merge(agency_field[field.id], {new: {new_values_new_users: {
                  component: MessageNewValuesNewUsers,
                  new_field_values: new_values_new_users,
                  new_users_count,
                  validated: false,
                  onClick: () => this.setState(deep_merge(this.state, {
                    messages: {agency_field: {[field.id]: {new: {new_values_new_users: {validated: !this.state.messages.agency_field[field.id].new.new_values_new_users.validated}}}}}
                  })),
                }}})
              } else {
                agency_field[field.id] = deep_merge(agency_field[field.id], {new: {ready: {
                  component: MessageAgencyFieldReady,
                  validated: true,
                }}})
              }
            }
            conflicting_users_count = array_from_hash(users).filter((user) => (
              user.existing && !for_all(
                field_values,
                (value) => !((!value.existing && value.entity_ids[user.id]) || value.mismatching_users[user.id])
              )
            )).length
            new_values_old_users = field_values.filter((value) => value.created_by_old_users).map((value) => value.name)
            break
          case 'exclusive':
            if (new_users_count > 0) {
              let new_values_new_users = field_values.filter((value) => !value.existing && value.created_by_new_users).map((value) => value.name)
              if (new_values_new_users.length > 0) {
                agency_field[field.id] = deep_merge(agency_field[field.id], {new: {new_values_new_users: {
                  component: MessageNewValuesNewUsers,
                  new_field_values: new_values_new_users,
                  new_users_count,
                  validated: false,
                  onClick: () => this.setState(deep_merge(this.state, {
                    messages: {agency_field: {[field.id]: {new: {new_values_new_users: {validated: !this.state.messages.agency_field[field.id].new.new_values_new_users.validated}}}}}
                  })),
                }}})
              } else {
                agency_field[field.id] = deep_merge(agency_field[field.id], {new: {ready: {
                  component: MessageAgencyFieldReady,
                  validated: true,
                }}})
              }
            }
            conflicting_users_count = array_from_hash(users)
            .filter((user) => user.existing && field.mismatching_user_ids[user.id])
            .length
            new_values_old_users = field_values
            .filter((value) => value.created_by_old_users)
            .map((value) => value.name)
            break
          case "comment":
            if (new_users_count > 0) {
              agency_field[field.id] = deep_merge(agency_field[field.id], {new: {ready: {
                component: MessageAgencyFieldReady,
                validated: true,
              }}})
            }
            conflicting_users_count = array_from_hash(users).filter((user) => field.conflicting_comments[user.id]).length
            new_values_old_users = []
            break
          default:
        }
        if (old_users_count > 0) {
          if (conflicting_users_count > 0) {
            agency_field[field.id] = deep_merge(agency_field[field.id], {old: {conflict: {
              component: MessageFieldConflict,
              conflicting_users_count,
              new_field_values: new_values_old_users,
              selected: null,
              exists_new_user: new_users_count > 0,
              on_select: (selected) => this.setState(deep_merge(this.state, {
                messages: {agency_field: {[field.id]: {old: {conflict: {selected}}}}}
              })),
            }}})
          } else {
            agency_field[field.id] = deep_merge(agency_field[field.id], {old: {identical: {
              component: MessageFieldIdentical,
              informational: true,
            }}})
          }
        }
      } else {
        agency_field[field.id] = deep_merge(agency_field[field.id], {common: {new_field: {
          component: MessageNewField,
          selected: null,
          on_select: (category) => {
            this.props.upload_results.fields = {
              ...this.props.upload_results.fields,
              [field.id]: {
                ...field,
                category
              }
            }
            this.setState(deep_merge(this.state, {
              messages: {agency_field: {[field.id]: {common: {new_field: {selected: category}}}}}
            }))
          },
        }}})
      }
    })
    this.setState({messages: {summary, invitations, instant_job_field, agency_field}})
  }

  send_invitations() {
    this.setState(deep_merge(this.state, {importing: {invitations: true}}))
    let users = array_from_hash(this.props.upload_results.users).filter((user) => !user.existing)
    action_invite_users(users)
    .then(() => this.setState(deep_merge(this.state, {imported: {invitations: true}})))
  }

  import_users(field_name) {
    let users = array_from_hash(this.props.upload_results.users)
    .filter((user) => user.existing && !this.props.users[user.existing].app_name)
    .filter((user) => this.props.users[user.existing][field_name] != user[field_name])
    .map((user) => ({...this.props.users[user.existing], [field_name]: user[field_name]}))
    store.dispatch(update_users(users.filter((user) => user.user_id).map((user) => ({...user, id: user.user_id}))))
    return request.asynchronous(`users/agency_update`, {users: users.map(({first_name, last_name, email, postal_code, phone_number}) => ({first_name, last_name, email, postal_code, phone_number}))})
    .then((users) => store.dispatch(update_users(users)))
  }

  import_field(imported_field_id, old_users_import_mode) {
    let {
      users,
      fields,
      values,
    } = this.props.upload_results
    let field = fields[imported_field_id]
    let users_to_import = array_from_hash(users)
    if (old_users_import_mode == 'ignore') {
      users_to_import = users_to_import.filter((user) => !user.existing)
    }
    let existing_users = hash_with_key(array_from_hash(this.props.users), 'email')
    users = map_hash(users, (user) => ({...user, existing: existing_users[user.email]}))
    let should_import_user = set_from_array(users_to_import.map((user) => users[user.id].existing.id))
    let imported_users = hash_with_key(array_from_hash(users), 'email')
    return (new Promise((resolve, reject) => {
      if (field.existing) {
        resolve(field.existing)
      } else {
        action_create_field(field)
        .then((id) => resolve(id))
      }
    })).then((field_id) => {
      const actions = []
      switch (field.category) {
        case "non_exclusive":
          return Promise.all(array_from_set(field.values).map((id) => {
            let imported_value = values[id]
            return new Promise((resolve, reject) => {
              if (imported_value.existing) {
                resolve(imported_value)
              } else {
                action_create_value(field_id, imported_value.name)
                .then((id) => resolve({...imported_value, existing: id}))
              }
            })
          }))
          .then((imported_values) => request.asynchronous("users/update_values", {values: imported_values.map((imported_value) => {
            let value = this.props.values[imported_value.existing]
            let result = {
              id: value.id,
              added: array_from_set(imported_value.entity_ids)
              .map((id) => users[id].existing.id)
              .filter((user_id) => !value.entity_ids[user_id] && should_import_user[user_id]),
              removed: array_from_set(value.entity_ids).filter((user_id) => {
                let imported_user = imported_users[this.props.users[user_id].email]
                return imported_user && !imported_value.entity_ids[imported_user.id] && should_import_user[user_id]
              })
            }
            actions.push(add_users_value(result.added, result.id))
            actions.push(remove_users_value(result.removed, result.id))
            return result
          })}))
          .then((result) => {
            store.dispatch(combined_actions(actions))
            return result
          })
        case "exclusive":
          return Promise.all(array_from_set(field.values).map((id) => {
            let imported_value = values[id]
            return new Promise((resolve, reject) => {
              if (imported_value.existing) {
                resolve(imported_value)
              } else {
                action_create_value(field_id, imported_value.name)
                .then((id) => resolve({...imported_value, existing: id}))
              }
            })
          }))
          .then((imported_values) => request.asynchronous("users/update_values", {values: imported_values.map((imported_value) => {
            const value = this.props.values[imported_value.existing]
            const {value_id_for} = this.props.fields[value.field_id] || {}
            const result = {
              id: value.id,
              added: Object.keys(field.value_id_for)
              .filter(
                (user_id) => field.value_id_for[user_id] == imported_value.id &&
                value_id_for[users[user_id].existing.id] != field.value_id_for[user_id]
              )
              .map((id) => users[id].existing.id)
              .filter((user_id) => should_import_user[user_id]),
              removed: Object.keys(value_id_for)
              .filter((user_id) => {
                if (value_id_for[user_id] != value.id) {
                  return false
                }
                const imported_user = imported_users[this.props.users[user_id].email]
                return imported_user && !field.value_id_for[imported_user.id] && should_import_user[user_id]
              })
            }
            result.added.forEach((user_id) => {
              actions.push(update_exclusive_entity_value(user_id, value.id))
            })
            result.removed.forEach((user_id) => {
              actions.push(clear_exclusive_entity_value(user_id, value.id))
            })
            return result
          })}))
          .then((result) => {
            store.dispatch(combined_actions(actions))
            return result
          })
        case "comment":
          let query = array_from_hash(users).filter((user) => (
            should_import_user[user.existing.id] && (
              field.conflicting_comments[user.id] || (
                !field.existing &&
                field.comments[user.id] != ""
              )
            )
          )).map((user) => ({id: user.existing.id, comment: field.comments[user.id]}))
          store.dispatch(update_user_comments(field_id, map_hash(hash_with_key(query), (user) => user.comment)))
          return request.asynchronous("users/update_comments", {users: query, field: {id: field_id}})
        default:
      }
    })
  }

  render_page() {
    let exists_new_user = this.props.upload_results.new_users_count > 0
    let exists_old_user = this.props.upload_results.old_users_count > 0
    switch (this.state.active_field_type) {
      case 'summary':
      case 'invitations':
        let messages = array_from_hash(this.state.messages[this.state.active_field_type])
        let message_wrappers = (messages || []).map(({component: MessageWrapper, ...props}, index) => (
          <MessageWrapper key={index} {...props} imported={this.state.imported.invitations} />
        ))
        if (this.state.active_field_type == 'summary') {
          return (
            <div className={cx('upload-results__content-container')}>
              <div className={cx('upload-results__content-title')}>
                Aperçu
              </div>
              {message_wrappers}
              {exists_old_user || exists_new_user ? (
                <UserTable {...this.props.upload_results} editable={false} place_filterable={false} users={get_uploaded_users(this.props.upload_results.users, this.props.users)}/>
              ) : null}
            </div>
          )
        } else {
          return (
            <div className={cx('upload-results__content-container')}>
              <div className={cx('upload-results__content-title')}>
                Invitations
              </div>
              <div className={cx('upload-results__messages')}>
                {message_wrappers}
              </div>
              <div className={cx('upload-results__upload-button')}>
                {this.state.imported.invitations ? (
                  <Button done>
                    {human_plural(this.props.upload_results.new_users_count, `L'invitation a été envoyée`, `Les invitations ont été envoyées`)}
                  </Button>
                ) : (this.state.importing.invitations ? (
                  <Button loading>
                    Importation en cours ...
                  </Button>
                ) : (
                  <Button
                    disabled={!for_all(messages, (message) => message.informational || message.validated || message.selected)}
                    onClick={this.send_invitations}
                  >
                    {human_plural(this.props.upload_results.new_users_count, `Envoyer l'invitation`, `Envoyer les invitations`)}
                  </Button>
                ))}
              </div>
            </div>
          )
        }
      case 'instant_job_field':
      case 'agency_field':
        let imported = this.state.imported[this.state.active_field_type][this.state.active_field]
        let new_field = this.state.active_field_type == 'agency_field' && !this.props.upload_results.fields[this.state.active_field].existing
        let common_messages = array_from_hash((this.state.messages[this.state.active_field_type][this.state.active_field] || {}).common)
        let common_message_wrappers = common_messages.map(({component: MessageWrapper, ...props}, index) => (
          <MessageWrapper key={index} {...props} imported={imported} />
        ))
        let new_users_messages = array_from_hash((this.state.messages[this.state.active_field_type][this.state.active_field] || {}).new)
        let new_users_message_wrappers = new_users_messages.map(({component: MessageWrapper, ...props}, index) => (
          <MessageWrapper key={index} {...props} imported={imported} />
        ))
        let old_users_messages = array_from_hash((this.state.messages[this.state.active_field_type][this.state.active_field] || {}).old)
        let old_users_message_wrappers = old_users_messages.map(({component: MessageWrapper, ...props}, index) => (
          <MessageWrapper key={index} {...props} imported={imported} />
        ))
        let statistics
        let switcher = exists_new_user && exists_old_user ? (
          <div className={cx('upload-results__statistics-switcher')}>
            {["new", "old"].map((option) => (
              <div
                key={option}
                className={cx('upload-results__statistics-switcher-option', {'upload-results__statistics-switcher-option_selected': this.state.statistics == option})}
                onClick={() => this.setState({statistics: option})}
                >
                {{"new": "Nouveaux candidats", "old": "Anciens candidats"}[option]}
              </div>
            ))}
          </div>
        ) : null
        const filter_user = (user) => this.state.statistics == (user.existing ? "old" : "new")
        let field
        if (this.state.active_field_type == 'instant_job_field') {
          field = {name: hash_key_with_value(this.props.instant_job_fields, this.state.active_field)}
          let all_users = array_from_hash(this.props.upload_results.users).filter(filter_user)
          let filled_users_count = all_users.filter((user) => user[this.state.active_field]).length
          statistics = (
            <div className={cx('upload-results__statistics')}>
              {switcher}
              <div className={cx('upload-results__content-title')}>
                Statistiques
              </div>
              <Statistics>
                {{
                  "Renseigné": filled_users_count,
                  "Vide": all_users.length - filled_users_count,
                }}
              </Statistics>
            </div>
          )
        } else {
          field = this.props.upload_results.fields[this.state.active_field]
          switch (field.category) {
            case 'exclusive':
            case 'non_exclusive':
              let field_values = array_from_set(field.values).map((id) => this.props.upload_results.values[id])
              let user_values_statistics = {}
              field_values.forEach((value) => {
                array_from_set(value.entity_ids).forEach((user_id) => {
                  if (filter_user(this.props.upload_results.users[user_id])) {
                    user_values_statistics[user_id] = (user_values_statistics[user_id] || 0) + 1
                  }
                })
              })
              statistics = (
                <div className={cx('upload-results__statistics')}>
                  {switcher}
                  <div className={cx('upload-results__content-title')}>
                    Statistiques
                  </div>
                  <Statistics>
                    {field_values.reduce((statistics, value) => {
                      statistics[value.name] = array_from_set(value.entity_ids).map((id) => this.props.upload_results.users[id]).filter(filter_user).length
                      return statistics
                    }, {})}
                  </Statistics>
                  {field.category == 'non_exclusive' ? (
                    <div>
                      <div className={cx('upload-results__content-title')}>
                        Nombre de valeurs
                      </div>
                      <Statistics>
                        {array_from_hash(user_values_statistics).reduce((statistics, value_count) => {
                          statistics[value_count] = (statistics[value_count] || 0) + 1
                          return statistics
                        }, {})}
                      </Statistics>
                    </div>
                  ) : null}
                </div>

              )
              break
            case 'comment':
              let all_users = array_from_hash(this.props.upload_results.users).filter(filter_user)
              let {comments} = this.props.upload_results.fields[this.state.active_field]
              let filled_users_count = all_users.filter(({id}) => comments[id]).length
              statistics = (
                <div className={cx('upload-results__statistics')}>
                  {switcher}
                  <div className={cx('upload-results__content-title')}>
                    Statistiques
                  </div>
                  <Statistics>
                    {{
                      "Renseigné": filled_users_count,
                      "Vide": all_users.length - filled_users_count,
                    }}
                  </Statistics>
                </div>
              )
              break
            default:
          }
        }
        return (
          <div className={cx('upload-results__content-container')}>
            <div className={cx('upload-results__content-title')}>
              {field.name}
            </div>
            <div className={cx('upload-results__main-content')}>
              <div className={cx('upload-results__messages')}>
                {common_message_wrappers}
                {exists_new_user && new_users_messages.length > 0 ? (
                  <div className={cx('upload-results__content-title')}>
                    Candidats nouvellement importés
                  </div>
                ) : null}
                {exists_new_user ? (
                  new_users_message_wrappers
                ) : null}
                {exists_old_user && old_users_messages.length > 0? (
                  <div className={cx('upload-results__content-title')}>
                    Candidats déjà présents dans la base
                  </div>
                ) : null}
                {exists_old_user ? (
                  old_users_message_wrappers
                ) : null}
              </div>
              {statistics}
            </div>
            <div className={cx('upload-results__upload-button')}>
              {for_all([...new_users_messages, ...old_users_messages, ...common_messages], (message) => message.informational) ? (
                <Button done>
                  {"Vous n'avez rien à faire"}
                </Button>
              ) : (imported ? (
                <Button done>
                  {new_field ? "Le champ a été créé et les données importées" : "Les données de ce champ ont été importées"}
                </Button>
              ) : (this.state.importing[this.state.active_field_type][this.state.active_field] ? (
                <Button loading>
                  Importation en cours ...
                </Button>
              ) : (
                <Button
                  disabled={!for_all([...new_users_messages, ...old_users_messages, ...common_messages], (message) => message.informational || message.validated || message.selected)}
                  onClick={() => {
                    let active_field = this.state.active_field, active_field_type = this.state.active_field_type
                    this.setState(deep_merge(this.state, {importing: {[active_field_type]: {[active_field]: true}}}))
                    this.forceUpdate()
                    let set_imported_state = () => {
                      if (this.mounted) {
                        this.setState(deep_merge(this.state, {imported: {[active_field_type]: {[active_field]: true}}}))
                      }
                    }
                    let messages = this.state.messages[active_field_type][active_field]
                    switch (active_field_type) {
                      case "instant_job_field":
                        this.import_users(active_field)
                        .then(set_imported_state)
                        break
                      case "agency_field":
                        this.import_field(active_field, new_field ? 'overwrite' : (exists_old_user && messages.old.conflict ? messages.old.conflict.selected : 'ignore'))
                        .then(set_imported_state)
                        break
                      default:
                    }
                  }}
                  >
                  {
                    (new_field) ?
                    "Créer le champ" :
                    ((!exists_old_user ||
                    (exists_old_user && exists_new_user && for_all(old_users_messages, (message) => message.selected != "overwrite"))) ?
                    "Importer les données pour les nouveaux candidats" :
                    "Importer les données de ce champ")
                  }
                </Button>
              )))}
            </div>
          </div>
        )
      default:
        return <div></div>
    }
  }

  render_navigation(field_array) {
    let current_index = field_array.findIndex((field) => field.active)

    let decrement = () => {
      field_array[current_index - 1].onClick()
    }

    let increment = () => {
      field_array[current_index + 1].onClick()
    }

    return (
      <div className={cx('upload-results__actions')}>
        <div className={cx('upload-results__actions__button-container', 'upload-results__actions__button-container__reverse')}>
          {current_index > 0 ? (
            <Button secondary left_icon={<MdKeyboardArrowLeft />} onClick={decrement} disabled={current_index == 0}>
              Précédent
            </Button>
          ) : null}
        </div>
        <div className={cx('upload-results__actions__button-container')}>
        {current_index + 1 < field_array.length ? (
          <Button secondary right_icon={<MdKeyboardArrowRight />} disabled={field_array[current_index + 1] && field_array[current_index + 1].disabled} onClick={increment}>
            Suivant
          </Button>
        ) : (
          <Button secondary right_icon={<MdCheck />} disabled={field_array[current_index + 1] && field_array[current_index + 1].disabled} onClick={this.props.close}>
            Terminer
          </Button>
        )}
        </div>
      </div>
    )
  }

  render() {
    let status = {
      invitations: for_all(array_from_hash(this.state.messages.invitations), (message) => message.informational || message.validated || message.selected) ? 'ready' : 'warning',
      instant_job_field: create_hash(array_from_hash(this.props.instant_job_fields), (field_name) => {
        let all_messages = this.state.messages.instant_job_field[field_name] || {}
        let messages = [
          ...array_from_hash(all_messages.common),
          ...array_from_hash(all_messages.new),
          ...array_from_hash(all_messages.old),
        ]
        if (for_all(messages, (message) => message.informational)) {
          return 'imported'
        } else if (for_all(messages, (message) => message.informational || message.validated || message.selected)) {
          return 'ready'
        } else {
          return 'warning'
        }
      }),
      agency_field: create_hash(Object.keys(this.props.upload_results.fields), (field_id) => {
        let all_messages = this.state.messages.agency_field[field_id] || {}
        let messages = [
          ...array_from_hash(all_messages.common),
          ...array_from_hash(all_messages.new),
          ...array_from_hash(all_messages.old),
        ]
        if (for_all(messages, (message) => message.informational)) {
          return 'imported'
        } else if (for_all(messages, (message) => message.informational || message.validated || message.selected)) {
          return 'ready'
        } else {
          return 'warning'
        }
      })
    }
    let exists_user = this.props.upload_results.new_users_count > 0 || this.props.upload_results.old_users_count > 0
    let field_array = [
      {
        label: "Aperçu",
        onClick: () => this.setState({active_field_type: 'summary'}),
        active: this.state.active_field_type == 'summary',
        disabled: false,
        icon: <MenuIcon />,
        display: true,
      },
      {
        label: "Invitations",
        onClick: () => this.setState({active_field_type: 'invitations'}),
        active: this.state.active_field_type == 'invitations',
        disabled: false,
        icon: <MenuIcon status={this.state.imported['invitations'] ? 'imported' : status['invitations']} />,
        display: this.props.upload_results.new_users_count > 0,
      },
      ...array_from_set(this.props.upload_results.instant_job_fields_present)
        .map((field_label) => {
          let field_name = this.props.instant_job_fields[field_label]
          return {
            label: field_label,
            onClick: () => this.setState({active_field_type: 'instant_job_field', active_field: field_name}),
            active: this.state.active_field_type == 'instant_job_field' && this.state.active_field == field_name,
            disabled: this.props.upload_results.new_users_count > 0 && !this.state.imported['invitations'],
            icon: <MenuIcon status={this.state.imported['instant_job_field'][field_name] ? 'imported' : status['instant_job_field'][field_name]} />,
            display: exists_user,
          }
        }),
      ...array_from_hash(this.props.upload_results.fields).map((field) => (
      {
        label: field.name,
        onClick: () => this.setState({active_field_type: 'agency_field', active_field: field.id}),
        active: this.state.active_field_type == 'agency_field' && this.state.active_field == field.id,
        disabled: this.props.upload_results.new_users_count > 0 && !this.state.imported['invitations'],
        icon: <MenuIcon status={this.state.imported['agency_field'][field.id] ? 'imported' : status['agency_field'][field.id]} />,
        display: exists_user,
      }
      )),
    ].filter((tab) => tab.display)
    return (
      <div className={cx('upload-results')}>
        <div className={cx('upload-results__import-button')}>
          <Button icon={MdFileUpload} secondary onClick={this.props.upload_new_file}>
            Charger un autre fichier
          </Button>
        </div>
        <div className={cx('upload-results__container')}>
          <div className={cx('upload-results__menu-container')}>
            <Menu>
              {field_array}
            </Menu>
          </div>
          {this.render_page()}
        </div>
        {this.render_navigation(field_array)}
      </div>
    )
  }
}

const Message = (props) => {
  let Icon = {
    'error': MdError,
    'warning': MdWarning,
    'ok': MdCheck,
  }[props.status || 'ok']
  return (
    <div className={cx('upload-results__message', `upload-results__message_${props.status || 'ok'}`)}>
      <div className={cx('upload-results__message-title')}>
        <div className={cx('upload-results__message-title-icon')}>
          <Icon />
        </div>
        <div className={cx('upload-results__message-title-label')}>
          {props.title}
        </div>
      </div>
      {props.children ? (
        <div className={cx('upload-results__message-information')}>
          {props.children}
        </div>
      ) : null}
    </div>
  )
}

const MessageFieldsCount = (props) => {
  let new_field_names_count = props.new_field_names.length
  if (new_field_names_count > 0) {
    return (
      <Message
        status={props.new_field_names.length > 0 ? 'warning' : 'ok'}
        title={human_plural(props.total_fields_count, 'Votre fichier contient %% champ (colonne)', 'Votre fichier contient %% champs (colonnes)')}
      >
        <p>{human_plural(props.total_fields_count - props.new_field_names.length, '%% est déjà présent', '%% sont déjà présents')} sur InstantJob</p>
        <p>{human_plural(props.new_field_names.length, '%% correspond à un nouveau champ', '%% correspondent à des nouveaux champs')} : {human_join(props.new_field_names)}</p>
      </Message>
    )
  } else {
    return (
      <Message
        status={props.new_field_names.length > 0 ? 'warning' : 'ok'}
        title={human_plural(props.total_fields_count, '%% champ a été importé et était déjà présent sur InstantJob', '%% champs ont été importés et étaient déjà présents sur InstantJob')}
        />
    )
  }
}

const MessageInviteUsers = (props) => {
  let title
  if (props.new_users == props.all_users) {
    title = `Votre fichier contient des données au sujet de ${human_plural(props.all_users, '%% nouveau candidat', '%% nouveaux candidats')}.`
  } else {
    title = `Votre fichier contient des données au sujet de ${human_plural(props.all_users, '%% candidat', '%% candidats')}.`
  }
  return (
    <Message
      status={props.validated ? 'ok' : 'warning'}
      title={title}
      >
      {props.new_users == props.all_users ? null : (
        <p>{human_plural(props.all_users - props.new_users, '%% était déjà présent', '%% étaient déjà présents')} sur InstantJob</p>
      )}
      {props.new_users == props.all_users ? null : (
        <p>{human_plural(props.new_users, '%% est un nouveau candidat', '%% sont des nouveaux candidats')}</p>
      )}
      <Action imported={props.imported} status={props.validated ? 'checked' : 'unchecked'} onClick={props.onClick}>
        {`Créer ${human_plural(props.new_users, '%% nouveau candidat sur InstantJob et lui', '%% nouveaux candidats sur InstantJob et leur')} envoyer une invitation à télécharger l'application.`}
      </Action>
    </Message>
  )
}

const MessageAbsentFields = (props) => (
  <Message
    status={props.validated ? 'ok' : 'warning'}
    title={`${human_plural(props.absent_fields.length, `Le champ "${props.absent_fields[0]}" n'a pas été trouvé`, `Les champs ${human_join(props.absent_fields.map((field) => `"${field}"`))} n'ont pas été trouvés`)} dans votre fichier.`}
    >
    <Action imported={props.imported} status={props.validated ? 'checked' : 'unchecked'} onClick={props.onClick}>
      {`Laisser ${human_plural(props.absent_fields.length, 'ce champ vide', 'ces champs vides')} pour les nouveaux candidats importés.`}
    </Action>
  </Message>
)

const MessageInstantJobFieldNew = (props) => (
  <Message title={`Les données ont déjà été importées car il s'agit d'un champ imposé par InstantJob.`} />
)

const MessageAgencyFieldReady = (props) => (
  <Message title={`Données prêtes à être importées.`} />
)

const MessageFieldIdentical = (props) => (
  <Message title={`Les données du fichier sont identiques aux données dans InstantJob.`} />
)

const MessageFieldConflict = (props) => {
  let new_field_values_count = (props.new_field_values || []).length
  return (
    <Message
      status={props.selected ? 'ok' : 'warning'}
      title={`Pour ${human_plural(props.conflicting_users_count, '%% candidat', '%% candidats')}, les données de votre fichier ne correspondent pas aux données présentes dans votre base InstantJob.`}
      >
      {new_field_values_count ? (
        <p>Nous avons également trouvé {human_plural(new_field_values_count, "%% nouvelle valeur", "%% nouvelles valeurs")} chez les candidats déjà présents : {human_join(props.new_field_values, 10)}</p>
      ) : null}
      {props.exists_new_user ? (
        <Action imported={props.imported} status={props.selected == 'ignore' ? 'checked' : (props.selected ? 'discarded' : 'unchecked')} onClick={() => props.on_select('ignore')}>
          Ne pas prendre en compte les données importées et laisser la base InstantJob inchangée
        </Action>
      ) : null}
      <Action
        imported={props.imported}
        status={props.selected == 'overwrite' ? 'checked' : (props.selected && props.exists_new_user ? 'discarded' : 'unchecked')}
        onClick={props.exists_new_user || !props.selected ? () => props.on_select('overwrite') : () => props.on_select(false)}
        >
        Ecraser les données sur InstantJob et les remplacer par les données de votre fichier {new_field_values_count > 0 ? `en créant ${human_plural(new_field_values_count, "%% nouvelle valeur", "%% nouvelles valeurs")}` : null}
      </Action>
    </Message>
  )
}

const MessageInstantJobAppUserConflict = (props) => (
  <Message
    status={'warning'}
    title={`Les données de ${human_plural(props.conflicting_users_count, "%% candidat ne pourront pas être modifiées car il indique", "%% candidats ne pourront pas être modifiées car ils indiquent")} ces informations via l'application.`}
    />
)

const MessageNewField = (props) => (
  <Message status={props.selected ? 'ok' : 'warning'} title={"Ce champ n'existe pas dans la base InstantJob"}>
    <p>Ce champ correspond-il a un champ de tri (à choix multiple) ou à un champ de commentaire ?</p>
    <FieldCategoriesSelector
      selected={props.selected}
      on_select={props.imported ? () => {} : props.on_select}
      />
  </Message>
)

const MessageDuplicateUsers = (props) => (
  <Message
    status={'warning'}
    title={`Votre fichier contient ${human_plural(props.duplicate_users_count, "%% addresse mail", "%% adresses mail")} en double`}
    >
    <p>Nous avons conservé uniquement la dernière ligne correspondant à chaque adresse mail dupliquée</p>
  </Message>
)

const MessageInvalidEmails = (props) => (
  <Message
    status={'warning'}
    title={`Votre fichier contient ${human_plural(props.invalid_emails.length, "%% addresse mail invalide", "%% adresses mail invalides")} : ${human_join(props.invalid_emails, 10)}`}
    >
    <p>Il faut une adresse mail valide pour envoyer une invitation, {human_plural(props.invalid_emails.length, "ce candidat ne pourra donc pas être importé", "ces candidats ne pourront donc pas être importés")}.</p>
  </Message>
)

const MessageEmptyFile = (props) => (
  <Message
    status={'error'}
    title={`Votre fichier ne contient aucune adresse mail valide`}
    />
)

const MessageNewValuesNewUsers = (props) => (
  <Message
    status={props.validated ? 'ok' : 'warning'}
    title={`Nous avons trouvé ${human_plural(props.new_field_values.length, "%% nouvelle valeur", "%% nouvelles valeurs")} chez ${human_plural(props.new_users_count, "le nouveau candidat", "les %% nouveaux candidats")} : ${human_join(props.new_field_values, 10)}`}
    >
    <Action imported={props.imported} status={props.validated ? 'checked' : 'unchecked'} onClick={props.onClick}>
      Créer {human_plural(props.new_field_values.length, "%% nouvelle valeur", "%% nouvelles valeurs")}
    </Action>
  </Message>
)

const Action = (props) => {
  let Icon = props.status == 'checked' ? MdCheckBox : MdCheckBoxOutlineBlank
  return (
    <div className={cx('upload-results__message-action', {[`upload-results__message-action_${props.status}`]: props.status, 'upload-results__message-action_editable': !props.imported})} onClick={props.imported ? () => {} : props.onClick}>
      <div className={cx('upload-results__message-action-checkbox')}>
        <Icon />
      </div>
      <div className={cx('upload-results__message-action-label')}>
        {props.children}
      </div>
    </div>
  )
}

const MenuIcon = (props) => {
  switch (props.status) {
    case 'imported':
      return (
        <div className={cx('upload-results__menu-icon', 'upload-results__menu-icon_imported')}>
          <MdCheck />
        </div>
      )
    case 'ready':
      return (
        <div className={cx('upload-results__menu-icon', 'upload-results__menu-icon_ready')}></div>
      )
    case 'warning':
      return (
        <div className={cx('upload-results__menu-icon', 'upload-results__menu-icon_warning')}></div>
      )
    case 'error':
      return (
        <div className={cx('upload-results__menu-icon', 'upload-results__menu-icon_error')}></div>
      )
    default:
      return <div></div>
  }
}

const Statistics = (props) => (
  <div style={{display: 'flex', flexDirection: 'column', alignItems: 'stretch'}}>
    {Object.keys(props.children).map((label, index) => (
      <div key={index} style={{display: 'flex', justifyContent: 'space-between'}}>
        <div>
          {label}
        </div>
        <div>
          {props.children[label]}
        </div>
      </div>
    ))}
  </div>
)

const UploadResults = connect(
  (state) => ({
    fields: state.fields.fields,
    values: state.fields.values,
    users: get_users(state),
  }),
)(UploadResultsStatic)

UploadResults.defaultProps = {
  upload_results: {
    fields: [],
    values: {},
    users: [],
  },
  fields: {},
  values: {},
  users: {},
  update_upload_results: () => {},
  upload_new_file: () => {},
  close: () => {},
}

export default UploadResults
