import React from 'react'
import moment from 'common/moment'
import {browserHistory} from 'react-router'
import {MdEdit, MdDone, MdDoneAll, MdSend, MdClose} from 'react-icons/lib/md'
import request from './request'
import store from './store'
import {
  set_from_array, set_intersection, human_plural, set_count, download_file, array_from_set, empty_set,
  make_memoized,
} from 'common/utilities'
import {color} from 'common/styles'
import {cancelable_timeout} from 'common/cancelable'
import {
  store_deals, store_missions, update_mission, update_deal, store_available_users,
  remove_mission, remove_deal, send_mission, assign_mission, unassign_mission, replace_mission_events,
  remove_deals,
} from '../actions/missions'
import {dismiss_popover, show_popover, alert_success} from 'actions/display'
import CancelMission from 'components/popovers/cancel_mission'
import SendMission from 'components/popovers/send_mission'
import AssignMission from 'components/popovers/assign_mission'
import UnassignMission from 'components/popovers/unassign_mission'
import ConfirmMissionUpdate from 'components/popovers/confirm_mission_update'
import CustomizeDealFields from 'components/popovers/customize_deal_fields'
import {get_missions, get_deals, get_mission_proposals} from 'selectors/missions'

export function mission_period(mission) {
  if (mission.start) {
    let day_format = `D MMM${moment().isSame(mission.start, 'year') ? '' : ' YYYY'}`
    let hour_format = 'HH:mm'
    let day_with_hour_format = `${day_format} ${mission.full_days ? '' : hour_format}`.trim()
    if (moment(mission.start).isSame(mission.end, 'day')) {
      return `${moment(mission.start).format(day_format)}${mission.full_days ? '' : ` : ${moment(mission.start).format(hour_format)} ▸ ${moment(mission.end).format(hour_format)}`}`
    } else {
      return `${moment(mission.start).format(day_with_hour_format)} ▸ ${moment(mission.end).format(day_with_hour_format)}`
    }
  } else {
    return ""
  }
}

export function action_create_deal() {
  request.post(`recruiters/${store.getState().profile.id}/deals`)
  .then((deal) => {
    store.dispatch(store_deals([deal]))
    browserHistory.push(`/deals/${deal.id}`)
  })
}

export function action_update_mission({users_count, grouped_users_status: {assigned, accepted}, status}, mission) {
  const action = () => {
    store.dispatch(update_mission(mission))
    request.delayed_put(`missions/${mission.id}`, {mission})
  }
  if (
    status != 'assigned' &&
    mission.users_count &&
    assigned.length >= mission.users_count &&
    accepted.length
  ) {
    store.dispatch(show_popover(
      ConfirmMissionUpdate,
      {on_confirm: action},
      "Attention"
    ))
  } else {
    action()
  }
}

export function action_cancel_mission({id, status}) {
  function action() {
    store.dispatch(remove_mission(id))
    request.delete(`missions/${id}`)
  }
  if (status == 'draft') {
    action()
  } else {
    store.dispatch(show_popover(
      CancelMission,
      {
        on_click: () => {
          action()
          store.dispatch(dismiss_popover())
        },
        mission_status: status,
      },
      'Annuler la prestation',
    ))
  }
}

export function action_cancel_deal({id, status, missions}) {
  function action() {
    store.dispatch(remove_deal(id))
    request.delete(`deals/${id}`)
    browserHistory.push("/deals")
  }
  store.dispatch(show_popover(
    CancelMission,
    {
      on_click: () => {
        action()
        store.dispatch(dismiss_popover())
      },
      mission_status: status,
    },
    'Annuler la mission',
  ))
}

export function action_update_mission_events(mission_id, events) {
  return request.post(`missions/${mission_id}/events`, {events})
  .then((events) => store.dispatch(replace_mission_events(mission_id, events)))
}

export function place_from_workplace({latitude, longitude, name, address}) {
  return {
    location: {
      lat: latitude,
      lng: longitude,
    },
    label: name,
    address,
  }
}

export function action_send_mission(mission, user_ids) {
  return new Promise((resolve, reject) => {
    store.dispatch(show_popover(
      SendMission,
      {
        mission_id: mission.id,
        on_confirm() {
          request.put(`missions/${mission.id}/send`, {user_ids})
          .then(() => store.dispatch(alert_success("La proposition de mission a bien été envoyée aux candidats que vous aviez sélectionnés.")))
          store.dispatch(send_mission(mission.id, user_ids))
          store.dispatch(dismiss_popover())
          resolve()
        }
      },
      store.getState().profile.agency.name
    ))
  })
}

export function action_assign_mission(mission, user_ids, status = 'accepted') {
  return new Promise((resolve, reject) => {
    store.dispatch(show_popover(
      AssignMission,
      {
        status,
        mission,
        on_confirm() {
          request.put(`missions/${mission.id}/assign`, {user_ids})
          .then(() => {
            const {grouped_users_status: {accepted}, status} = get_missions(store.getState())[mission.id]
            const has_users_with_status_not_retained = status == "assigned" && set_count(set_intersection(set_from_array(mission.grouped_users_status.accepted), accepted))
            store.dispatch(alert_success(`La mission a bien été validée auprès ${human_plural(
              user_ids.length,
              "du candidat que vous aviez sélectionné, et il a été prévenu par mail",
              "des candidats que vous aviez sélectionnés, et ils ont été prévenus par mail"
            )}.${
              has_users_with_status_not_retained ?
              " Les candidats qui s'étaient déclarés intéressés et que vous n'avez pas sélectionés ont reçu un message pour les prévenir." :
              ""
            }`))
          })
          store.dispatch(assign_mission(mission.id, user_ids))
          store.dispatch(dismiss_popover())
          resolve()
        }
      },
      'Valider la mission pour ce candidat'
    ))
  })
}

