import { Image, Alert, Flex, Typography, Box, Divider } from '@tidbcloud/uikit'
import { Form } from '@tidbcloud/uikit/biz'
import { sha256 } from 'js-sha256'
import React, { Suspense, useState, useEffect } from 'react'
import { useHistory } from 'react-router-dom'

import { log } from 'common/log'
import { HeroComponent } from 'dbaas/components/Measurement'
import PageLoader from 'dbaas/components/Placeholder'
import { CloudProvider, getCloudProviderLabel } from 'dbaas/features/Project'
import { registration } from 'dbaas/services/account'
import { CentralRegistrationReq, RegistrationReqConnectionType } from 'dbaas/services/account/interface'
import auth from 'dbaas/services/auth'
import { getErrorMessage, pickErrorResponse } from 'dbaas/services/errorCodes'
import { removeSignupPlan, setSignupPlan } from 'dbaas/stores/localStorage'
import { isPoC } from 'dbaas/utils/chore'
import {
  clearEmailLakeConnectIntent,
  getLakeConnectIntentFromSearch,
  getLakeConnectTrackingProperties,
  saveEmailLakeConnectIntent
} from 'dbaas/utils/lake-connect'
import { useThirdParty, getThirdPartyVendor, isFromMarketplace } from 'dbaas/utils/marketplace'
import {
  eventTracking,
  getUTMSource,
  MixpanelEvents,
  PRODUCT_TYPES,
  REGISTER_TYPES,
  reportGA,
  reportSignup
} from 'dbaas/utils/tracking'
import TiDBCloudLogo from 'media/logo/tidb-cloud-no-text.svg'

import config from '../../../../config'
import { OrgPlanStatus } from '../../Plans/constant'
import { AcceptServices as CAcceptServices, MSPAgreement } from '../Common/AcceptServices'
import { EmailField, CompanyField, PasswordField, SigninField, NameFields, SignupForm } from '../Common/FormFields'
import { useMSPCustomer } from '../Common/MSP'
import { PageShell } from '../Common/Shell'
import { SSOSignIn } from '../Common/SSO'
import { useVercelParams } from '../Common/Vercel/helpers'
import SignUpCallback from '../SignUpCallback'

// splitting code

export type UserInfoFormValues = CentralRegistrationReq

interface SignupFormProps {
  defaultValues?: UserInfoFormValues
  onSubmit: (data: UserInfoFormValues) => Promise<void>
}

const CSignupForm: React.FC<React.PropsWithChildren<SignupFormProps>> = ({ defaultValues, onSubmit, children }) => {
  const [loading, setLoading] = useState(false)

  const handleSubmit = async (data: UserInfoFormValues) => {
    setLoading(true)
    try {
      await onSubmit(data)
    } catch (e) {
      throw e
    } finally {
      setLoading(false)
    }
  }

  return (
    <Form<UserInfoFormValues>
      onSubmit={handleSubmit}
      formMode="onSubmit"
      defaultValues={defaultValues}
      layoutProps={{ gap: 0 }}
      actionsProps={{
        mt: 16,
        cancelProps: { display: 'none' },
        confirmText: 'Sign Up',
        confirmProps: {
          loading,
          w: '100%',
          h: 40,
          'data-mp-event': 'mp-signup-1691461013710'
        }
      }}
      errorMessageProps={{ mt: 16 }}
    >
      {children}
    </Form>
  )
}

