import React, { useReducer, useEffect } from 'react'

import {
  storeBookingData,
  loadBookingData,
  clearBookingData,
} from '../../../helpers/storage'

export const WizardContext = React.createContext()

export const ACTIONS = {
  SET_FORM_DATA: 'setFormData',
  POST_DATA: 'postData',
  POST_DATA_ERROR: 'postDataError',
  POST_DATA_SUCCESS: 'postDataSuccess',
  DATA_STORED: 'dataStored',
  DATA_STORED_LOADED: 'dataStoredLoaded',
  DATA_STORED_FORGOTTEN: 'dataStoredForgotten',
}

function reducer(state, action) {
  switch (action.type) {
    case ACTIONS.SET_FORM_DATA:
      return {
        ...state,
        formData: {
          ...state.formData,
          ...action.payload,
        },
        formDataChanged: [
          ...state.formDataChanged,
          ...Object.keys(action.payload),
        ],
      }
    case ACTIONS.POST_DATA:
      return {
        ...state,
        postData: true,
        postDataError: null,
        postDataSuccess: null,
      }
    case ACTIONS.POST_DATA_ERROR:
      return {
        ...state,
        postData: false,
        postDataError: action.payload,
        postDataSuccess: null,
      }
    case ACTIONS.POST_DATA_SUCCESS:
      return {
        ...state,
        formData: {
          ...state.formData,
        },
        booking: { ...action.payload },
        postData: false,
        postDataError: null,
        postDataSuccess: true,
      }
    case ACTIONS.DATA_STORED_LOADED:
      return {
        ...state,
        dataStoredLoaded: true,
        formData: {
          ...state.formData,
          ...action.payload,
        },
      }
    case ACTIONS.DATA_STORED_FORGOTTEN:
      return {
        ...state,
        dataStored: undefined,
        dataStoredLoaded: undefined,
        formData: { ...initialState.formData },
      }
    case ACTIONS.DATA_STORED:
      return {
        ...state,
        dataStored: action.payload,
      }
    default:
      throw new Error(`Unkown Action type ${action.type}`)
  }
}

function debugReducer(state, action) {
  console.debug('applying action', action)
  const newState = reducer(state, action)
  console.debug(newState)
  return newState
}

const initialState = {
  postData: false,
  postDataError: null,
  postDataSuccess: null,
  formData: {
    startDate: '',
    endDate: '',
    purpose: '',
    org: '',
    destination: '',
    name: '',
    email: '',
    street: '',
    zip: '',
    city: '',
  },
  formDataChanged: [],
}

async function createBooking(formData) {
  const response = await fetch('/api/booking', {
    method: 'POST',
    mode: 'cors',
    cache: 'no-cache',
    credentials: 'same-origin',
    headers: {
      'Content-Type': 'application/json',
    },
    referrerPolicy: 'no-referrer',
    body: JSON.stringify(formData),
  })
  return response.json()
}

export default function WizardStore({ children }) {
  const [state, dispatch] = useReducer(debugReducer, initialState)

  useEffect(() => {
    const data = loadBookingData()
    if (data !== null) {
      dispatch({ type: ACTIONS.DATA_STORED_LOADED, payload: data })
    }
  }, [])

  const onChangeEvent = (event) => {
    const { name, value } = event.target

    dispatch({
      type: ACTIONS.SET_FORM_DATA,
      payload: { [name]: value },
    })
  }

  const onChange = (data) => {
    dispatch({
      type: ACTIONS.SET_FORM_DATA,
      payload: data,
    })
  }

  const onSubmit = async () => {
    dispatch({ type: ACTIONS.POST_DATA })

    try {
      const booking = await createBooking(state.formData)
      dispatch({ type: ACTIONS.POST_DATA_SUCCESS, payload: booking })
    } catch (error) {
      console.error(error)
      dispatch({ type: ACTIONS.POST_DATA_ERROR, payload: error.message })
    }
  }

  const storeData = (value) => {
    if (value) {
      storeBookingData(state.booking)
    }

    dispatch({ type: ACTIONS.DATA_STORED, payload: value })
  }

  const forgetData = () => {
    clearBookingData()
    dispatch({ type: ACTIONS.DATA_STORED_FORGOTTEN })
  }

  return (
    <WizardContext.Provider
      value={{
        state,
        dispatch,
        onChangeEvent,
        onChange,
        onSubmit,
        storeData,
        forgetData,
      }}
    >
      {children}
    </WizardContext.Provider>
  )
}
