import {memo, useMemo, useState} from 'react'
import {View} from 'react-native'
import {
  type AppBskyActorDefs,
  moderateProfile,
  type ModerationDecision,
  type ModerationOpts,
  type RichText as RichTextAPI,
} from '@atproto/api'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'

import {useHaptics} from '#/lib/haptics'
import {sanitizeDisplayName} from '#/lib/strings/display-names'
import {sanitizeHandle} from '#/lib/strings/handles'
import {formatJoinDate} from '#/lib/strings/time'
import {
  sanitizeWebsiteForDisplay,
  sanitizeWebsiteForLink,
} from '#/lib/strings/website'
import {logger} from '#/logger'
import {type Shadow, useProfileShadow} from '#/state/cache/profile-shadow'
import {useDisableFollowedByMetrics} from '#/state/preferences/disable-followed-by-metrics'
import {
  useProfileBlockMutationQueue,
  useProfileFollowMutationQueue,
} from '#/state/queries/profile'
import {useRequireAuth, useSession} from '#/state/session'
import {ProfileMenu} from '#/view/com/profile/ProfileMenu'
import {atoms as a, platform, tokens, useBreakpoints, useTheme} from '#/alf'
import {SubscribeProfileButton} from '#/components/activity-notifications/SubscribeProfileButton'
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import {DebugFieldDisplay} from '#/components/DebugFieldDisplay'
import {useDialogControl} from '#/components/Dialog'
import {MessageProfileButton} from '#/components/dms/MessageProfileButton'
import {CalendarDays_Stroke2_Corner0_Rounded as CalendarDays} from '#/components/icons/CalendarDays'
import {Globe_Stroke2_Corner0_Rounded as Globe} from '#/components/icons/Globe'
import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus'
import {
  KnownFollowers,
  shouldShowKnownFollowers,
} from '#/components/KnownFollowers'
import {Link} from '#/components/Link'
import {PdsBadge} from '#/components/PdsBadge'
import * as Prompt from '#/components/Prompt'
import {RichText} from '#/components/RichText'
import * as Toast from '#/components/Toast'
import {Text} from '#/components/Typography'
import {VerificationCheckButton} from '#/components/verification/VerificationCheckButton'
import {IS_IOS} from '#/env'
import {useActorStatus} from '#/features/liveNow'
import {GermButton} from '../components/GermButton'
import {EditProfileDialog} from './EditProfileDialog'
import {ProfileHeaderHandle} from './Handle'
import {ProfileHeaderMetrics} from './Metrics'
import {ProfileHeaderShell} from './Shell'
import {ProfileHeaderSuggestedFollows} from './SuggestedFollows'

interface Props {
  profile: AppBskyActorDefs.ProfileViewDetailed
  descriptionRT: RichTextAPI | null
  moderationOpts: ModerationOpts
  hideBackButton?: boolean
  isPlaceholderProfile?: boolean
}

