/** @module swisstennis/state */
import { call, put, takeEvery } from 'redux-saga/effects'
import { SZTM_API } from '../local-constants'
import { normalizePhone } from '../helpers'
import api from '../api'

/**
 * state.js
 *
 * Collection of everything which has to do with state changes.
 **/

/** actionTypes define what actions are handeled by the reducer. */
export const actions = {
  changeForm: (data) => {
    return {
      type: 'SMS/CHANGE_FORM',
      data,
    }
  },
  setRecipients: (data) => {
    return {
      type: 'SMS/SET_RECIPIENTS',
      data,
    }
  },
  addRecipient: (data) => {
    return {
      type: 'SMS/ADD_RECIPIENT',
      data,
    }
  },
  removeRecipient: (data) => {
    return {
      type: 'SMS/REMOVE_RECIPIENT',
      data,
    }
  },
  sendSMSRequest: (data) => {
    return {
      type: 'SMS/SEND_REQUEST',
      data,
    }
  },
  sendSMSSuccess: (data) => {
    return {
      type: 'SMS/SEND_SUCCESS',
      data,
    }
  },
  sendSMSFailure: (error) => {
    return {
      type: 'SMS/SEND_FAILURE',
      error,
    }
  },
  getCreditRequest: (data) => {
    return {
      type: 'SMS/CREDIT_REQUEST',
      data,
    }
  },
  getCreditSuccess: (data) => {
    return {
      type: 'SMS/CREDIT_SUCCESS',
      data,
    }
  },
  getCreditFailure: (error) => {
    return {
      type: 'SMS/CREDIT_FAILURE',
      error,
    }
  },
}
console.log('State actions', actions)

/** state definition */
export const state = {
  recipients: [],
  sender: 'SZTM',
  body: '',
  sending: false,
  newRecipient: '',
  message: '',
  credit: '?',
}
console.log('State state', state)

/** reducer is called by the redux dispatcher and handles all component actions */
export function reducer(state = [], action) {
  switch (action.type) {
    case 'SMS/CHANGE_FORM':
      return { ...state, ...action.data }
    case 'SMS/SET_RECIPIENTS':
      return { ...state, recipients: action.data }
    case 'SMS/ADD_RECIPIENT':
      const number = normalizePhone(action.data)
      if (number) {
        return {
          ...state,
          recipients: [number, ...state.recipients],
          newRecipient: '',
        }
      } else {
        return state
      }
    case 'SMS/REMOVE_RECIPIENT':
      console.log(action.data)
      return {
        ...state,
        recipients: [
          ...state.recipients.slice(0, action.data),
          ...state.recipients.slice(action.data + 1),
        ],
      }
    case 'SMS/SEND_REQUEST':
      return { ...state, sending: true }
    case 'SMS/SEND_SUCCESS':
      return {
        ...state,
        sending: false,
        recipients: [],
        newRecipient: '',
        body: '',
      }
    case 'SMS/SEND_FAILURE':
      return { ...state, sending: false }
    case 'SMS/CREDIT_REQUEST':
      return { ...state, credit: '...' }
    case 'SMS/CREDIT_SUCCESS':
      return { ...state, credit: action.data }
    case 'SMS/CREDIT_FAILURE':
      return { ...state, credit: '?' }
    default:
      return state
  }
}

function* sendSMS(action) {
  try {
    const token = localStorage.getItem('accessToken')
    console.log('Send SMS requested', action, token)
    const { body, sender, recipients } = action.data
    const recipientNumbers = recipients
      .map((recipient) =>
        typeof recipient === 'string' ? recipient : recipient.phone
      )
      .filter((recipient) => recipient !== null)
    const response = yield call(fetch, `${SZTM_API}/api/sms/send`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-access-token': token,
      },
      body: JSON.stringify({
        recipients: recipientNumbers,
        body,
        sender,
      }),
    })
    if (response.status !== 200) {
      console.log(response)
      throw Error(yield response.json())
    } else {
      const responseJson = yield response.json()
      yield put(actions.sendSMSSuccess(responseJson))
    }
  } catch (error) {
    console.log('Config failure!', actions.sendSMSFailure(error.toString()))
    yield put(actions.sendSMSFailure(error))
  }
}

function* getCredit(action) {
  console.log('getting credit.')
  yield put(
    api.actions.apiRequest({
      path: 'api/sms/credits',
      onSuccess: actions.getCreditSuccess,
      onFailure: actions.getCreditFailure,
    })
  )
}

/** sagas are asynchronous workers (JS generators) to handle the state. */
export function* saga() {
  console.log('SMS saga started.')
  yield takeEvery('SMS/SEND_REQUEST', sendSMS)
  yield takeEvery('SMS/CREDIT_REQUEST', getCredit)
}
