import { Alert, Drawer, Stepper, Typography } from '@tidbcloud/uikit'
import {
  Form,
  FormPhoneInput,
  validPhoneNumber,
  FormSelect,
  FormTextareaInput,
  FormTextInput
} from '@tidbcloud/uikit/biz'
import { observer } from 'mobx-react'
import React, { useEffect, useState } from 'react'
import { useForm, useFormContext } from 'react-hook-form'

import { log } from 'common/log'
import { CompanyField, EmailField, NameFields } from 'dbaas/screens/User/Common/FormFields'
import { CentralCreatePocApplicationReq, CentralPocQuestionType, createPOCApplication } from 'dbaas/services'
import useStores from 'dbaas/stores/useStores'
import countriesData, { isAllowedOtherCountryOrRegion, OTHER_COUNTRY_OR_REGION } from 'dbaas/utils/countriesData'
import { eventTracking } from 'dbaas/utils/tracking'

import { ContactUsQuestion, questions } from './questions'

enum QUESTION_TYPES {
  APPLY_FOR_POC = '0',
  PRODUCT_FEEDBACK = '3'
}

interface FormValues {
  questions: { optionIndex?: string; note: '' }[]
  email: string
  first_name: string
  last_name: string
  country: string
  country_name?: string
  phone_number: string
  company: string
}

export interface ContactUsProps {
  open: boolean
  onClose?: () => void
  source: 'poc' | 'feedback' | 'endpoint'
}

const pickAnswer = (data: FormValues): CentralCreatePocApplicationReq => {
  const options = questions.reduce(
    (prev, next, idx) => {
      prev[next.key] = next.options
        ? next.options[Number(data.questions[idx]?.optionIndex) || 0]?.name || ''
        : data.questions[idx].note
      return prev
    },
    { poc_record_type: '', sub_topic: '', msg: '' }
  )

  return options
}

const profiles = [
  {
    question: 'Work Email',
    key: 'email'
  },
  {
    question: 'First Name',
    key: 'first_name'
  },
  {
    question: 'Last Name',
    key: 'last_name'
  },
  {
    question: 'Country / Region',
    key: 'country'
  },
  {
    question: 'Phone Number',
    key: 'phone_number'
  },
  {
    question: 'Company Name',
    key: 'company'
  }
]

const pickUserProfile = (data: FormValues) => {
  return profiles.map((profile, index) => {
    return {
      question: profile.question,
      number: (index + 1).toString(),
      type: CentralPocQuestionType.TEXT,
      note: data[profile.key]
    }
  })
}

const Questions: React.FC<React.PropsWithChildren<{ source: ContactUsProps['source'] }>> = ({ source }) => {
  const {
    watch,
    clearErrors,
    formState: { errors }
  } = useFormContext()
  const filledQuestions = watch('questions')
  const hideQuestionType = source === 'poc'

  const renderLabel = (question: ContactUsQuestion) => {
    if (question.label) {
      return question.label(filledQuestions)
    }
    return question.question
  }

  const isProductFeedback = filledQuestions[0]?.optionIndex === QUESTION_TYPES.PRODUCT_FEEDBACK

  useEffect(() => {
    // if switch product feedback to other options need to clear errors
    if (filledQuestions[0]?.optionIndex !== QUESTION_TYPES.PRODUCT_FEEDBACK && errors.questions?.[2]) {
      clearErrors('questions.2.note')
    }
    // eslint-disable-next-line
  }, [filledQuestions[0]?.optionIndex, clearErrors])

  return (
    <div>
      {questions.map((question, index) => {
        if (hideQuestionType && index === 0) {
          return null
        }
        // for product feed back need hide second question
        if (isProductFeedback && index === 1) {
          return null
        }
        if (question.type === CentralPocQuestionType.RADIO) {
          return (
            <FormSelect
              mb={16}
              key={question.question}
              name={`questions.${index}.optionIndex`}
              label={
                question.helper ? (
                  <>
                    {renderLabel(question)} {question.helper}
                  </>
                ) : (
                  renderLabel(question)
                )
              }
              data={(question.options || []).map((op, idx) => {
                return {
                  label: op.name,
                  value: idx.toString()
                }
              })}
            />
          )
        }
        return (
          <FormTextareaInput
            key={question.question}
            name={`questions.${index}.note`}
            autosize
            minRows={2}
            rules={{
              required: isProductFeedback ? 'Please enter your message' : undefined,
              maxLength: {
                value: 255,
                message: 'The maximum number of characters is 255.'
              }
            }}
            required={isProductFeedback ? true : question.required}
            label={question.question}
          />
        )
      })}
    </div>
  )
}

