import React, {useState} from 'react'
import {ActivityIndicator, SafeAreaView, StyleSheet, View} from 'react-native'
import {ScrollView, TextInput} from './util'
import {observer} from 'mobx-react-lite'
import {Text} from '../util/text/Text'
import {Button} from '../util/forms/Button'
import {ErrorMessage} from '../util/error/ErrorMessage'
import * as Toast from '../util/Toast'
import {useStores} from 'state/index'
import {s, colors} from 'lib/styles'
import {usePalette} from 'lib/hooks/usePalette'
import {isWeb} from 'platform/detection'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {cleanError} from 'lib/strings/errors'
import {Trans, msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useModalControls} from '#/state/modals'

enum Stages {
  InputEmail,
  ConfirmCode,
  Done,
}

export const snapPoints = ['90%']

export const Component = observer(function Component({}: {}) {
  const pal = usePalette('default')
  const store = useStores()
  const {_} = useLingui()
  const [stage, setStage] = useState<Stages>(Stages.InputEmail)
  const [email, setEmail] = useState<string>(
    store.session.currentSession?.email || '',
  )
  const [confirmationCode, setConfirmationCode] = useState<string>('')
  const [isProcessing, setIsProcessing] = useState<boolean>(false)
  const [error, setError] = useState<string>('')
  const {isMobile} = useWebMediaQueries()
  const {openModal, closeModal} = useModalControls()

  const onRequestChange = async () => {
    if (email === store.session.currentSession?.email) {
      setError('Enter your new email above')
      return
    }
    setError('')
    setIsProcessing(true)
    try {
      const res = await store.agent.com.atproto.server.requestEmailUpdate()
      if (res.data.tokenRequired) {
        setStage(Stages.ConfirmCode)
      } else {
        await store.agent.com.atproto.server.updateEmail({email: email.trim()})
        store.session.updateLocalAccountData({
          email: email.trim(),
          emailConfirmed: false,
        })
        Toast.show('Email updated')
        setStage(Stages.Done)
      }
    } catch (e) {
      let err = cleanError(String(e))
      // TEMP
      // while rollout is occuring, we're giving a temporary error message
      // you can remove this any time after Oct2023
      // -prf
      if (err === 'email must be confirmed (temporary)') {
        err = _(
          msg`Please confirm your email before changing it. This is a temporary requirement while email-updating tools are added, and it will soon be removed.`,
        )
      }
      setError(err)
    } finally {
      setIsProcessing(false)
    }
  }

  const onConfirm = async () => {
    setError('')
    setIsProcessing(true)
    try {
      await store.agent.com.atproto.server.updateEmail({
        email: email.trim(),
        token: confirmationCode.trim(),
      })
      store.session.updateLocalAccountData({
        email: email.trim(),
        emailConfirmed: false,
      })
      Toast.show('Email updated')
      setStage(Stages.Done)
    } catch (e) {
      setError(cleanError(String(e)))
    } finally {
      setIsProcessing(false)
    }
  }

  const onVerify = async () => {
    closeModal()
    openModal({name: 'verify-email'})
  }

  return (
    <SafeAreaView style={[pal.view, s.flex1]}>
      <ScrollView
        testID="changeEmailModal"
        style={[s.flex1, isMobile && {paddingHorizontal: 18}]}>
        <View style={styles.titleSection}>
          <Text type="title-lg" style={[pal.text, styles.title]}>
            {stage === Stages.InputEmail ? _(msg`Change Your Email`) : ''}
            {stage === Stages.ConfirmCode ? _(msg`Security Step Required`) : ''}
            {stage === Stages.Done ? _(msg`Email Updated`) : ''}
          </Text>
        </View>

        <Text type="lg" style={[pal.textLight, {marginBottom: 10}]}>
          {stage === Stages.InputEmail ? (
            <Trans>Enter your new email address below.</Trans>
          ) : stage === Stages.ConfirmCode ? (
            <Trans>
              An email has been sent to your previous address,{' '}
              {store.session.currentSession?.email || ''}. It includes a
              confirmation code which you can enter below.
            </Trans>
          ) : (
            <Trans>
              Your email has been updated but not verified. As a next step,
              please verify your new email.
            </Trans>
          )}
        </Text>

        {stage === Stages.InputEmail && (
          <TextInput
            testID="emailInput"
            style={[styles.textInput, pal.border, pal.text]}
            placeholder="alice@mail.com"
            placeholderTextColor={pal.colors.textLight}
            value={email}
            onChangeText={setEmail}
            accessible={true}
            accessibilityLabel={_(msg`Email`)}
            accessibilityHint=""
            autoCapitalize="none"
            autoComplete="email"
            autoCorrect={false}
          />
        )}
        {stage === Stages.ConfirmCode && (
          <TextInput
            testID="confirmCodeInput"
            style={[styles.textInput, pal.border, pal.text]}
            placeholder="XXXXX-XXXXX"
            placeholderTextColor={pal.colors.textLight}
            value={confirmationCode}
            onChangeText={setConfirmationCode}
            accessible={true}
            accessibilityLabel={_(msg`Confirmation code`)}
            accessibilityHint=""
            autoCapitalize="none"
            autoComplete="off"
            autoCorrect={false}
          />
        )}

        {error ? (
          <ErrorMessage message={error} style={styles.error} />
        ) : undefined}

        <View style={[styles.btnContainer]}>
          {isProcessing ? (
            <View style={styles.btn}>
              <ActivityIndicator color="#fff" />
            </View>
          ) : (
            <View style={{gap: 6}}>
              {stage === Stages.InputEmail && (
                <Button
                  testID="requestChangeBtn"
                  type="primary"
                  onPress={onRequestChange}
                  accessibilityLabel={_(msg`Request Change`)}
                  accessibilityHint=""
                  label={_(msg`Request Change`)}
                  labelContainerStyle={{justifyContent: 'center', padding: 4}}
                  labelStyle={[s.f18]}
                />
              )}
              {stage === Stages.ConfirmCode && (
                <Button
                  testID="confirmBtn"
                  type="primary"
                  onPress={onConfirm}
                  accessibilityLabel={_(msg`Confirm Change`)}
                  accessibilityHint=""
                  label={_(msg`Confirm Change`)}
                  labelContainerStyle={{justifyContent: 'center', padding: 4}}
                  labelStyle={[s.f18]}
                />
              )}
              {stage === Stages.Done && (
                <Button
                  testID="verifyBtn"
                  type="primary"
                  onPress={onVerify}
                  accessibilityLabel={_(msg`Verify New Email`)}
                  accessibilityHint=""
                  label={_(msg`Verify New Email`)}
                  labelContainerStyle={{justifyContent: 'center', padding: 4}}
                  labelStyle={[s.f18]}
                />
              )}
              <Button
                testID="cancelBtn"
                type="default"
                onPress={() => closeModal()}
                accessibilityLabel={_(msg`Cancel`)}
                accessibilityHint=""
                label={_(msg`Cancel`)}
                labelContainerStyle={{justifyContent: 'center', padding: 4}}
                labelStyle={[s.f18]}
              />
            </View>
          )}
        </View>
      </ScrollView>
    </SafeAreaView>
  )
})

const styles = StyleSheet.create({
  titleSection: {
    paddingTop: isWeb ? 0 : 4,
    paddingBottom: isWeb ? 14 : 10,
  },
  title: {
    textAlign: 'center',
    fontWeight: '600',
    marginBottom: 5,
  },
  error: {
    borderRadius: 6,
    marginTop: 10,
  },
  emailContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 6,
    borderWidth: 1,
    borderRadius: 6,
    paddingHorizontal: 14,
    paddingVertical: 12,
  },
  textInput: {
    borderWidth: 1,
    borderRadius: 6,
    paddingHorizontal: 14,
    paddingVertical: 10,
    fontSize: 16,
  },
  btn: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
    borderRadius: 32,
    padding: 14,
    backgroundColor: colors.blue3,
  },
  btnContainer: {
    paddingTop: 20,
  },
})