const VercelSignup: React.FC<React.PropsWithChildren<SignupFormProps>> = ({ defaultValues, onSubmit }) => {
  return (
    <Flex mih="100vh" align="center" p="3rem 0" bg="#FFFFFF">
      <Flex
        direction="column"
        align="baseline"
        justify="center"
        p="0 1.65 0 1.65rem"
        sx={{ alignSelf: 'stretch', position: 'relative', width: '43%', textAlign: 'center' }}
      >
        <Image w={48} m="0 auto" src={TiDBCloudLogo} />
        <Box sx={{ alignSelf: 'center' }}>
          <Typography variant="headline-lg" my={24}>
            Sign Up
          </Typography>
          <SigninField accountProvider="vercel" />
        </Box>
      </Flex>
      <Divider orientation="vertical"></Divider>
      <Box w="57%" p="0 2.5rem">
        <SSOSignIn source="signup" mt={0} />
        <CSignupForm defaultValues={defaultValues} onSubmit={onSubmit}>
          <NameFields labeled={false} required={false} />
          <EmailField labeled={false} />
          <PasswordField labeled={false} />
          <CompanyField labeled={false} required={false} />
          <CAcceptServices />
        </CSignupForm>
      </Box>
    </Flex>
  )
}

export default () => {
  const params = new URLSearchParams(window.location.search)
  const status = params.get('status')
  const msp = params.get('msp')
  const { accountProvider, accountToken, freeTrial } = useThirdParty(params)
  const isPoCPlan = isPoC(params.get('plan'))

  const fromMarketplace = isFromMarketplace(params)
  const providerSource = params.get('provider_source') as CloudProvider
  const marketplaceVendor = fromMarketplace ? getCloudProviderLabel(getThirdPartyVendor(accountProvider)) : ''
  const showThirdPartyAccountAlert = fromMarketplace
  const showAliCloudProgramAlert = providerSource === 'alicloud' && !showThirdPartyAccountAlert
  const { fromVercel } = useVercelParams()

  const history = useHistory()
  const [loading, setLoading] = useState(false)

  const { logo_url, advertisings, disclaimers } = useMSPCustomer(msp || '')

  const defaultValues = {
    first_name: params.get('first_name') || '',
    last_name: params.get('last_name') || '',
    email: params.get('email') || '',
    job: '',
    company: '',
    country: '',
    phone_number: '',
    password: '',
    accept_service: false,
    recaptcha_response: ''
  }

  async function handleSubmit(data: UserInfoFormValues) {
    if (loading) {
      return
    }
    setLoading(true)
    try {
      const { first_name, last_name, company, ...payload } = data
      const utm = getUTMSource()
      const submitData: CentralRegistrationReq = {
        ...payload,
        first_name: first_name.trim(),
        last_name: last_name.trim(),
        company: '',
        third_party_account_provider: accountProvider,
        third_party_account_token: accountToken,
        third_party_free_trial: freeTrial,
        connection_type: RegistrationReqConnectionType.EMAIL,
        source: utm
      }
      await registration(submitData, {
        timeout: config.SIGNUP_TIMEOUT,
        isHandleErr: true,
        _warningStatus: [400]
      })

      const lakeConnectIntent = getLakeConnectIntentFromSearch(window.location.search)
      if (lakeConnectIntent && saveEmailLakeConnectIntent(window.location.search)) {
        eventTracking(MixpanelEvents.TidbCloudLake.Create.RequestStarted, {
          entry: 'email_signup',
          ...getLakeConnectTrackingProperties(lakeConnectIntent)
        })
      } else {
        clearEmailLakeConnectIntent()
      }

      //report data to hubspot
      reportSignup({ ...submitData, signupSource: 'signup', productType: PRODUCT_TYPES.DEDICATED })

      // change tracking EventName 'Sign Up' into "SignUp Form Submission", which means the user files out the sign-up form and click "Continue".
      eventTracking('SignUp Form Submission')
      // report marketplace user
      if (fromMarketplace) {
        eventTracking('Became A Billed Customer', {
          source: accountProvider
        })
      }
      history.push(`/signup?status=verifying&email=${encodeURIComponent(data.email || '')}&from=signup`)

      // GA password signup event
      reportGA({
        event: 'registrationComplete'
      })

      reportGA({
        event: 'sign_up_complete',
        user_id: sha256(payload.email),
        sign_up_method: 'form',
        register_type: REGISTER_TYPES.SIGNUP,
        most_recent_referral_url: utm.most_recent_referral_url,
        website_referrer_url: utm.website_referrer_url,
        product_type: PRODUCT_TYPES.DEDICATED
      })

      setLoading(false)
    } catch (e) {
      // tracking "SignUp Form Submission Failed"
      eventTracking('SignUp Form Submission Failed', {
        'Error Message': getErrorMessage(e)
      })
      setLoading(false)

      const { status } = pickErrorResponse(e)

      if (status !== 400) {
        log.error('Signup error', e as Error)
      }
      throw e
    }
  }

  useEffect(() => {
    if (isPoCPlan) {
      setSignupPlan(OrgPlanStatus.POC)
    } else {
      removeSignupPlan()
    }
  }, [])

  // useGAPageView(true)

  // sign up callback page
  if (status) {
    return <SignUpCallback />
  }

  return (
    <Suspense fallback={<PageLoader />}>
      <HeroComponent />
      {fromVercel ? (
        <VercelSignup onSubmit={handleSubmit} defaultValues={{ ...defaultValues }} />
      ) : (
        <PageShell
          extra={!!logo_url ? <Image src={logo_url} height={40} fit="contain" sx={{ maxWidth: 4 * 40 }} /> : undefined}
          slogans={!!advertisings.length ? advertisings : undefined}
          withAdvertisement={!msp}
        >
          <Box
            sx={(theme) => ({
              width: 360,
              margin: '0 auto',
              backgroundColor: '#FFFFFF',
              borderRadius: theme.defaultRadius,

              '@media screen and (max-width: 1024px)': {
                width: '100%',
                padding: '1.75rem 1.5rem'
              }
            })}
          >
            <div>
              {showAliCloudProgramAlert && (
                <Alert title={<>Join the TiDB on Alibaba Cloud Program</>} mb={10}>
                  <span>
                    Already have a TiDB Cloud Account?{' '}
                    <a
                      onClick={(e) => {
                        e.preventDefault()
                        auth.login(window.location.search)
                      }}
                    >
                      Sign In
                    </a>{' '}
                    to join the Alibaba Cloud program.
                  </span>
                </Alert>
              )}
              {showThirdPartyAccountAlert && (
                <Alert title={<>You need a TiDB account to link with your {marketplaceVendor} account.</>} mb={10}>
                  <span>
                    Already have a TiDB Cloud Account?{' '}
                    <a
                      onClick={(e) => {
                        e.preventDefault()
                        auth.login(window.location.search)
                      }}
                    >
                      Sign In
                    </a>{' '}
                    to complete linking your {marketplaceVendor} account to TiDB Cloud.
                  </span>
                </Alert>
              )}
              <Flex align="baseline" justify="space-between">
                <Typography variant="headline-lg" c="carbon.8">
                  Sign Up
                </Typography>
                <SigninField accountProvider={accountProvider || providerSource} />
              </Flex>
              <Box>
                <SignupForm
                  withVendor={!fromMarketplace && !providerSource}
                  onSubmit={handleSubmit}
                  defaultValues={{ ...defaultValues }}
                  ssoProps={{
                    source: 'signup',
                    productType: PRODUCT_TYPES.DEDICATED
                  }}
                  layoutProps={{ gap: 0 }}
                  actionsProps={{
                    mt: 16,
                    cancelProps: { display: 'none' },
                    confirmText: 'Sign Up',
                    confirmProps: {
                      loading,
                      w: '100%',
                      h: 40,
                      'data-mp-event': 'mp-signup-1691461013710'
                    }
                  }}
                  errorMessageProps={{ mt: 16 }}
                >
                  {!!disclaimers ? <MSPAgreement agreement={disclaimers} /> : <CAcceptServices />}
                </SignupForm>
              </Box>
            </div>
          </Box>
        </PageShell>
      )}
    </Suspense>
  )
}
