import { Button, CircularProgress } from '@mui/material'
import axios, { AxiosError } from 'axios'
import { Form, Formik, FormikValues } from 'formik'
import _get from 'lodash/get'
import _identity from 'lodash/identity'
import _map from 'lodash/map'
import React, { FC, useEffect, useState } from 'react'

import { getCountries, getProfileData, getStates, register } from '../../api'
import { CONFIGS, getFormInitialValues, getQueryVariable } from '../../utils'
import { FieldsSection } from '../common/FieldSection'
import { updateFormFieldsAttributes } from '../common/FieldSection/utils'
import ConfirmModal from '../confirmModal'
import { collectStates } from './adapters'
import { formDefaultFields } from './constants'

interface IRegistrationProps {
  formFields?: Array<IFormFieldsSection>;
  additionalFieldAttribute?: IFieldAttribute;
  registrationType: string;
  onGetCountriesSuccess?: (res: any) => void;
  onGetCountriesError?: (e: AxiosError) => void;
  onRegisterAccountSuccess?: (res: any) => void;
  onRegisterAccountError?: (e: AxiosError) => void;
  onGetStatesSuccess?: (res: any) => void;
  onGetStatesError?: (e: AxiosError) => void;
  customerEmail: string;
}

export const RegistrationForm: FC<IRegistrationProps> = ({
  formFields,
  additionalFieldAttribute,
  registrationType,
  customerEmail,
  onGetCountriesSuccess = _identity,
  onGetCountriesError = _identity,
  onRegisterAccountSuccess = _identity,
  onRegisterAccountError = _identity,
  onGetStatesSuccess = _identity,
  onGetStatesError = _identity,
}) => {
  const [errorMessage, setErrorMessage] = useState('')
  const [countries, setCountries] = useState<{ [key: string]: string | number }[]>([])
  const [states, setStates] = useState<{ [key: string]: string | number }[]>([])
  const [phoneValidationIsLoading, setPhoneValidationIsLoading] = useState(false)
  const [showErrorModal, setshowErrorModal] = useState(false)

  const updatedFormFields = updateFormFieldsAttributes(
    formFields || formDefaultFields,
    additionalFieldAttribute
  )

  // Fetch countries data
  const fetchCountries = async () => {
    try {
      const res = await getCountries()
      setCountries(
        _map(res.data, item => ({
          label: item.name,
          value: item.id,
        }))
      )
      onGetCountriesSuccess(res.data)
    } catch (e) {
      if (axios.isAxiosError(e)) {
        const errorMessage = _get(e, 'response.data.message') || 'Error'
        setErrorMessage(errorMessage)
        onGetCountriesError(e)
      }
    }
  }

  // Fetch states data
  const fetchStates = async (countryId?: string | number) => {
    try {
      const fetchCountryId = countryId ? countryId : '1'
      const res = await getStates(fetchCountryId)
      const states = _get(res, 'data', [])
      const mappedStates = collectStates(states)
      setStates(mappedStates)
      onGetStatesSuccess(res.data)
    } catch (e) {
      if (axios.isAxiosError(e)) {
        const errorMessage = _get(e, 'response.data.message', {}) as AxiosError
        onGetStatesError(errorMessage)
      }
    }
  }

  const handleRegisterAccount = async (values: FormikValues) => {
    const accessHash = getQueryVariable('hash') || ''

    try {
      const bodyFormData = new FormData()

      bodyFormData.append('first_name', values.firstName)
      bodyFormData.append('last_name', values.lastName)
      bodyFormData.append('email', values.email)
      bodyFormData.append('zip', values.zip)
      bodyFormData.append('city', values.city)
      bodyFormData.append('country', values.country)
      bodyFormData.append('password', values.password)
      bodyFormData.append('phone', values.phone || '')
      bodyFormData.append('password_confirmation', values.confirmPassword)
      bodyFormData.append('client_id', CONFIGS.CLIENT_ID)
      bodyFormData.append('client_secret', CONFIGS.CLIENT_SECRET)
      bodyFormData.append('register_for', registrationType)
      bodyFormData.append('delegation_access_hash', accessHash)

      await register(bodyFormData)
      const profileRes = await getProfileData()

      window.localStorage.setItem('user_data', JSON.stringify(_get(profileRes, 'data')))
      onRegisterAccountSuccess(profileRes)
    } catch (e) {
      if (axios.isAxiosError(e)) {
        const errorMessage = _get(e, 'response.data.message') || 'Error'
        onRegisterAccountError(e)
        setshowErrorModal(true)
        setErrorMessage(errorMessage)
      } else if (e instanceof Error) {
        setErrorMessage(e?.message || 'Error')
      }
    }
  }

  useEffect(() => {
    fetchCountries()
    fetchStates()
  }, [])

  return (
    <div className="register-form-container">
      <h2>Create an account</h2>
      <div className="register-sub-title">
        To manage your tickets, please create an account:
      </div>
      {showErrorModal && (
        <ConfirmModal
          hideCancelBtn={true}
          message={errorMessage}
          onClose={() => (window.location.href = '/')}
          onConfirm={() => (window.location.href = '/')}
        />
      )}
      {errorMessage && <div className="register-error">{errorMessage}</div>}
      <Formik
        initialValues={{
          ...getFormInitialValues(updatedFormFields),
          email: customerEmail,
        }}
        enableReinitialize={true}
        onSubmit={handleRegisterAccount}
      >
        {props => (
          <Form>
            <div className="register-body">
              <FieldsSection
                disableField={'email'}
                containerClass="register"
                formFields={updatedFormFields}
                values={props.values}
                setFieldValue={props.setFieldValue}
                setPhoneValidationIsLoading={setPhoneValidationIsLoading}
                countries={countries}
                states={states}
                onFieldChange={(name, value) => {
                  if (name === 'country') {
                    fetchStates(value)
                  }
                }}
              />
            </div>
            <div className="button-container">
              <Button
                className="register-button"
                type="submit"
                disabled={props.isSubmitting || phoneValidationIsLoading}
              >
                {props.isSubmitting ? <CircularProgress size={26} /> : 'Create Account'}
              </Button>
            </div>
          </Form>
        )}
      </Formik>
    </div>
  )
}
