import React from 'react'
import Fuse from 'fuse.js'
import store from 'common/store'
import request from 'common/request'
import {
  array_from_set, property_getter, property_toggler, download_file, empty_set,
} from 'common/utilities'
import {
  add_users_value, remove_users_value, store_fields, store_values, update_user_comments,
  update_field, update_value, remove_field, remove_value, add_entity_value, remove_entity_value,
  update_entity_comment, update_exclusive_entity_value, clear_exclusive_entity_value,
} from 'actions/fields'
import {get_missions_recyclable_fields} from 'selectors/fields'
import {alert_failure, show_popover, dismiss_popover} from 'actions/display'
import NewFieldForm from 'components/popovers/new_field_form'
import DeleteField from 'components/popovers/delete_field'
import DeleteValue from 'components/popovers/delete_value'
import {add_modal} from 'components/architecture/modals'
import AssociatedValuesSettings from 'components/associated_values_settings'

export function action_remove_field(field_id) {
  const field = store.getState().fields.fields[field_id] || {}
  const remove = () => {
    store.dispatch(remove_field(field_id))
    request.delete(`fields/${field_id}`)
  }
  if (field.name) {
    store.dispatch(show_popover(
      DeleteField,
      {
         field,
         on_delete() {
           remove()
           store.dispatch(dismiss_popover())
         },
      },
      `Supprimer le champ ${field.name}`,
    ))
  } else {
    remove()
  }
}

export function action_remove_value(value_id) {
  function remove() {
    store.dispatch(remove_value(value_id))
    return request.delete(`values/${value_id}`)
  }
  const {values, fields} = store.getState().fields
  const {mission_ids, entity_ids, name, field_id} = values[value_id]
  const {name: field_name} = fields[field_id]
  if (empty_set(mission_ids) && empty_set(entity_ids)) {
    return remove()
  } else {
    store.dispatch(show_popover(
      DeleteValue,
      {
        field_name: field_name,
        value_name: name,
        confirm() {
          remove()
          store.dispatch(dismiss_popover())
        },
      },
      `Suppression de la valeur « ${name} »`
    ))
  }
}

function is_exclusive_update(value_id, for_missions) {
  const {fields, values} = store.getState().fields
  const {field_id} = values[value_id] || {}
  const {for_entity, category} = fields[field_id] || {}
  return category == 'exclusive' && !(for_entity == 'User' && for_missions)
}

export function action_select_entity_value(entity_id, value_id, for_missions) {
  let action = add_entity_value
  if (is_exclusive_update(value_id, for_missions)) {
    action = update_exclusive_entity_value
  }
  store.dispatch(action(entity_id, value_id, for_missions))
  return request.put(`values/${value_id}/add`, {entity_id, for_missions})
}

export function action_remove_entity_value(entity_id, value_id, for_missions) {
  if (is_exclusive_update(value_id, for_missions)) {
    store.dispatch(clear_exclusive_entity_value(entity_id, value_id))
  } else {
    store.dispatch(remove_entity_value(entity_id, value_id, for_missions))
  }
  return request.delete(`values/${value_id}/remove`, {entity_id, for_missions})
}

export function action_update_entity_comment(entity_id, field_id, comment) {
  store.dispatch(update_entity_comment(entity_id, field_id, comment))
  return request.put(`fields/${field_id}/comments`, {entity_id, comment})
}

export function action_view_entity_template(entity_id, {name, id: field_id}) {
  return request.asynchronous(`fields/${field_id}/create_from_template`, {entity_id})
  .then(({url}) => download_file(url, name))
}

export function action_upload_entity_file(entity_id, field_id, file) {
  return request.upload(`fields/${field_id}/files`, file, {entity_id})
}

export function action_fetch_entity_computed_value(entity_id, field_id) {
  return request.get(`fields/${field_id}/compute`, {entity_id})
  .then(property_getter('result'))
}

export function action_create_user_field() {
  return action_new_field(
    "Création d'un nouveau champ candidat",
    "user",
    {for_entity: 'User'},
  )
}