let ProfileHeaderStandard = ({
  profile: profileUnshadowed,
  descriptionRT,
  moderationOpts,
  hideBackButton = false,
  isPlaceholderProfile,
}: Props): React.ReactNode => {
  const t = useTheme()
  const {gtMobile} = useBreakpoints()
  const profile =
    useProfileShadow<AppBskyActorDefs.ProfileViewDetailed>(profileUnshadowed)
  const {currentAccount} = useSession()
  const {_} = useLingui()
  const moderation = useMemo(
    () => moderateProfile(profile, moderationOpts),
    [profile, moderationOpts],
  )
  const [, queueUnblock] = useProfileBlockMutationQueue(profile)
  const unblockPromptControl = Prompt.usePromptControl()
  const [showSuggestedFollows, setShowSuggestedFollows] = useState(false)
  const isBlockedUser =
    profile.viewer?.blocking ||
    profile.viewer?.blockedBy ||
    profile.viewer?.blockingByList

  const website = profile.website
  const websiteFormatted = sanitizeWebsiteForDisplay(website ?? '')

  const dateJoined = useMemo(() => {
    if (!profile.createdAt) return ''
    return formatJoinDate(profile.createdAt)
  }, [profile.createdAt])

  const unblockAccount = async () => {
    try {
      await queueUnblock()
      Toast.show(_(msg({message: 'Account unblocked', context: 'toast'})))
    } catch (e: any) {
      if (e?.name !== 'AbortError') {
        logger.error('Failed to unblock account', {message: e})
        Toast.show(_(msg`There was an issue! ${e.toString()}`), {type: 'error'})
      }
    }
  }

  const isMe = currentAccount?.did === profile.did

  const {isActive: live} = useActorStatus(profile)

  // disable metrics
  const disableFollowedByMetrics = useDisableFollowedByMetrics()

  return (
    <>
      <ProfileHeaderShell
        profile={profile}
        moderation={moderation}
        hideBackButton={hideBackButton}
        isPlaceholderProfile={isPlaceholderProfile}>
        <View
          style={[a.px_lg, a.pt_md, a.pb_sm, a.overflow_hidden]}
          pointerEvents={IS_IOS ? 'auto' : 'box-none'}>
          <View
            style={[
              {paddingLeft: 90},
              a.flex_row,
              a.align_center,
              a.justify_end,
              a.gap_xs,
              a.pb_sm,
              a.flex_wrap,
            ]}
            pointerEvents={IS_IOS ? 'auto' : 'box-none'}>
            <HeaderStandardButtons
              profile={profile}
              moderation={moderation}
              moderationOpts={moderationOpts}
              onFollow={() => setShowSuggestedFollows(true)}
              onUnfollow={() => setShowSuggestedFollows(false)}
            />
          </View>
          <View
            style={[a.flex_col, a.gap_xs, a.pb_md, live ? a.pt_sm : a.pt_2xs]}>
            <View style={[a.flex_row, a.align_center, a.gap_xs, a.flex_1]}>
              <Text
                emoji
                testID="profileHeaderDisplayName"
                style={[
                  t.atoms.text,
                  gtMobile ? a.text_4xl : a.text_3xl,
                  a.self_start,
                  a.font_bold,
                  a.leading_tight,
                ]}>
                {sanitizeDisplayName(
                  profile.displayName || sanitizeHandle(profile.handle),
                  moderation.ui('displayName'),
                )}
                <View
                  style={[
                    a.pl_xs,
                    a.flex_row,
                    a.gap_2xs,
                    a.align_center,
                    {marginTop: platform({ios: 2})},
                  ]}>
                  <PdsBadge did={profile.did} size="lg" />
                  <VerificationCheckButton profile={profile} size="lg" />
                </View>
              </Text>
            </View>
            <ProfileHeaderHandle profile={profile} />
          </View>
          {!isPlaceholderProfile && !isBlockedUser && (
            <View style={a.gap_md}>
              <ProfileHeaderMetrics profile={profile} />
              {descriptionRT && !moderation.ui('profileView').blur ? (
                <View pointerEvents="auto">
                  <RichText
                    testID="profileHeaderDescription"
                    style={[a.text_md]}
                    numberOfLines={15}
                    selectable
                    value={descriptionRT}
                    enableTags
                    authorHandle={profile.handle}
                  />
                </View>
              ) : undefined}

              {profile.associated?.germ && (
                <GermButton germ={profile.associated.germ} profile={profile} />
              )}

              {!isMe &&
                !disableFollowedByMetrics &&
                !isBlockedUser &&
                shouldShowKnownFollowers(profile.viewer?.knownFollowers) && (
                  <View style={[a.flex_row, a.align_center, a.gap_sm]}>
                    <KnownFollowers
                      profile={profile}
                      moderationOpts={moderationOpts}
                    />
                  </View>
                )}
            </View>
          )}

          <View style={[a.flex_row, a.flex_wrap, {gap: 10}, a.pt_md]}>
            {websiteFormatted && (
              <Link
                to={sanitizeWebsiteForLink(website ?? '')}
                label={_(msg({message: `Visit ${websiteFormatted}`}))}
                style={[a.flex_row, a.align_center, a.gap_xs]}>
                <Globe
                  width={tokens.space.lg}
                  style={{color: t.palette.primary_500}}
                />
                <Text style={[{color: t.palette.primary_500}]}>
                  {websiteFormatted}
                </Text>
              </Link>
            )}
            <View style={[a.flex_row, a.align_center, a.gap_xs]}>
              <CalendarDays
                width={tokens.space.lg}
                style={{color: t.atoms.text_contrast_medium.color}}
              />
              <Text style={[t.atoms.text_contrast_medium]}>
                <Trans>Joined {dateJoined}</Trans>
              </Text>
            </View>
          </View>

          <DebugFieldDisplay subject={profile} />
        </View>

        <Prompt.Basic
          control={unblockPromptControl}
          title={_(msg`Unblock Account?`)}
          description={_(
            msg`The account will be able to interact with you after unblocking.`,
          )}
          onConfirm={unblockAccount}
          confirmButtonCta={
            profile.viewer?.blocking ? _(msg`Unblock`) : _(msg`Block`)
          }
          confirmButtonColor="negative"
        />
      </ProfileHeaderShell>

      <ProfileHeaderSuggestedFollows
        isExpanded={showSuggestedFollows}
        actorDid={profile.did}
      />
    </>
  )
}

ProfileHeaderStandard = memo(ProfileHeaderStandard)
export {ProfileHeaderStandard}

