import { Card, Typography, Group, LoadingOverlay, notifier } from '@tidbcloud/uikit'
import { Form, FormTextInput, FormSelect } from '@tidbcloud/uikit/biz'
import { observer } from 'mobx-react'
import { useEffect, useMemo, useState } from 'react'
import { useForm } from 'react-hook-form'

import { useAccessCheck } from 'dbaas/contexts/access-control'
import { TAX_IDS } from 'dbaas/features/Billing/tax'
import { updateBillingInfo } from 'dbaas/services/billing'
import { FormsBillingInformationInput } from 'dbaas/services/billing/interface'
import useStores from 'dbaas/stores/useStores'
import { BILLING_COUNTRY_OPTIONS, OTHER_COUNTRY_OR_REGION } from 'dbaas/utils/countriesData'
import { emailRegEx } from 'dbaas/utils/regex'
import { eventTracking } from 'dbaas/utils/tracking'
import { companyNameRules } from 'dbaas/utils/validationRules'
import { addressRules, cityRules, provinceRules, postalCodeRules } from 'dbaas/utils/validationRules'

const TaxIDOptions = TAX_IDS.map((tax) => ({
  label: tax.country + ' - ' + tax.description,
  value: tax.country_code + ':' + tax.tax_id_type
}))

const ProfileForm: React.FC<
  React.PropsWithChildren<{
    info: FormsBillingInformationInput
    disabled?: boolean
    onSubmit: (data: FormsBillingInformationInput) => Promise<void>
  }>
> = ({ info, onSubmit, disabled }) => {
  const isBiilingProfileEditable = useAccessCheck('BillingProfileEdit')
  // compatibility for old data
  const taxIdCountryCode = info.tax_id_country_code || info.country_code
  const form = useForm<FormsBillingInformationInput>({
    mode: 'all',
    defaultValues: {
      ...info,
      tax_id_country_code: taxIdCountryCode,
      tax_id_type: taxIdCountryCode + ':' + info.tax_id_type
    },
    disabled: !isBiilingProfileEditable
  })

  const { watch } = form

  const country = watch('country_code')

  const taxIDType = watch('tax_id_type')

  const taxVatPlaceholder = useMemo(() => {
    return TAX_IDS.find((tax) => tax.tax_id_type === taxIDType?.split(':')?.[1])?.example || 'Tax ID'
  }, [taxIDType])

  useEffect(() => {
    if (!taxIDType) {
      const tax = TAX_IDS.find((tax) => tax.country_code === country)
      if (tax) {
        form.setValue('tax_id_type', tax.country_code + ':' + tax.tax_id_type)
      }
    }
  }, [country, form, taxIDType])

  useEffect(() => {
    if (country && country !== OTHER_COUNTRY_OR_REGION) {
      form.clearErrors('custom_input_country_name')
    }
  }, [country, form])

  return (
    <Form
      form={form}
      onSubmit={onSubmit}
      layout="none"
      actionsProps={{
        justify: 'flex-start',
        cancelProps: { display: 'none' },
        confirmProps: {
          disabled: disabled || !isBiilingProfileEditable
        },
        confirmText: 'Save'
      }}
    >
      <Typography variant="title-lg">Company name</Typography>
      <Typography variant="body-lg">
        If specified, this name will appear on invoices instead of your organization name.
      </Typography>
      <FormTextInput
        mt={16}
        name="company_name"
        rules={{
          ...companyNameRules
        }}
        placeholder="Optional"
      ></FormTextInput>
      <Typography variant="title-lg" mt={24}>
        Billing email
      </Typography>
      <Typography variant="body-lg">
        Invoices and other billing notifications will be sent to the billing email address.
      </Typography>
      <FormTextInput
        mt={16}
        name="billing_email"
        rules={{
          pattern: {
            value: emailRegEx,
            message: 'Please enter a valid email address.'
          }
        }}
        placeholder="Optional"
      ></FormTextInput>
      <Typography variant="title-lg" mt={24}>
        Primary business address
      </Typography>
      <Typography variant="body-lg">The address provided is used to calculate any applicable tax.</Typography>
      <FormSelect
        mt={16}
        required
        name="country_code"
        searchable
        data={BILLING_COUNTRY_OPTIONS.map((option) => ({ label: option.text, value: option.value }))}
        placeholder="Country / Region"
        rules={{ required: 'Please select your country/region.' }}
        disabled={!isBiilingProfileEditable}
      />
      {country === OTHER_COUNTRY_OR_REGION && (
        <FormTextInput
          mt={16}
          withAsterisk
          name="custom_input_country_name"
          placeholder="Country / Region"
          rules={{ required: 'Please input your country/region' }}
        />
      )}
      <FormTextInput
        mt={16}
        withAsterisk
        name="line1"
        placeholder="Address Line 1"
        rules={{ ...addressRules, required: 'Required' }}
      />
      <FormTextInput mt={16} name="line2" placeholder="Address Line 2 (Optional)" rules={addressRules} />
      <FormTextInput
        mt={16}
        withAsterisk
        name="city"
        placeholder="City"
        rules={{ ...cityRules, required: 'Required' }}
      />
      <FormTextInput
        mt={16}
        withAsterisk
        name="postal_code"
        placeholder="Zip Code"
        rules={{ ...postalCodeRules, required: 'Required' }}
      />
      <FormTextInput
        mt={16}
        withAsterisk
        name="state"
        placeholder="State"
        rules={{ ...provinceRules, required: 'Required' }}
      />
      <Typography variant="title-lg" mt={24}>
        Business tax ID
      </Typography>
      <Typography variant="body-lg">
        If you are a VAT/GST registered business, please enter a valid VAT/GST ID and we will not charge you VAT/GST as
        applicable.
      </Typography>
      <Group wrap="nowrap" mt={16} align="flex-start">
        <FormSelect
          data={TaxIDOptions}
          w={300}
          searchable
          name="tax_id_type"
          placeholder="Tax Type"
          disabled={!isBiilingProfileEditable}
        ></FormSelect>
        <FormTextInput name="tax_vat" placeholder={taxVatPlaceholder} rules={{ ...postalCodeRules }} />
      </Group>
    </Form>
  )
}