export function action_create_mission_field() {
  return action_new_field(
    "Création d'un nouveau champ mission",
    "mission",
    {for_entity: 'Mission'},
    get_missions_recyclable_fields(store.getState())
  )
}

export function action_create_proposal_field() {
  return action_new_field(
    "Création d'un nouveau champ poste",
    "mission_proposal",
    {for_entity: 'MissionProposal'},
  )
}

export function action_create_shift_field() {
  return action_new_field(
    "Création d'un nouveau champ créneau",
    "shift",
    {for_entity: 'Shift'},
  )
}

export function action_create_value_field(field_id) {
  return action_new_field(
    "Création d'une nouvelle valeur associée",
    "value",
    {for_entity: 'Value', field_id}
  )
}

export function action_create_workplace_field() {
  return action_new_field(
    "Création d'un nouveau champ Lieu de travail",
    "workplace",
    {for_entity: 'Workplace'}
  )
}

export function action_create_deal_field() {
  return action_new_field(
    "Création d'un champ d'export mission",
    "deal",
    {for_entity: 'Deal'}
  )
}

export function action_new_field(title, type, template, existing_fields = []) {
  store.dispatch(show_popover(
    NewFieldForm,
    {
      type,
      create_field(field) {
        action_create_field({
          ...field,
          ...template,
        })
        store.dispatch(dismiss_popover())
      },
      recycle_field(field) {
        action_update_field({...field, recycled: true})
        store.dispatch(dismiss_popover())
      },
      existing_fields,
    },
    title
  ))
}

export function action_create_field(field) {
  return request.post(`agencies/${store.getState().profile.agency_id}/fields`, {field})
  .then((field) => {
    store.dispatch(store_fields([field]))
    return field.id
  })
}

export function action_create_value(field_id, name = "") {
  return new Promise((resolve, reject) => {
    let characters = name.split("")
    if (',' in characters || ';' in characters) {
      store.dispatch(alert_failure(`Les caractères ',' et ';' sont interdits dans le nom d'une valeur.`))
      reject()
    } else {
      request.post(`fields/${field_id}/values`, {value: {name}})
      .then((value) => {
        store.dispatch(store_values([value]))
        action_show_associated_values(value.id)
        return value.id
      })
      .then(resolve)
    }
  })
}

export function action_show_associated_values(value_id) {
  add_modal(() => <AssociatedValuesSettings value_id={value_id} />)
}

export const new_values_fuse = () => new Fuse([], {
  keys: ["name"],
  id: "id",
  threshold: 0.2,
})

export const new_comments_fuse = () => new Fuse([], {
  keys: ["comment"],
  id: "id",
  threshold: 0.2,
})

export function allow_creating_value(item_type, field) {
  return !((item_type == 'mission' || item_type == 'new_mission') && field.recycled)
}

export function action_update_field(field) {
  store.dispatch(update_field(field))
  return request.put(`fields/${field.id}`, {field})
}

export function action_update_value(value) {
  store.dispatch(update_value(value))
  return request.put(`values/${value.id}`, {value})
}

export function action_update_field_template(field_id, template) {
  return request.upload(`fields/${field_id}/template`, template, {field_id})
    .then(() => {})
    .catch(() => store.dispatch(alert_failure("Une erreur s'est produite. Avez-vous bien téléchargé un fichier au format .docx ?")))
}

export function action_export_field(field_id, deal_ids) {
  const {name} = store.getState().fields.fields[field_id]
  const {agency_id} = store.getState().profile
  return request.asynchronous(`agencies/${agency_id}/export_missions`, {field_id, deal_ids})
  .then(({url}) => download_file(url, name))
}

export const users_fields_options = [
  {
    name: "Renseigné par le candidat",
    get: property_getter('shared_by_user'),
    toggle: property_toggler('shared_by_user'),
  },
]

export const missions_fields_options = [
  {
    name: "Partagé avec le candidat",
    get: property_getter('shared_with_user'),
    toggle: property_toggler('shared_with_user'),
  },
]
