import { useEnqueueSnackbar } from '@/hooks/useEnqueueSnackbar'
import { useModalSearchParams } from '@/hooks/useModalSearchParams'
import { Modal } from '@/shared/Modal/Modal'
import { MODAL_PARAMS_KEYS } from '@/types/modal'
import { Stack, Typography, useTheme } from '@mui/material'
import React, { ChangeEvent, useEffect, useState } from 'react'
import { Input } from '@/shared/Input/Input'
import { Button } from '@/shared/Button/Button'
import { CheckmarkIcon } from '@/assets'
import { swicCall } from '@/modules/swic'
import { useNavigate } from 'react-router-dom'
import { DOMAIN } from '@/utils/consts'
import { fetchNip05 } from '@/utils/helpers/helpers'
import { LoadingSpinner } from '@/shared/LoadingSpinner/LoadingSpinner'

export const ModalSignUp = () => {
  const { getModalOpened, createHandleCloseReplace } = useModalSearchParams()
  const isModalOpened = getModalOpened(MODAL_PARAMS_KEYS.SIGN_UP)
  const handleCloseModal = createHandleCloseReplace(MODAL_PARAMS_KEYS.SIGN_UP)
  const notify = useEnqueueSnackbar()
  const theme = useTheme()

  const navigate = useNavigate()

  const [enteredValue, setEnteredValue] = useState('')
  const [isAvailable, setIsAvailable] = useState(false)

  const [isLoading, setIsLoading] = useState(false)

  const handleInputChange = async (e: ChangeEvent<HTMLInputElement>) => {
    setEnteredValue(e.target.value)
    const name = e.target.value.trim()
    if (name) {
      const npubNip05 = await fetchNip05(`${name}@${DOMAIN}`)
      setIsAvailable(!npubNip05)
    } else {
      setIsAvailable(false)
    }
  }

  const getInputHelperText = () => {
    if (!enteredValue) return "Don't worry, username can be changed later."
    if (!isAvailable) return 'Already taken'
    return (
      <>
        <CheckmarkIcon /> Available
      </>
    )
  }

  const inputHelperText = getInputHelperText()

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault()
    if (isLoading || !isAvailable) return undefined

    const name = enteredValue.trim()
    if (!name.length) return

    try {
      setIsLoading(true)
      const k: any = await swicCall('generateKey', name)
      if (k.name) notify(`Account created for "${k.name}"`, 'success')
      else notify(`Failed to assign name "${name}", try again`, 'error')
      setIsLoading(false)
      setTimeout(() => {
        // give frontend time to read the new key first
        navigate(`/key/${k.npub}`)
      }, 300)
    } catch (error: any) {
      notify(error?.message || 'Something went wrong!', 'error')
      setIsLoading(false)
    }
  }

  useEffect(() => {
    return () => {
      if (isModalOpened) {
        // modal closed
        setIsLoading(false)
        setIsAvailable(false)
      }
    }
  }, [isModalOpened])

  return (
    <Modal open={isModalOpened} onClose={handleCloseModal} withCloseButton={false}>
      <Stack paddingTop={'1rem'} gap={'1rem'} component={'form'} onSubmit={handleSubmit}>
        <Stack gap={'0.2rem'} padding={'0 1rem'} alignSelf={'flex-start'}>
          <Typography fontWeight={600} variant="h5">
            Sign up
          </Typography>
          <Typography noWrap variant="body2" color={'GrayText'}>
            Generate new Nostr keys
          </Typography>
        </Stack>
        <Input
          label="Username"
          fullWidth
          placeholder="Enter a Username"
          helperText={inputHelperText}
          endAdornment={<Typography color={'#FFFFFFA8'}>@{DOMAIN}</Typography>}
          onChange={handleInputChange}
          value={enteredValue}
          helperTextProps={{
            sx: {
              '&.helper_text': {
                color:
                  enteredValue && isAvailable
                    ? theme.palette.success.main
                    : enteredValue && !isAvailable
                      ? theme.palette.error.main
                      : theme.palette.textSecondaryDecorate.main,
              },
            },
          }}
        />
        <Stack gap={'0.5rem'}>
          <Button fullWidth type="submit" disabled={isLoading}>
            Create account {isLoading && <LoadingSpinner />}
          </Button>
        </Stack>
      </Stack>
    </Modal>
  )
}