export const ContactUs: React.FC<React.PropsWithChildren<ContactUsProps>> = observer(
  ({ open, onClose = () => {}, source = 'poc' }) => {
    const [activeStep, setActiveStep] = useState(0)
    const [isSent, setIsSent] = useState(false)
    const {
      store: { tenantData, userProfile }
    } = useStores()

    const defaultProfile = {
      first_name: userProfile.first_name,
      last_name: userProfile.last_name,
      email: userProfile.email,
      company: tenantData.name ?? '',
      country: tenantData.country ?? '',
      phone_number: userProfile.phone_number ?? ''
    }

    const form = useForm<FormValues>({
      mode: 'all',
      reValidateMode: 'onChange',
      defaultValues: {
        questions: [
          {
            // 0 means Apply for POC
            // 3 means Product Feedback
            optionIndex: source === 'poc' ? QUESTION_TYPES.APPLY_FOR_POC : QUESTION_TYPES.PRODUCT_FEEDBACK
          },
          {
            optionIndex: '0'
          },
          {
            note: ''
          }
        ],
        ...defaultProfile,
        country_name: ''
      }
    })

    const onSubmit = async (data: FormValues, _reset: any, withContact = false) => {
      try {
        // Check country_name validation only when country is OTHER_COUNTRY_OR_REGION
        if (data.country === OTHER_COUNTRY_OR_REGION && data.country_name) {
          if (!isAllowedOtherCountryOrRegion(data.country_name)) {
            throw new Error('Information error')
          }
          data.country = 'TW'
        }

        const answer = pickAnswer(data)
        eventTracking('Submit Contact Us Form', {
          withContact,
          source,
          contactType: answer.poc_record_type
        })
        const questions = pickUserProfile(data)
        await createPOCApplication(tenantData.id, {
          ...answer,
          questions
        })
        setIsSent(true)
        onClose?.()
        // reset state after close dialog
        setTimeout(() => {
          setActiveStep(0)
          setIsSent(false)
        }, 0)
      } catch (e) {
        throw e
      }
    }

    const isFinal = activeStep === 1

    const onDrawerClose = async () => {
      if (!isSent && isFinal) {
        const formValues = form.getValues()
        try {
          // in this case, need to submit original user profile
          await onSubmit({ ...formValues, ...defaultProfile }, undefined, true)
        } catch (_e) {
          log.error(
            `sync poc error: ${formValues.questions[0]?.optionIndex} ${formValues.questions[1]?.optionIndex || ''}`
          )
        }
      }
      // reset state
      setTimeout(() => {
        setActiveStep(0)
        setIsSent(false)
      }, 0)
      eventTracking('Close Contact Us Form', {
        source
      })
    }

    const { watch } = form

    const country = watch('country')
    const countryName = watch('country_name')

    useEffect(() => {
      if (open) {
        eventTracking('Open Contact Us Form', {
          source
        })
      }
    }, [open, source])

    useEffect(() => {
      // Clear country_name when country is not OTHER_COUNTRY_OR_REGION
      if (country && country !== OTHER_COUNTRY_OR_REGION) {
        form.clearErrors('country_name')
      }
    }, [country, form])

    return (
      <Drawer
        opened={open}
        size={560}
        onClose={() => {
          onClose()
          onDrawerClose()
        }}
        position="right"
        title={<Typography variant="title-lg">Contact Us</Typography>}
        padding={24}
        trapFocus={false}
      >
        <Form<FormValues>
          onSubmit={onSubmit}
          form={form}
          onCancel={() => {
            onClose()
            onDrawerClose()
          }}
          actionsProps={
            isFinal
              ? {}
              : {
                  cancelProps: {
                    onClick: () => {
                      eventTracking('Cancel Contact Us Form Clicked', { source })
                      onClose()
                    }
                  },
                  confirmText: 'Submit',
                  confirmProps: {
                    type: 'button',
                    onClick: async (e) => {
                      e.stopPropagation()
                      e.preventDefault()
                      eventTracking('Contact Us Form Next Clicked', { source })
                      const result = await form.trigger(`questions.2.note`)
                      if (!result) {
                        return
                      }
                      setActiveStep(activeStep + 1)
                    }
                  }
                }
          }
        >
          <Stepper size="sm" iconSize={28} active={activeStep}>
            <Stepper.Step label="Submit Feedback"></Stepper.Step>
            <Stepper.Step label="Confirm information"></Stepper.Step>
          </Stepper>
          <div style={{ display: isFinal ? 'none' : 'block' }}>
            <Questions source={source} />
          </div>
          <div style={{ display: isFinal ? 'block' : 'none' }}>
            <Alert title="Your feedback has been received. Thank you." color="green" mb={16}>
              <p>Please complete your contact information and we will get back to you in 48 hours.</p>
            </Alert>
            <EmailField required />
            <NameFields required />
            <FormSelect
              data={countriesData.map((it) => ({ value: it.value, label: it.text }))}
              name="country"
              label="Country / Region"
              placeholder=""
              withAsterisk
              searchable
              rules={{ required: 'Please select your country/region.' }}
              mb={16}
            />
            {country === OTHER_COUNTRY_OR_REGION && (
              <FormTextInput
                name="country_name"
                placeholder="Country / Region"
                withAsterisk
                rules={{
                  required: 'Please input your country/region'
                }}
                mb={16}
              />
            )}
            <CompanyField requiredTip />
            <FormPhoneInput
              name="phone_number"
              rules={{
                required: 'Please input your phone number.',
                validate: async (val: string) => {
                  const country = form.getValues().country
                  if (!country) {
                    return 'Please select your country / region'
                  }
                  try {
                    const result = await validPhoneNumber(country === OTHER_COUNTRY_OR_REGION ? 'TW' : country, val)
                    if (!result) {
                      return 'Phone Number is invalid.'
                    }
                    return true
                  } catch (_e) {
                    return true
                  }
                }
              }}
              country={
                country === OTHER_COUNTRY_OR_REGION && isAllowedOtherCountryOrRegion(countryName || '') ? 'TW' : country
              }
              withAsterisk
              showContryCodeAfterFocus
              label="Phone Number"
            />
          </div>
        </Form>
      </Drawer>
    )
  }
)
