import { useEffect, useState } from 'react'
import { gql, useMutation } from '@apollo/client'
import { signIn } from 'next-auth/react'
import Container from 'react-bootstrap/Container'
import Col from 'react-bootstrap/Col'
import Row from 'react-bootstrap/Row'
import { useRouter } from 'next/router'
import AccordianItem from './accordian-item'
import BackIcon from '@/svgs/arrow-left-line.svg'
import styles from './lightning-auth.module.css'
import { callWithTimeout } from '@/lib/nostr'

function ExtensionError ({ message, details }) {
  return (
    <>
      <h4 className='fw-bold text-danger pb-1'>error: {message}</h4>
      <div className='text-muted pb-4'>{details}</div>
    </>
  )
}

function NostrExplainer ({ text }) {
  return (
    <>
      <ExtensionError message='nostr extension not found' details='Nostr extensions are the safest way to use your nostr identity on Stacker News.' />
      <Row className='w-100 text-muted'>
        <AccordianItem
          header={`Which extensions can I use to ${(text || 'Login').toLowerCase()} with Nostr?`}
          show
          body={
            <>
              <Row>
                <Col>
                  <ul>
                    <li>
                      <a href='https://getalby.com'>Alby</a><br />
                      available for: chrome, firefox, and safari
                    </li>
                    <li>
                      <a href='https://www.getflamingo.org/'>Flamingo</a><br />
                      available for: chrome
                    </li>
                    <li>
                      <a href='https://github.com/fiatjaf/nos2x'>nos2x</a><br />
                      available for: chrome
                    </li>
                    <li>
                      <a href='https://diegogurpegui.com/nos2x-fox/'>nos2x-fox</a><br />
                      available for: firefox
                    </li>
                    <li>
                      <a href='https://github.com/fiatjaf/horse'>horse</a><br />
                      available for: chrome<br />
                      supports hardware signing
                    </li>
                  </ul>
                </Col>
              </Row>
            </>
          }
        />
      </Row>
    </>
  )
}

export function NostrAuth ({ text, callbackUrl }) {
  const [createAuth, { data, error }] = useMutation(gql`
    mutation createAuth {
      createAuth {
        k1
      }
    }`, {
    // don't cache this mutation
    fetchPolicy: 'no-cache'
  })
  const [hasExtension, setHasExtension] = useState(undefined)
  const [extensionError, setExtensionError] = useState(null)

  useEffect(() => {
    createAuth()
    setHasExtension(!!window.nostr)
  }, [])

  const k1 = data?.createAuth.k1

  useEffect(() => {
    if (!k1 || !hasExtension) return

    console.info('nostr extension detected')

    let mounted = true;
    (async function () {
      try {
        // have them sign a message with the challenge
        let event
        try {
          event = await callWithTimeout(() => window.nostr.signEvent({
            kind: 22242,
            created_at: Math.floor(Date.now() / 1000),
            tags: [['challenge', k1]],
            content: 'Stacker News Authentication'
          }), 5000)
          if (!event) throw new Error('extension returned empty event')
        } catch (e) {
          if (e.message === 'window.nostr call already executing' || !mounted) return
          setExtensionError({ message: 'nostr extension failed to sign event', details: e.message })
          return
        }

        // sign them in
        try {
          await signIn('nostr', {
            event: JSON.stringify(event),
            callbackUrl
          })
        } catch (e) {
          throw new Error('authorization failed', e)
        }
      } catch (e) {
        if (!mounted) return
        console.log('nostr auth error', e)
        setExtensionError({ message: `${text} failed`, details: e.message })
      }
    })()
    return () => { mounted = false }
  }, [k1, hasExtension])

  if (error) return <div>error</div>

  return (
    <>
      {hasExtension === false && <NostrExplainer text={text} />}
      {extensionError && <ExtensionError {...extensionError} />}
      {hasExtension && !extensionError &&
        <>
          <h4 className='fw-bold text-success pb-1'>nostr extension found</h4>
          <h6 className='text-muted pb-4'>authorize event signature in extension</h6>
        </>}
    </>
  )
}

export default function NostrAuthWithExplainer ({ text, callbackUrl }) {
  const router = useRouter()
  return (
    <Container>
      <div className={styles.login}>
        <div className='w-100 mb-3 text-muted pointer' onClick={() => router.back()}><BackIcon /></div>
        <h3 className='w-100 pb-2'>{text || 'Login'} with Nostr</h3>
        <NostrAuth text={text} callbackUrl={callbackUrl} />
      </div>
    </Container>
  )
}