import { LoadingSpinner } from 'components/LoadingSpinner'
import { ZapButtons, ZapPopUp, ZapPresets, ZapQR } from 'components/Zap'
import { MetadataController, RelayController, ZapController } from 'controllers'
import { useAppSelector, useDidMount } from 'hooks'
import { useCallback, useState } from 'react'
import { toast } from 'react-toastify'
import { ModDetails, PaymentRequest } from 'types'
import { abbreviateNumber, formatNumber, unformatNumber } from 'utils'

type ZapProps = {
  modDetails: ModDetails
}

export const Zap = ({ modDetails }: ZapProps) => {
  const [isOpen, setIsOpen] = useState(false)
  const [hasZapped, setHasZapped] = useState(false)

  const userState = useAppSelector((state) => state.user)

  const [totalZappedAmount, setTotalZappedAmount] = useState(0)

  useDidMount(() => {
    RelayController.getInstance()
      .getTotalZapAmount(
        modDetails.author,
        modDetails.id,
        modDetails.aTag,
        userState.user?.pubkey as string
      )
      .then((res) => {
        setTotalZappedAmount(res.accumulatedZapAmount)
        setHasZapped(res.hasZapped)
      })
      .catch((err) => {
        toast.error(err.message || err)
      })
  })

  return (
    <>
      <div
        id='reactBolt'
        className={`IBMSMSMBSS_Details_Card IBMSMSMBSS_D_CBolt ${
          hasZapped ? 'IBMSMSMBSS_D_CBActive' : ''
        }`}
        onClick={() => setIsOpen(true)}
      >
        <div className='IBMSMSMBSS_Details_CardVisual'>
          <svg
            xmlns='http://www.w3.org/2000/svg'
            viewBox='-64 0 512 512'
            width='1em'
            height='1em'
            fill='currentColor'
            className='IBMSMSMBSS_Details_CardVisualIcon'
          >
            <path d='M240.5 224H352C365.3 224 377.3 232.3 381.1 244.7C386.6 257.2 383.1 271.3 373.1 280.1L117.1 504.1C105.8 513.9 89.27 514.7 77.19 505.9C65.1 497.1 60.7 481.1 66.59 467.4L143.5 288H31.1C18.67 288 6.733 279.7 2.044 267.3C-2.645 254.8 .8944 240.7 10.93 231.9L266.9 7.918C278.2-1.92 294.7-2.669 306.8 6.114C318.9 14.9 323.3 30.87 317.4 44.61L240.5 224z'></path>
          </svg>
        </div>
        <p className='IBMSMSMBSS_Details_CardText'>
          {abbreviateNumber(totalZappedAmount)}
        </p>
        <div className='IBMSMSMBSSCL_CAElementLoadWrapper'>
          <div className='IBMSMSMBSSCL_CAElementLoad'></div>
        </div>
      </div>
      {isOpen && (
        <ZapPopUp
          title='Tip/Zap'
          receiver={modDetails.author}
          eventId={modDetails.id}
          aTag={modDetails.aTag}
          handleClose={() => setIsOpen(false)}
          lastNode={<ZapSite />}
          notCloseAfterZap
          setTotalZapAmount={setTotalZappedAmount}
          setHasZapped={setHasZapped}
        />
      )}
    </>
  )
}

