import {useCallback, useEffect} from 'react'
import {ScrollView, View} from 'react-native'
import {useSafeAreaInsets} from 'react-native-safe-area-context'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'

import {
  SupportCode,
  useCreateSupportLink,
} from '#/lib/hooks/useCreateSupportLink'
import {dateDiff, useGetTimeAgo} from '#/lib/hooks/useTimeAgo'
import {useIsBirthdateUpdateAllowed} from '#/state/birthdate'
import {useSessionApi} from '#/state/session'
import {DeactivateAccountDialog} from '#/screens/Settings/components/DeactivateAccountDialog'
import {DeleteAccountDialog} from '#/screens/Settings/components/DeleteAccountDialog'
import {atoms as a, useBreakpoints, useTheme, web} from '#/alf'
import {Admonition} from '#/components/Admonition'
import {AgeAssuranceAppealDialog} from '#/components/ageAssurance/AgeAssuranceAppealDialog'
import {AgeAssuranceBadge} from '#/components/ageAssurance/AgeAssuranceBadge'
import {AgeAssuranceInitDialog} from '#/components/ageAssurance/AgeAssuranceInitDialog'
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import * as Dialog from '#/components/Dialog'
import {useDialogControl} from '#/components/Dialog'
import {BirthDateSettingsDialog} from '#/components/dialogs/BirthDateSettings'
import {DeviceLocationRequestDialog} from '#/components/dialogs/DeviceLocationRequestDialog'
import {Full as Logo} from '#/components/icons/Logo'
import {ShieldCheck_Stroke2_Corner0_Rounded as ShieldIcon} from '#/components/icons/Shield'
import {createStaticClick, SimpleInlineLinkText} from '#/components/Link'
import {Outlet as PortalOutlet} from '#/components/Portal'
import * as Toast from '#/components/Toast'
import {Text} from '#/components/Typography'
import {BottomSheetOutlet} from '#/../modules/bottom-sheet'
import {useAgeAssurance} from '#/ageAssurance'
import {useAgeAssuranceServerDataContext} from '#/ageAssurance/data'
import {useComputeAgeAssuranceRegionAccess} from '#/ageAssurance/useComputeAgeAssuranceRegionAccess'
import {
  isLegacyBirthdateBug,
  useAgeAssuranceRegionConfig,
} from '#/ageAssurance/util'
import {useAnalytics} from '#/analytics'
import {IS_NATIVE, IS_WEB} from '#/env'
import {useDeviceGeolocationApi} from '#/geolocation'

const textStyles = [a.text_md, a.leading_snug]

