import ContentCopyIcon from '@mui/icons-material/ContentCopy'
import EditIcon from '@mui/icons-material/Edit'
import { Box, IconButton, SxProps, Theme, Typography } from '@mui/material'
import { truncate } from 'lodash'
import { Event, VerifiedEvent, kinds, nip19 } from 'nostr-tools'
import { useEffect, useMemo, useState } from 'react'
import { useSelector } from 'react-redux'
import { Link, useNavigate, useParams } from 'react-router-dom'
import { toast } from 'react-toastify'
import { LoadingSpinner } from '../../components/LoadingSpinner'
import { MetadataController } from '../../controllers'
import { getProfileSettingsRoute } from '../../routes'
import { State } from '../../store/rootReducer'
import { NostrJoiningBlock, ProfileMetadata } from '../../types'
import {
  getNostrJoiningBlockNumber,
  getRoboHashPicture,
  hexToNpub,
  shorten
} from '../../utils'
import styles from './style.module.scss'
import { Container } from '../../components/Container'
import { Footer } from '../../components/Footer/Footer'

export const ProfilePage = () => {
  const navigate = useNavigate()

  const { npub } = useParams()

  const metadataController = useMemo(() => MetadataController.getInstance(), [])

  const [pubkey, setPubkey] = useState<string>()
  const [nostrJoiningBlock, setNostrJoiningBlock] =
    useState<NostrJoiningBlock | null>(null)
  const [profileMetadata, setProfileMetadata] = useState<ProfileMetadata>()
  const metadataState = useSelector((state: State) => state.metadata)
  const { usersPubkey } = useSelector((state: State) => state.auth)
  const userRobotImage = useSelector((state: State) => state.userRobotImage)

  const [isUsersOwnProfile, setIsUsersOwnProfile] = useState(false)

  const [isLoading, setIsLoading] = useState(true)
  const [loadingSpinnerDesc] = useState('Fetching metadata')

  const profileName =
    pubkey &&
    profileMetadata &&
    truncate(
      profileMetadata.display_name || profileMetadata.name || hexToNpub(pubkey),
      {
        length: 16
      }
    )

  useEffect(() => {
    if (npub) {
      try {
        const hexPubkey = nip19.decode(npub).data as string
        setPubkey(hexPubkey)

        if (hexPubkey === usersPubkey) setIsUsersOwnProfile(true)
      } catch (error) {
        toast.error('Error occurred in decoding npub' + error)
      }
    }
  }, [npub, usersPubkey])

  useEffect(() => {
    if (pubkey) {
      getNostrJoiningBlockNumber(pubkey)
        .then((res) => {
          setNostrJoiningBlock(res)
        })
        .catch((err) => {
          // todo: handle error
          console.log('err :>> ', err)
        })
    }

    if (isUsersOwnProfile && metadataState) {
      const metadataContent = metadataController.extractProfileMetadataContent(
        metadataState as VerifiedEvent
      )
      if (metadataContent) {
        setProfileMetadata(metadataContent)
        setIsLoading(false)
      }

      return
    }

    if (pubkey) {
      const getMetadata = async (pubkey: string) => {
        const handleMetadataEvent = (event: Event) => {
          const metadataContent =
            metadataController.extractProfileMetadataContent(event)
          if (metadataContent) {
            setProfileMetadata(metadataContent)
          }
        }

        metadataController.on(pubkey, (kind: number, event: Event) => {
          if (kind === kinds.Metadata) {
            handleMetadataEvent(event)
          }
        })

        const metadataEvent = await metadataController
          .findMetadata(pubkey)
          .catch((err) => {
            toast.error(err)
            return null
          })

        if (metadataEvent) handleMetadataEvent(metadataEvent)

        setIsLoading(false)
      }

      getMetadata(pubkey)
    }
  }, [isUsersOwnProfile, metadataState, pubkey, metadataController])

  /**
   * Rendering text with button which copies the provided text
   * @param text to be visible
   * @param sx props (MUI) to customize style
   * @returns HTML rendered text
   */
  const textElementWithCopyIcon = (
    text: string,
    sx?: SxProps<Theme>,
    shortenOffset?: number
  ) => {
    const onClick = () => {
      navigator.clipboard.writeText(text)

      toast.success('Copied to clipboard', {
        autoClose: 1000,
        hideProgressBar: true
      })
    }

    return (
      <Typography variant="caption" sx={sx} className={styles.npubNipItem}>
        <span onClick={onClick}>{shorten(text, shortenOffset)}</span>
        <ContentCopyIcon onClick={onClick} className={styles.copyIcon} />
      </Typography>
    )
  }

  /**
   * Handles the logic for Image URL.
   * If no picture in kind 0 found - use robohash avatar
   *
   * @returns robohash image url
   */
  const getProfileImage = (metadata: ProfileMetadata) => {
    if (!metadata) return ''

    if (!isUsersOwnProfile) {
      return metadata.picture || getRoboHashPicture(npub!)
    }

    // userRobotImage is used only when visiting own profile
    // while kind 0 picture is not set
    return metadata.picture || userRobotImage || getRoboHashPicture(npub!)
  }

  return (
    <>
      {isLoading && <LoadingSpinner desc={loadingSpinnerDesc} />}
      {pubkey && (
        <Container className={styles.container}>
          <Box
            className={`${styles.banner} ${!profileMetadata || !profileMetadata.banner ? styles.noImage : ''}`}
          >
            {profileMetadata && profileMetadata.banner ? (
              <img
                src={profileMetadata.banner}
                alt={`banner image for ${profileName}`}
              />
            ) : (
              ''
            )}
          </Box>

          <Box className={styles.belowBanner}>
            <Box className={styles.upper}>
              <Box className={styles.left}>
                <div
                  style={{
                    borderWidth: '2px',
                    borderStyle: pubkey ? 'solid' : 'none',
                    borderColor: `#${pubkey?.substring(0, 6)}`
                  }}
                  className={styles.imageWrapper}
                >
                  <img
                    className={styles['image-placeholder']}
                    src={getProfileImage(profileMetadata!)}
                    alt={profileName}
                  />
                </div>
              </Box>
              <Box className={styles.middle}>
                <Typography
                  component={Link}
                  to={`https://njump.me/${nostrJoiningBlock?.encodedEventPointer || ''}`}
                  target="_blank"
                  className={`${styles.nostrSince} ${styles.link}`}
                  variant="caption"
                >
                  {nostrJoiningBlock
                    ? `On nostr since ${nostrJoiningBlock.block.toLocaleString()}`
                    : 'On nostr since: unknown'}
                </Typography>
              </Box>
              <Box className={styles.right}>
                {isUsersOwnProfile && (
                  <IconButton
                    onClick={() => navigate(getProfileSettingsRoute(pubkey))}
                  >
                    <EditIcon />
                  </IconButton>
                )}
              </Box>
            </Box>
            <Box className={styles.head}>
              <Box sx={{ lineHeight: 1 }} className={styles.npubNip}>
                <Box
                  sx={{
                    display: 'flex'
                  }}
                >
                  {profileMetadata && (
                    <Typography
                      sx={{ margin: '5px 0 5px 0' }}
                      variant="h6"
                      className={styles.bold}
                    >
                      {profileName}
                    </Typography>
                  )}
                </Box>
                <Box>
                  {textElementWithCopyIcon(
                    hexToNpub(pubkey) || '',
                    undefined,
                    15
                  )}
                </Box>
                <Box>
                  {profileMetadata?.nip05 &&
                    textElementWithCopyIcon(
                      profileMetadata.nip05,
                      undefined,
                      15
                    )}
                </Box>
                <Box>
                  {profileMetadata?.lud16 &&
                    textElementWithCopyIcon(
                      profileMetadata.lud16,
                      undefined,
                      15
                    )}
                </Box>
              </Box>

              <Box>
                {profileMetadata?.website && (
                  <Typography
                    sx={{ marginTop: '10px' }}
                    variant="caption"
                    component={Link}
                    to={profileMetadata.website}
                    target="_blank"
                    className={`${styles.website} ${styles.link} ${styles.captionWrapper}`}
                  >
                    {profileMetadata.website}
                  </Typography>
                )}
              </Box>
            </Box>
            <Box>
              {profileMetadata?.about && (
                <Typography mt={1} className={styles.about}>
                  {profileMetadata.about}
                </Typography>
              )}
            </Box>
          </Box>
        </Container>
      )}
      <Footer />
    </>
  )
}
