import { useQuery, useMutation } from '@apollo/client'
import { CenterLayout } from '@/components/layout'
import { CopyInput, Input, InputSkeleton } from '@/components/form'
import InputGroup from 'react-bootstrap/InputGroup'
import InvoiceStatus from '@/components/invoice-status'
import { useRouter } from 'next/router'
import { WITHDRAWL } from '@/fragments/wallet'
import Link from 'next/link'
import { SSR, INVOICE_RETENTION_DAYS, FAST_POLL_INTERVAL } from '@/lib/constants'
import { numWithUnits } from '@/lib/format'
import Bolt11Info from '@/components/bolt11-info'
import { datePivot, timeLeft } from '@/lib/time'
import { useMe } from '@/components/me'
import { useToast } from '@/components/toast'
import { gql } from 'graphql-tag'
import { useShowModal } from '@/components/modal'
import { DeleteConfirm } from '@/components/delete'
import { getGetServerSideProps } from '@/api/ssrApollo'

// force SSR to include CSP nonces
export const getServerSideProps = getGetServerSideProps({ query: null })

export default function Withdrawl () {
  return (
    <CenterLayout>
      <LoadWithdrawl />
    </CenterLayout>
  )
}

export function WithdrawlSkeleton ({ status }) {
  return (
    <>
      <div className='w-100 form-group'>
        <InputSkeleton label='invoice' />
      </div>
      <div className='w-100 form-group'>
        <InputSkeleton label='max fee' />
      </div>
      <InvoiceStatus status={status} />
      <div className='w-100 mt-3'>
        <Bolt11Info />
      </div>
    </>
  )
}

function LoadWithdrawl () {
  const router = useRouter()
  const { loading, error, data } = useQuery(WITHDRAWL, SSR
    ? {}
    : {
        variables: { id: router.query.id },
        pollInterval: FAST_POLL_INTERVAL,
        nextFetchPolicy: 'cache-and-network'
      })
  if (error) return <div>error</div>
  if (!data || loading) {
    return <WithdrawlSkeleton status='loading' />
  }

  const TryMaxFee = () =>
    <Link href='/wallet?type=withdraw' className='text-reset text-underline'>
      <small className='ms-3'>try increasing max fee</small>
    </Link>

  let status = 'pending'
  let variant = 'default'
  switch (data.withdrawl.status) {
    case 'CONFIRMED':
      status = `sent ${numWithUnits(data.withdrawl.satsPaid, { abbreviate: false })} with ${numWithUnits(data.withdrawl.satsFeePaid, { abbreviate: false })} in routing fees`
      variant = 'confirmed'
      break
    case 'INSUFFICIENT_BALANCE':
      status = <>insufficient balance <small className='ms-3'>contact keyan!</small></>
      variant = 'failed'
      break
    case 'INVALID_PAYMENT':
      status = 'invalid invoice'
      variant = 'failed'
      break
    case 'PATHFINDING_TIMEOUT':
      status = <>timed out finding route <TryMaxFee /></>
      variant = 'failed'
      break
    case 'ROUTE_NOT_FOUND':
      status = <>no route <TryMaxFee /></>
      variant = 'failed'
      break
    case 'UNKNOWN_FAILURE':
      status = <>unknown error</>
      variant = 'failed'
      break
    default:
      break
  }

  return (
    <>
      <div className='w-100'>
        <CopyInput
          label='invoice' type='text'
          placeholder={data.withdrawl.bolt11 || 'deleted'} readOnly noForm
        />
      </div>
      <div className='w-100'>
        <Input
          label='max fee' type='text'
          placeholder={data.withdrawl.satsFeePaying} readOnly noForm
          append={<InputGroup.Text className='text-monospace'>sats</InputGroup.Text>}
        />
      </div>
      <InvoiceStatus variant={variant} status={status} />
      <div className='w-100 mt-3'>
        <Bolt11Info bolt11={data.withdrawl.bolt11} preimage={data.withdrawl.preimage}>
          <PrivacyOption wd={data.withdrawl} />
        </Bolt11Info>
      </div>
    </>
  )
}

function PrivacyOption ({ wd }) {
  if (!wd.bolt11) return

  const me = useMe()
  const keepUntil = datePivot(new Date(wd.createdAt), { days: INVOICE_RETENTION_DAYS })
  const oldEnough = new Date() >= keepUntil
  if (!oldEnough) {
    return (
      <span className='text-muted fst-italic'>
        {`this invoice ${me.privates?.autoDropBolt11s ? 'will be auto-deleted' : 'can be deleted'} in ${timeLeft(keepUntil)}`}
      </span>
    )
  }

  const showModal = useShowModal()
  const toaster = useToast()
  const [dropBolt11] = useMutation(
    gql`
      mutation dropBolt11($id: ID!) {
        dropBolt11(id: $id) {
          id
        }
      }`, {
      update (cache) {
        cache.modify({
          id: `Withdrawl:${wd.id}`,
          fields: {
            bolt11: () => null,
            hash: () => null
          }
        })
      }
    })

  return (
    <span
      className='btn btn-md btn-danger' onClick={() => {
        showModal(onClose => {
          return (
            <DeleteConfirm
              type='invoice'
              onConfirm={async () => {
                if (me) {
                  try {
                    await dropBolt11({ variables: { id: wd.id } })
                  } catch (err) {
                    toaster.danger('unable to delete invoice: ' + err.message || err.toString?.())
                    throw err
                  } finally {
                    onClose()
                  }
                }
              }}
            />
          )
        })
      }}
    >delete invoice
    </span>
  )
}