export const BillingProfile: React.FC<React.PropsWithChildren<{ disabled?: boolean }>> = observer(({ disabled }) => {
  const {
    store: {
      tenantData,
      payments: { billingProfile }
    },
    actions: { fetchBillingProfile }
  } = useStores()

  const [loaded, setLoaded] = useState(false)

  const onSubmit = async (data: FormsBillingInformationInput) => {
    const [taxIdCountryCode, taxIdType] = data.tax_id_type?.split(':') || []
    await updateBillingInfo(tenantData.id, {
      ...data,
      custom_input_country_name:
        data.country_code === OTHER_COUNTRY_OR_REGION ? data.custom_input_country_name : undefined,
      tax_id_type: taxIdType || '',
      tax_id_country_code: taxIdCountryCode || ''
    })
    await fetchBillingProfile(tenantData.id)
    notifier.success('Billing profile saved.')
    eventTracking('Save Billing Profile', { country: data.country_code })
  }

  useEffect(() => {
    fetchBillingProfile(tenantData.id)
      .then(() => {
        setLoaded(true)
      })
      .catch(() => {
        setLoaded(true)
      })
  }, [tenantData.id, fetchBillingProfile])

  return (
    <Card p={24} sx={{ position: 'relative', minHeight: 800, width: 720 }}>
      <LoadingOverlay visible={!loaded}></LoadingOverlay>
      {loaded && <ProfileForm info={billingProfile} onSubmit={onSubmit} disabled={disabled}></ProfileForm>}
    </Card>
  )
})