export function action_unassign_mission(mission, user_ids) {
  return new Promise((resolve, reject) => {
    store.dispatch(show_popover(
      UnassignMission,
      {on_confirm() {
        request.put(`missions/${mission.id}/unassign`, {user_ids})
        .then(() => store.dispatch(alert_success(`Nous avons envoyé un mail ${human_plural(user_ids.length, 'au candidat que vous aviez sélectionné pour lui dire que sa', 'aux candidats que vous aviez sélectionnés pour leur dire que leur')} mission est annulée.`)))
        store.dispatch(unassign_mission(mission.id, user_ids))
        store.dispatch(dismiss_popover())
        resolve()
      }},
      'Annuler la mission pour ce candidat'
    ))
  })
}

export function action_duplicate_deal({id}) {
  browserHistory.push('/deals')
  request.post(`deals/${id}/duplicate`)
  .then((deal) => {
    browserHistory.push(`/deals/${deal.id}`)
    store.dispatch(store_deals([deal]))
  })
}

export function deal_has_custom_fields({has_custom_events, has_custom_workplace, custom_field_ids}) {
  return has_custom_events || has_custom_workplace || !empty_set(custom_field_ids)
}

export function action_add_mission(deal) {
  function action() {
    request.post(`deals/${deal.id}/missions`)
    .then((mission) => store.dispatch(store_missions([mission])))
  }
  if (!deal_has_custom_fields(deal)) {
    action_customize_deal_fields(deal)
    .then(action)
  } else {
    action()
  }
}

export function action_customize_deal_fields({id}) {
  return new Promise((resolve, reject) => {
    store.dispatch(show_popover(
      CustomizeDealFields,
      {
        deal_id: id,
        update(deal) {
          store.dispatch(update_deal({...deal, id}))
          const {has_custom_events, has_custom_workplace, custom_field_ids} = deal
          request.put(`deals/${id}`, {deal: {has_custom_events, has_custom_workplace, custom_field_ids: array_from_set(custom_field_ids)}})
          store.dispatch(dismiss_popover())
          resolve()
        }
      },
      "Sélectionner les champs spécifiques à chaque prestation"
    ))
  })
}

export function action_export_users({id}) {
  return request.asynchronous(`deals/${id}/export_users`)
  .then((response) => {
    download_file(response.url, "mission")
  })
}

export const get_mission_status_elements = make_memoized((status) => {
  switch (status) {
    case 'draft':
      return {
        priority: 1,
        name: 'non proposée',
        color: color('black', 'pale'),
        icon: <MdEdit />,
      }
    case 'sent':
      return {
        priority: 4,
        name: 'en attente de réponse',
        color: color('primary', 'light'),
        icon: "?",
      }
    case 'pending_assignement':
      return {
        priority: 3,
        name: 'en attente de validation',
        color: color('attention'),
        icon: <MdDone />,
      }
    case 'assigned':
      return {
        priority: 5,
        name: 'validée',
        color: color('primary'),
        icon: <MdDoneAll />,
      }
    case 'pending_selection':
      return {
        priority: 2,
        name: 'à proposer à nouveau',
        color: color('important'),
        icon: <MdSend />,
      }
  }
})

export function get_mission_proposal_status_elements(status) {
  switch (status) {
    case 'new':
      return {
        icon: "?",
        color: color('primary', 'light'),
      }
    case 'accepted':
      return {
        icon: <MdDone />,
        color: color('attention'),
      }
    case 'rejected':
      return {
        icon: <MdClose />,
        color: color('black', 'pale'),
      }
    case 'assigned':
      return {
        icon: <MdDoneAll />,
        color: color('primary'),
      }
    default:
      return {}
  }
}

export function action_cancel_drafts(deal_ids) {
  const deals = get_deals(store.getState())
  deal_ids = deal_ids.filter((id) => (deals[id] || {}).status == 'draft')
  request.put(`deals/cancel`, {deal_ids})
  store.dispatch(remove_deals(deal_ids))
}

export function action_toggle_publish_mission({id, published}) {
  store.dispatch(update_mission({id, published: !published}))
  if (published) {
    return request.put(`missions/${id}/unpublish`)
  } else {
    return request.put(`missions/${id}/publish`)
  }
}

export function action_notify_updated_mission(mission_id) {
  const {id, notification_timeout, sent} = get_mission_proposals(store.getState())[mission_id]
  if (!sent) {
    return
  }
  if (notification_timeout) {
    notification_timeout.cancel()
  }
  const will_send_notification_at = moment().add(1, 'minute')
  store.dispatch(update_mission({
    id,
    notification_timeout: cancelable_timeout(() => {
      request.put(`missions/${id}/notify_of_update`)
      store.dispatch(update_mission({
        id,
        notification_timeout: cancelable_timeout(() => {
          store.dispatch(update_mission({id, will_send_notification_at: false}))
        }, 2 * 1000)
      }))
    }, -moment().diff(will_send_notification_at)),
    will_send_notification_at,
  }))
}

export function action_cancel_notify_updated_mission({id, notification_timeout}) {
  if (notification_timeout) {
    notification_timeout.cancel()
  }
  store.dispatch(update_mission({id, will_send_notification_at: false}))
}