export function NoAccessScreen() {
  const t = useTheme()
  const {_} = useLingui()
  const ax = useAnalytics()
  const {gtPhone} = useBreakpoints()
  const insets = useSafeAreaInsets()
  const birthdateControl = useDialogControl()
  const deactivateAccountControl = useDialogControl()
  const deleteAccountControl = useDialogControl()
  const {metadata} = useAgeAssuranceServerDataContext()
  const region = useAgeAssuranceRegionConfig()
  const isBirthdateUpdateAllowed = useIsBirthdateUpdateAllowed()
  const {logoutCurrentAccount} = useSessionApi()
  const createSupportLink = useCreateSupportLink()

  const aa = useAgeAssurance()
  const isBlocked = aa.state.status === aa.Status.Blocked
  const isAARegion = !!region
  const hasDeclaredAge = metadata?.declaredAge !== undefined
  const canUpdateBirthday =
    isBirthdateUpdateAllowed || isLegacyBirthdateBug(metadata?.birthdate || '')

  useEffect(() => {
    // just counting overall hits here
    ax.metric(`blockedGeoOverlay:shown`, {})
    ax.metric(`ageAssurance:noAccessScreen:shown`, {
      accountCreatedAt: metadata?.accountCreatedAt || 'unknown',
      isAARegion,
      hasDeclaredAge,
      canUpdateBirthday,
    })
    // TODO This can be cleaned up with useEffectEvent once we're on 19.2
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  const onPressLogout = useCallback(() => {
    if (IS_WEB) {
      // We're switching accounts, which remounts the entire app.
      // On mobile, this gets us Home, but on the web we also need reset the URL.
      // We can't change the URL via a navigate() call because the navigator
      // itself is about to unmount, and it calls pushState() too late.
      // So we change the URL ourselves. The navigator will pick it up on remount.
      history.pushState(null, '', '/')
    }
    logoutCurrentAccount('AgeAssuranceNoAccessScreen')
  }, [logoutCurrentAccount])

  const orgAdmonition = (
    <Admonition type="tip">
      <Trans>
        For organizational accounts, use the birthdate of the person who is
        responsible for the account.
      </Trans>
    </Admonition>
  )

  const birthdateUpdateText = canUpdateBirthday ? (
    <>
      <Text style={[textStyles]}>
        <Trans>
          If you believe your birthdate is incorrect, you can update it by{' '}
          <SimpleInlineLinkText
            label={_(msg`Click here to update your birthdate`)}
            style={[textStyles]}
            {...createStaticClick(() => {
              ax.metric('ageAssurance:noAccessScreen:openBirthdateDialog', {})
              birthdateControl.open()
            })}>
            clicking here
          </SimpleInlineLinkText>
          .
        </Trans>
      </Text>

      {orgAdmonition}
    </>
  ) : (
    <Text style={[textStyles]}>
      <Trans>
        If you believe your birthdate is incorrect, please{' '}
        <SimpleInlineLinkText
          to={createSupportLink({code: SupportCode.AA_BIRTHDATE})}
          label={_(msg`Click here to contact our support team`)}
          style={[textStyles]}>
          contact our support team
        </SimpleInlineLinkText>
        .
      </Trans>
    </Text>
  )

  return (
    <>
      <View style={[a.util_screen_outer, a.flex_1]}>
        <ScrollView
          contentContainerStyle={[
            a.px_2xl,
            {
              paddingTop: IS_WEB
                ? a.p_5xl.padding
                : insets.top + a.p_2xl.padding,
              paddingBottom: 100,
            },
          ]}>
          <View
            style={[
              a.mx_auto,
              a.w_full,
              web({
                maxWidth: 380,
                paddingTop: gtPhone ? '8vh' : undefined,
              }),
              {
                gap: 32,
              },
            ]}>
            <View style={[a.align_start]}>
              <AgeAssuranceBadge />
            </View>

            {hasDeclaredAge ? (
              <>
                {isAARegion ? (
                  <>
                    <View style={[a.gap_lg]}>
                      <Text style={[textStyles]}>
                        <Trans>Hey there!</Trans>
                      </Text>
                      <Text style={[textStyles]}>
                        <Trans>
                          You are accessing Bluesky from a region that legally
                          requires us to verify your age before allowing you to
                          access the app.
                        </Trans>
                      </Text>

                      {!aa.flags.isOverRegionMinAccessAge && (
                        <Text style={[textStyles]}>
                          <Trans>
                            Unfortunately, your declared age indicates that you
                            are not old enough to access Bluesky in your region.
                          </Trans>
                        </Text>
                      )}

                      {!isBlocked && birthdateUpdateText}
                    </View>

                    {aa.flags.isOverRegionMinAccessAge && <AccessSection />}
                  </>
                ) : (
                  <View style={[a.gap_lg]}>
                    <Text style={[textStyles]}>
                      <Trans>
                        Unfortunately, the birthdate you have saved to your
                        profile makes you too young to access Bluesky.
                      </Trans>
                    </Text>

                    {birthdateUpdateText}
                  </View>
                )}
              </>
            ) : (
              <View style={[a.gap_lg]}>
                <Text style={[textStyles]}>
                  <Trans>Hi there!</Trans>
                </Text>
                <Text style={[textStyles]}>
                  <Trans>
                    In order to provide an age-appropriate experience, we need
                    to know your birthdate. This is a one-time thing, and your
                    data will be kept private.
                  </Trans>
                </Text>
                <Text style={[textStyles]}>
                  <Trans>
                    Set your birthdate below and we'll get you back to posting
                    and exploring in no time!
                  </Trans>
                </Text>
                <Button
                  color="primary"
                  size="large"
                  label={_(msg`Click here to update your birthdate`)}
                  onPress={() => birthdateControl.open()}>
                  <ButtonText>
                    <Trans>Add your birthdate</Trans>
                  </ButtonText>
                </Button>

                {orgAdmonition}
              </View>
            )}

            <View style={[a.pt_lg, a.gap_xl, {maxWidth: 280}]}>
              <Logo width={120} textFill={t.atoms.text.color} />
              <Text
                style={[
                  a.text_sm,
                  a.italic,
                  a.leading_snug,
                  t.atoms.text_contrast_medium,
                ]}>
                <Trans>
                  To log out,{' '}
                  <SimpleInlineLinkText
                    label={_(msg`Click here to log out`)}
                    {...createStaticClick(() => {
                      onPressLogout()
                    })}
                    style={[a.italic]}>
                    click here
                  </SimpleInlineLinkText>
                  . Or if you’d prefer, you can{' '}
                  <SimpleInlineLinkText
                    label={_(msg`Click here to delete your account`)}
                    {...createStaticClick(() => {
                      ax.metric(
                        'ageAssurance:noAccessScreen:openDeleteAccountDialog',
                        {},
                      )
                      deleteAccountControl.open()
                    })}
                    style={[a.italic]}>
                    delete your account
                  </SimpleInlineLinkText>
                  .
                </Trans>
              </Text>
            </View>
          </View>
        </ScrollView>
      </View>

      <BirthDateSettingsDialog control={birthdateControl} />
      <DeactivateAccountDialog control={deactivateAccountControl} />
      <DeleteAccountDialog
        control={deleteAccountControl}
        deactivateDialogControl={deactivateAccountControl}
      />

      {/*
       * While this blocking overlay is up, other dialogs in the shell
       * are not mounted, so it _should_ be safe to use these here
       * without fear of other modals showing up.
       */}
      <BottomSheetOutlet />
      <PortalOutlet />
    </>
  )
}

function AccessSection() {
  const t = useTheme()
  const {_, i18n} = useLingui()
  const ax = useAnalytics()
  const control = useDialogControl()
  const appealControl = Dialog.useDialogControl()
  const locationControl = Dialog.useDialogControl()
  const getTimeAgo = useGetTimeAgo()
  const {setDeviceGeolocation} = useDeviceGeolocationApi()
  const computeAgeAssuranceRegionAccess = useComputeAgeAssuranceRegionAccess()

  const aa = useAgeAssurance()
  const {status, lastInitiatedAt} = aa.state
  const isBlocked = status === aa.Status.Blocked
  const hasInitiated = !!lastInitiatedAt
  const timeAgo = lastInitiatedAt
    ? getTimeAgo(lastInitiatedAt, new Date())
    : null
  const diff = lastInitiatedAt
    ? dateDiff(lastInitiatedAt, new Date(), 'down')
    : null

  return (
    <>
      <AgeAssuranceInitDialog control={control} />
      <AgeAssuranceAppealDialog control={appealControl} />

      <View style={[a.gap_xl]}>
        {isBlocked ? (
          <Admonition type="warning">
            <Trans>
              You are currently unable to access Bluesky's Age Assurance flow.
              Please{' '}
              <SimpleInlineLinkText
                label={_(msg`Contact our moderation team`)}
                {...createStaticClick(() => {
                  appealControl.open()
                  ax.metric('ageAssurance:appealDialogOpen', {})
                })}>
                contact our moderation team
              </SimpleInlineLinkText>{' '}
              if you believe this is an error.
            </Trans>
          </Admonition>
        ) : (
          <>
            <View style={[a.gap_md]}>
              <Button
                label={_(msg`Verify now`)}
                size="large"
                color={hasInitiated ? 'secondary' : 'primary'}
                onPress={() => {
                  control.open()
                  ax.metric('ageAssurance:initDialogOpen', {
                    hasInitiatedPreviously: hasInitiated,
                  })
                }}>
                <ButtonIcon icon={ShieldIcon} />
                <ButtonText>
                  {hasInitiated ? (
                    <Trans>Verify again</Trans>
                  ) : (
                    <Trans>Verify now</Trans>
                  )}
                </ButtonText>
              </Button>

              {lastInitiatedAt && timeAgo && diff ? (
                <Text
                  style={[a.text_sm, a.italic, t.atoms.text_contrast_medium]}
                  title={i18n.date(lastInitiatedAt, {
                    dateStyle: 'medium',
                    timeStyle: 'medium',
                  })}>
                  {diff.value === 0 ? (
                    <Trans>Last initiated just now</Trans>
                  ) : (
                    <Trans>Last initiated {timeAgo} ago</Trans>
                  )}
                </Text>
              ) : (
                <Text
                  style={[a.text_sm, a.italic, t.atoms.text_contrast_medium]}>
                  <Trans>Age assurance only takes a few minutes</Trans>
                </Text>
              )}
            </View>
          </>
        )}

        <View style={[a.gap_xs]}>
          {IS_NATIVE && (
            <>
              <Admonition>
                <Trans>
                  Is your location not accurate?{' '}
                  <SimpleInlineLinkText
                    label={_(msg`Update your location`)}
                    {...createStaticClick(() => {
                      locationControl.open()
                    })}>
                    Tap here to update your location with GPS.
                  </SimpleInlineLinkText>{' '}
                </Trans>
              </Admonition>

              <DeviceLocationRequestDialog
                control={locationControl}
                onLocationAcquired={props => {
                  const access = computeAgeAssuranceRegionAccess(
                    props.geolocation,
                  )
                  if (access !== aa.Access.Full) {
                    props.disableDialogAction()
                    props.setDialogError(
                      _(
                        msg`We're sorry, but based on your device's location, you are currently located in a region that requires age assurance.`,
                      ),
                    )
                  } else {
                    props.closeDialog(() => {
                      // set this after close!
                      setDeviceGeolocation(props.geolocation)
                      Toast.show(_(msg`Thanks! You're all set.`), {
                        type: 'success',
                      })
                    })
                  }
                }}
              />
            </>
          )}
        </View>
      </View>
    </>
  )
}
