import { Grid } from '@mui/material'
import { AxiosError } from 'axios'
import { Field, Form, Formik } from 'formik'
import _get from 'lodash/get'
import _map from 'lodash/map'
import React, { FC, useEffect, useState } from 'react'

import { getCountries, getProfileData, getStates, register } from '../../api'
import { CONFIGS, isBrowser, setLoggedUserData } from '../../utils'
import {
  confirmPasswordValidator,
  emailValidator,
  passwordValidator,
  requiredValidator,
} from '../../validators'
import { CustomField } from '../common/CustomField'
import { PhoneNumberField } from '../common/PhoneNumberField'

interface SignUpFormProps {
  onSignUpSuccess: (res: IProfileData) => void;
  onGetProfileDataSuccess?: (res: any) => void;
  onGetProfileDataError?: (e: AxiosError) => void;
  logo?: string;
}

export const SignUpForm: FC<SignUpFormProps> = ({
  onSignUpSuccess,
  onGetProfileDataSuccess = () => {},
  onGetProfileDataError = () => {},
  logo,
}) => {
  const [error, setError] = useState('')
  const [isSubmitting, setIsSubmitting] = useState(false)
  const [countries, setCountries] = useState<any[]>([])
  const [states, setStates] = useState<any[]>([])
  const [phoneValidationIsLoading, setPhoneValidationIsLoading] = useState(false)

  // Fetch countries on mount
  useEffect(() => {
    const fetchCountries = async () => {
      try {
        const res = await getCountries()
        const mappedCountries = _map(res.data, (item: any) => ({
          id: item.id,
          name: item.name,
          code: item.code,
        }))
        setCountries(mappedCountries)
      } catch (e) {
        console.error('Error fetching countries:', e)
      }
    }
    fetchCountries()
  }, [])

  return (
    <Formik
      enableReinitialize
      initialValues={{
        firstName: '',
        lastName: '',
        email: '',
        password: '',
        passwordConfirmation: '',
        phone: '',
        country: '1',
        city: '',
        state: '',
        streetAddress: '',
        zip: '',
      }}
      onSubmit={async values => {
        setIsSubmitting(true)
        setError('')
        try {
          const formData = new FormData()
          formData.append('first_name', values.firstName)
          formData.append('last_name', values.lastName)
          formData.append('email', values.email)
          formData.append('password', values.password)
          formData.append('password_confirmation', values.passwordConfirmation)
          formData.append('phone', values.phone)
          formData.append('country', values.country)
          formData.append('city', values.city)
          formData.append('state', values.state)
          formData.append('street_address', values.streetAddress)
          formData.append('zip', values.zip)
          formData.append('client_id', CONFIGS.CLIENT_ID || '')
          formData.append('client_secret', CONFIGS.CLIENT_SECRET || '')

          await register(formData)

          // Fetch profile data after successful signup
          try {
            const profileResponse = await getProfileData()
            onGetProfileDataSuccess(profileResponse.data)

            const profileSpecifiedData = profileResponse.data
            const profileDataObj = setLoggedUserData(profileSpecifiedData)

            if (isBrowser) {
              window.localStorage.setItem('user_data', JSON.stringify(profileDataObj))
              const event = new window.CustomEvent('tf-login')
              window.document.dispatchEvent(event)
            }

            onSignUpSuccess(_get(profileResponse, 'data.data', {}) as IProfileData)
          } catch (e) {
            if ((e as any).isAxiosError) {
              onGetProfileDataError(e as AxiosError)
            }
            setError('Registration successful but failed to fetch profile data')
          }
        } catch (e) {
          const errorData = _get(e, 'response.data.message', '')

          // Check if error is an object with field-specific errors
          if (typeof errorData === 'object' && errorData !== null) {
            const errorMessages = Object.entries(errorData)
              .map(([field, messages]) => {
                const fieldName = field.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase())
                const messageArray = Array.isArray(messages) ? messages : [messages]
                return `${fieldName}: ${messageArray.join(', ')}`
              })
              .join('\n')
            setError(errorMessages || 'Registration failed. Please try again.')
          } else {
            setError(String(errorData) || 'Registration failed. Please try again.')
          }
        } finally {
          setIsSubmitting(false)
        }
      }}
    >
      {props => (
        <Form onSubmit={props.handleSubmit}>
          <div className="login-logo-container">
            <img
              className="login-logo-tff"
              src={
                logo ||
                'https://www.ticketfairy.com/resources/images/logo-ttf-black.svg'
              }
              alt="logo"
            />
          </div>
          {error && (
            <div className="server_auth__error" style={{ whiteSpace: 'pre-line' }}>
              {error}
            </div>
          )}
          <Grid container spacing={2} sx={{ padding: '15px 25px', maxHeight: { xs: '40vh', sm: '60vh' }, overflowY: 'auto' }}>
            {/* Name Fields */}
            <Grid item xs={12} md={6}>
              <Field
                name="firstName"
                label="First Name"
                type="text"
                component={CustomField}
                theme="light"
                validate={requiredValidator}
              />
            </Grid>
            <Grid item xs={12} md={6}>
              <Field
                name="lastName"
                label="Last Name"
                type="text"
                component={CustomField}
                theme="light"
                validate={requiredValidator}
              />
            </Grid>

            {/* Email */}
            <Grid item xs={12} md={6}>
              <Field
                name="email"
                label="Email"
                type="email"
                component={CustomField}
                theme="light"
                validate={(value: string) => {
                  const required = requiredValidator(value)
                  if (required) return required
                  return emailValidator(value)
                }}
              />
            </Grid>

            {/* Street Address */}
            <Grid item xs={12} md={6}>
              <Field
                name="streetAddress"
                label="Street Address"
                type="text"
                component={CustomField}
                theme="light"
                validate={requiredValidator}
              />
            </Grid>

            {/* Zip Code */}
            <Grid item xs={12} md={6}>
              <Field
                name="zip"
                label="Zip / Postal Code"
                type="text"
                component={CustomField}
                theme="light"
                validate={requiredValidator}
              />
            </Grid>

            {/* Country */}
            <Grid item xs={12} md={6}>
              <Field
                name="country"
                label="Country"
                type="select"
                component={CustomField}
                theme="light"
                validate={requiredValidator}
                selectOptions={_map(countries, item => ({
                  value: item.id,
                  label: item.name,
                }))}
                onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
                  props.setFieldValue('country', e.target.value)
                  props.setFieldValue('state', '')
                  // Fetch states for selected country
                  const fetchStatesForCountry = async () => {
                    try {
                      const res = await getStates(e.target.value)
                      const mappedStates = _map(res.data, (item, key) => ({
                        label: item,
                        value: key,
                      }))
                      setStates(mappedStates)
                    } catch (error) {
                      console.error('Error fetching states:', error)
                      setStates([])
                    }
                  }
                  fetchStatesForCountry()
                }}
              />
            </Grid>

            {/* State */}
            <Grid item xs={12} md={6}>
              <Field
                name="state"
                label="State / Province"
                type="select"
                component={CustomField}
                theme="light"
                validate={requiredValidator}
                selectOptions={[
                  { value: '', label: 'Select State/Province', disabled: true },
                  ...states,
                ]}
              />
            </Grid>

            {/* City */}
            <Grid item xs={12} md={6}>
              <Field
                name="city"
                label="City"
                type="text"
                component={CustomField}
                theme="light"
                validate={requiredValidator}
              />
            </Grid>

            {/* Phone */}
            <Grid item xs={12}>
              <Field
                name="phone"
                label="Phone"
                type="phone"
                component={PhoneNumberField}
                fill={true}
                disableDropdown={false}
                setPhoneValidationIsLoading={setPhoneValidationIsLoading}
                defaultCountry="us"
                isCountryCodeEditable={true}
              />
            </Grid>

            {/* Password */}
            <Grid item xs={12} md={6}>
              <Field
                name="password"
                label="Password"
                type="password"
                component={CustomField}
                theme="light"
                validate={passwordValidator}
              />
            </Grid>

            {/* Confirm Password */}
            <Grid item xs={12} md={6}>
              <Field
                name="passwordConfirmation"
                label="Confirm Password"
                type="password"
                component={CustomField}
                theme="light"
                validate={(value: string) => confirmPasswordValidator(value, props.values.password)}
              />
            </Grid>
          </Grid>

          <div className="login-modal-body">
            <div className="login-action-button">
              <button type="submit" disabled={isSubmitting || phoneValidationIsLoading}>
                {isSubmitting ? 'Creating Account...' : 'Create Account'}
              </button>
            </div>
          </div>
        </Form>
      )}
    </Formik>
  )
}
