import { Alert, Box, Group, Image, Typography } from '@tidbcloud/uikit'
import { FormTextInput, Form } from '@tidbcloud/uikit/biz'
import React, { useMemo, useState } from 'react'
import { Link } from 'react-router-dom'

import { CentralAcceptInvitationReq } from 'dbaas/services'
import auth, { databaseConnection } from 'dbaas/services/auth'
import { setSSOSource } from 'dbaas/stores/localStorage'
import useSessionStorage from 'dbaas/utils/useSessionStorage'

import { AcceptServices, MSPAgreement } from '../../Common/AcceptServices'
import { useMSPCustomer } from '../../Common/MSP'
import { PageShell } from '../../Common/Shell'
import { getEmail } from '../../utils'
import SSOLogin from '../components/SSOLogin'
import { INVITE_CALLBACK_URI } from '../constants'

type ITenantFormValues = Pick<CentralAcceptInvitationReq, 'email'> & { password: string }

const TenantFields = React.memo(({ email, services }: { email: string; services?: React.ReactNode }) => {
  return (
    <>
      {/* Ensure users cannot edit the email field */}
      <FormTextInput name="email" placeholder="Work Email" required readOnly value={email} mb={16} />
      <FormTextInput
        type="password"
        name="password"
        placeholder="Password"
        autoComplete="current-password"
        rules={{
          required: 'Required'
        }}
        mb={16}
      />
      {!!services ? services : <AcceptServices />}
    </>
  )
})

const SignIn: React.FC<React.PropsWithChildren<unknown>> = () => {
  const search = window.location.search
  const urlParams = useMemo(() => new URLSearchParams(search), [search])
  const email = getEmail(urlParams.get('email') || '') // invited user email
  const orgId = urlParams.get('org_id') || '' //invite user from a exist tenant
  const orgName = urlParams.get('org_name') // invite organization name
  const [loading, setLoading] = useState(false)

  const [, setInviteUser] = useSessionStorage<
    Pick<CentralAcceptInvitationReq, 'org_id' | 'email'> & { invite_link: string; connection: string; search: string }
  >('invite_user')

  const { isMSPCustomer, logo_url, advertisings, disclaimers } = useMSPCustomer(urlParams.get('msp') || '')

  const beforeSSOAction = (connectionType: string) => {
    setInviteUser({
      email,
      org_id: orgId,
      invite_link: window.location.pathname + search,
      connection: connectionType,
      search
    })
    setSSOSource('invite_signin')
  }

  const loginToAccount = async (data: ITenantFormValues) => {
    setInviteUser({
      email,
      org_id: orgId,
      invite_link: window.location.pathname + search,
      connection: databaseConnection,
      search
    })
    setLoading(true)

    return new Promise<any>((_resolve, reject) => {
      return auth.auth0.login(
        {
          realm: databaseConnection,
          email,
          password: data.password,
          redirectUri: INVITE_CALLBACK_URI
        },
        function (err) {
          const errMsg = err?.description || ''
          setLoading(false)
          reject(new Error(errMsg))
        }
      )
    })
  }

  const defaultTenant = useMemo(
    () => ({
      email,
      password: ''
    }),
    [email]
  )

  return (
    <PageShell
      extra={!!logo_url ? <Image src={logo_url} height={40} fit="contain" sx={{ maxWidth: 4 * 40 }} /> : undefined}
      slogans={!!advertisings?.length ? advertisings : undefined}
    >
      <Box w={360}>
        <div>
          <Alert>
            You have been invited to join{' '}
            {orgName ? (
              <>
                the <b>{orgName}</b> organization
              </>
            ) : (
              'TiDB Cloud'
            )}
            . To accept the invitation, please sign in.
          </Alert>
          <Group align="baseline" my={16} justify="space-between">
            <Typography variant="headline-md">Sign In</Typography>
            <Typography variant="body-lg">
              Don't have an account?{' '}
              <Link className="link" to="/signup" data-mp-event="Sign Up Link Clicked" data-mp-source="Invite">
                Sign Up
              </Link>
            </Typography>
          </Group>
        </div>

        <div>
          <SSOLogin action="sign-in" beforeAction={beforeSSOAction} />
          <Form<ITenantFormValues>
            w={360}
            m="0 auto"
            layoutProps={{ gap: 0 }}
            onSubmit={loginToAccount}
            defaultValues={defaultTenant}
            actionsProps={{
              mt: 16,
              confirmText: 'Join',
              cancelProps: {
                display: 'none'
              },
              confirmProps: {
                'data-mp-event': 'mp-join-1691461016295',
                loading,
                w: '100%',
                h: 40
              }
            }}
          >
            <TenantFields
              email={email}
              services={isMSPCustomer ? <MSPAgreement agreement={disclaimers} /> : undefined}
            />
          </Form>
        </div>

        <Typography variant="body-lg" mt={8}>
          <Box
            component={Link}
            to="/forgot_password"
            data-mp-event="Forgot Password Link Clicked"
            data-mp-source="Invite"
            mr={32}
          >
            Forgot password?
          </Box>
          Questions?{' '}
          <a
            href="https://en.pingcap.com/contact-us/"
            target="_blank"
            rel="noreferrer"
            data-mp-event="Contact Us Link Clicked"
            data-mp-source="Invite"
          >
            Contact us
          </a>
          .
        </Typography>
      </Box>
    </PageShell>
  )
}

export default SignIn
