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

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

  const { npub } = useParams()

  const metadataController = useMemo(() => new MetadataController(), [])

  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')

  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) {
      metadataController
        .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 metadataEvent = await metadataController
          .findMetadata(pubkey)
          .catch((err) => {
            toast.error(err)
            return null
          })

        if (metadataEvent) {
          const metadataContent =
            metadataController.extractProfileMetadataContent(metadataEvent)
          if (metadataContent) {
            setProfileMetadata(metadataContent)
          }
        }

        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 && (
        <Box className={styles.container}>
          <Box
            className={`${styles.banner} ${!profileMetadata || !profileMetadata.banner ? styles.noImage : ''}`}
          >
            {profileMetadata && profileMetadata.banner ? (
              <img src={profileMetadata.banner} />
            ) : (
              ''
            )}
          </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!)}
                  />
                </div>
              </Box>
              <Box className={styles.middle}>
                <Typography
                  component={Link}
                  to={`https://njump.me/${nostrJoiningBlock?.encodedEventPointer || ''}`}
                  target="_blank"
                  sx={{ color: '#7b7b7b', marginTop: '15px', display: 'block' }}
                  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 className={styles.npubNip}>
                <Box
                  sx={{
                    display: 'flex'
                  }}
                >
                  {profileMetadata && (
                    <Typography
                      sx={{ marginRight: 1 }}
                      variant="h6"
                      className={styles.bold}
                    >
                      {truncate(
                        profileMetadata.display_name ||
                          profileMetadata.name ||
                          hexToNpub(pubkey),
                        {
                          length: 16
                        }
                      )}
                    </Typography>
                  )}
                </Box>
                <Box>
                  {textElementWithCopyIcon(
                    hexToNpub(pubkey) || '',
                    { color: '#5e5e5e' },
                    5
                  )}
                </Box>
                <Box>
                  {profileMetadata?.nip05 &&
                    textElementWithCopyIcon(profileMetadata.nip05, {
                      color: '#5e5e5e'
                    })}
                </Box>
                <Box>
                  {profileMetadata?.lud16 &&
                    textElementWithCopyIcon(profileMetadata.lud16, {
                      color: '#5e5e5e'
                    })}
                </Box>
              </Box>

              <Box>
                {profileMetadata?.website && (
                  <Typography
                    sx={{ marginTop: '10px' }}
                    variant="caption"
                    className={`${styles.website} ${styles.captionWrapper}`}
                  >
                    <Typography
                      variant="caption"
                      sx={{ color: '#5e5e5e' }}
                      className={styles.npubNipItem}
                    >
                      {profileMetadata.website}
                    </Typography>
                    <LinkIcon className={styles.captionIcon} />
                  </Typography>
                )}
              </Box>
            </Box>
            <Box>
              {profileMetadata?.about && (
                <Typography mt={1} className={styles.about}>
                  {profileMetadata.about}
                </Typography>
              )}
            </Box>
          </Box>
        </Box>
      )}
    </>
  )
}