export function HeaderStandardButtons({
  profile,
  moderation,
  moderationOpts,
  onFollow,
  onUnfollow,
  minimal,
}: {
  profile: Shadow<AppBskyActorDefs.ProfileViewDetailed>
  moderation: ModerationDecision
  moderationOpts: ModerationOpts
  onFollow?: () => void
  onUnfollow?: () => void
  minimal?: boolean
}) {
  const {_} = useLingui()
  const {hasSession, currentAccount} = useSession()
  const playHaptic = useHaptics()
  const requireAuth = useRequireAuth()
  const [queueFollow, queueUnfollow] = useProfileFollowMutationQueue(
    profile,
    'ProfileHeader',
  )
  const [, queueUnblock] = useProfileBlockMutationQueue(profile)
  const editProfileControl = useDialogControl()
  const unblockPromptControl = Prompt.usePromptControl()

  const isMe = currentAccount?.did === profile.did

  const onPressFollow = () => {
    playHaptic()
    requireAuth(async () => {
      try {
        await queueFollow()
        onFollow?.()
        Toast.show(
          _(
            msg`Following ${sanitizeDisplayName(
              profile.displayName || profile.handle,
              moderation.ui('displayName'),
            )}`,
          ),
        )
      } catch (e: any) {
        if (e?.name !== 'AbortError') {
          logger.error('Failed to follow', {message: String(e)})
          Toast.show(_(msg`There was an issue! ${e.toString()}`), {
            type: 'error',
          })
        }
      }
    })
  }

  const onPressUnfollow = () => {
    playHaptic()
    requireAuth(async () => {
      try {
        await queueUnfollow()
        onUnfollow?.()
        Toast.show(
          _(
            msg`No longer following ${sanitizeDisplayName(
              profile.displayName || profile.handle,
              moderation.ui('displayName'),
            )}`,
          ),
          {type: 'default'},
        )
      } catch (e: any) {
        if (e?.name !== 'AbortError') {
          logger.error('Failed to unfollow', {message: String(e)})
          Toast.show(_(msg`There was an issue! ${e.toString()}`), {
            type: 'error',
          })
        }
      }
    })
  }

  const unblockAccount = async () => {
    try {
      await queueUnblock()
      Toast.show(_(msg({message: 'Account unblocked', context: 'toast'})))
    } catch (e: any) {
      if (e?.name !== 'AbortError') {
        logger.error('Failed to unblock account', {message: e})
        Toast.show(_(msg`There was an issue! ${e.toString()}`), {type: 'error'})
      }
    }
  }

  const subscriptionsAllowed = useMemo(() => {
    switch (profile.associated?.activitySubscription?.allowSubscriptions) {
      case 'followers':
      case undefined:
        return !!profile.viewer?.following
      case 'mutuals':
        return !!profile.viewer?.following && !!profile.viewer.followedBy
      case 'none':
      default:
        return false
    }
  }, [profile])

  return (
    <>
      {isMe ? (
        <>
          <Button
            testID="profileHeaderEditProfileButton"
            size="small"
            color="secondary"
            onPress={() => {
              playHaptic('Light')
              editProfileControl.open()
            }}
            label={_(msg`Edit profile`)}>
            <ButtonText>
              <Trans>Edit Profile</Trans>
            </ButtonText>
          </Button>
          <EditProfileDialog profile={profile} control={editProfileControl} />
        </>
      ) : profile.viewer?.blocking ? (
        profile.viewer?.blockingByList ? null : (
          <Button
            testID="unblockBtn"
            size="small"
            color="secondary"
            label={_(msg`Unblock`)}
            disabled={!hasSession}
            onPress={() => unblockPromptControl.open()}>
            <ButtonText>
              <Trans context="action">Unblock</Trans>
            </ButtonText>
          </Button>
        )
      ) : !profile.viewer?.blockedBy ? (
        <>
          {hasSession && (!minimal || profile.viewer?.following) && (
            <>
              {subscriptionsAllowed && (
                <SubscribeProfileButton
                  profile={profile}
                  moderationOpts={moderationOpts}
                  disableHint={minimal}
                />
              )}

              <MessageProfileButton profile={profile} />
            </>
          )}

          {(!minimal || !profile.viewer?.following) && (
            <Button
              testID={profile.viewer?.following ? 'unfollowBtn' : 'followBtn'}
              size="small"
              color={profile.viewer?.following ? 'secondary' : 'primary'}
              label={
                profile.viewer?.following
                  ? _(msg`Unfollow ${profile.handle}`)
                  : _(msg`Follow ${profile.handle}`)
              }
              onPress={
                profile.viewer?.following ? onPressUnfollow : onPressFollow
              }>
              {!profile.viewer?.following && <ButtonIcon icon={Plus} />}
              <ButtonText>
                {profile.viewer?.following ? (
                  profile.viewer?.followedBy ? (
                    <Trans>Mutuals</Trans>
                  ) : (
                    <Trans>Following</Trans>
                  )
                ) : profile.viewer?.followedBy ? (
                  <Trans>Follow back</Trans>
                ) : (
                  <Trans>Follow</Trans>
                )}
              </ButtonText>
            </Button>
          )}
        </>
      ) : null}
      <ProfileMenu profile={profile} />

      <Prompt.Basic
        control={unblockPromptControl}
        title={_(msg`Unblock Account?`)}
        description={_(
          msg`The account will be able to interact with you after unblocking.`,
        )}
        onConfirm={unblockAccount}
        confirmButtonCta={_(msg`Unblock`)}
        confirmButtonColor="negative"
      />
    </>
  )
}