const ZapSite = () => {
  const [isLoading, setIsLoading] = useState(false)
  const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState('')

  const [amount, setAmount] = useState(0)

  const [paymentRequest, setPaymentRequest] = useState<PaymentRequest>()

  const userState = useAppSelector((state) => state.user)

  const handleAmountChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const unformattedValue = unformatNumber(event.target.value)
    setAmount(unformattedValue)
  }

  const handleClose = useCallback(() => {
    setPaymentRequest(undefined)
    setIsLoading(false)
  }, [])

  const handleQRExpiry = useCallback(() => {
    setPaymentRequest(undefined)
  }, [])

  const generatePaymentRequest =
    useCallback(async (): Promise<PaymentRequest | null> => {
      let userHexKey: string

      setIsLoading(true)
      setLoadingSpinnerDesc('Getting user pubkey')

      if (userState.auth && userState.user?.pubkey) {
        userHexKey = userState.user.pubkey as string
      } else {
        userHexKey = (await window.nostr?.getPublicKey()) as string
      }

      if (!userHexKey) {
        setIsLoading(false)
        toast.error('Could not get pubkey')
        return null
      }

      setLoadingSpinnerDesc('Getting admin metadata')
      const metadataController = await MetadataController.getInstance()

      const adminMetadata = await metadataController.findAdminMetadata()

      if (!adminMetadata?.lud16) {
        setIsLoading(false)
        toast.error('Lighting address (lud16) is missing in admin metadata!')
        return null
      }

      if (!adminMetadata?.pubkey) {
        setIsLoading(false)
        toast.error('pubkey is missing in admin metadata!')
        return null
      }

      const zapController = ZapController.getInstance()

      setLoadingSpinnerDesc('Creating zap request')
      return await zapController
        .getLightningPaymentRequest(
          adminMetadata.lud16,
          amount,
          adminMetadata.pubkey as string,
          userHexKey
        )
        .catch((err) => {
          toast.error(err.message || err)
          return null
        })
        .finally(() => {
          setIsLoading(false)
        })
    }, [amount, userState])

  const handleSend = useCallback(async () => {
    const pr = await generatePaymentRequest()

    if (!pr) return

    setIsLoading(true)
    setLoadingSpinnerDesc('Sending payment!')

    const zapController = ZapController.getInstance()

    if (await zapController.isWeblnProviderExists()) {
      await zapController
        .sendPayment(pr.pr)
        .then(() => {
          toast.success(`Successfully sent ${amount} sats!`)
          handleClose()
        })
        .catch((err) => {
          toast.error(err.message || err)
        })
    } else {
      toast.warn('Webln is not present. Use QR code to send zap.')
      setPaymentRequest(pr)
    }

    setIsLoading(false)
  }, [amount, handleClose, generatePaymentRequest])

  const handleGenerateQRCode = async () => {
    const pr = await generatePaymentRequest()

    if (!pr) return

    setPaymentRequest(pr)
  }

  return (
    <>
      <div className='inputLabelWrapperMain'>
        <label className='form-label labelMain'>
          Tip DEG Mods too (Optional)
        </label>
        <div className='ZapSplitUserBox'>
          <div className='ZapSplitUserBoxUser'>
            <div
              className='ZapSplitUserBoxUserPic'
              style={{
                background: `url('/assets/img/Logo%20with%20circle.png')
            center / cover no-repeat`
              }}
            ></div>
            <div className='ZapSplitUserBoxUserDetails'>
              <p className='ZapSplitUserBoxUserDetailsName'>DEG Mods</p>
              <p className='ZapSplitUserBoxUserDetailsHandle'>
                degmods@degmods.com
              </p>
            </div>
          </div>
          <p className='ZapSplitUserBoxText'>
            Help with the development, maintenance, management, and growth of
            DEG Mods.
          </p>
          <div className='inputLabelWrapperMain'>
            <label className='form-label labelMain'>Amount (Satoshis)</label>
            <input
              type='text'
              className='inputMain'
              inputMode='numeric'
              placeholder='69 or 420? or 69,420?'
              value={amount ? formatNumber(amount) : ''}
              onChange={handleAmountChange}
            />
          </div>
          <div className='pUMCB_ZapsInsideAmountOptions'>
            <ZapPresets setAmount={setAmount} />
          </div>
          <ZapButtons
            disabled={!amount}
            handleGenerateQRCode={handleGenerateQRCode}
            handleSend={handleSend}
          />
          {paymentRequest && (
            <ZapQR
              paymentRequest={paymentRequest}
              handleClose={handleClose}
              handleQRExpiry={handleQRExpiry}
            />
          )}
        </div>
      </div>
      {isLoading && <LoadingSpinner desc={loadingSpinnerDesc} />}
    </>
  )
}
