import { Form, MarkdownInput } from '@/components/form'
import { gql, useMutation } from '@apollo/client'
import styles from './reply.module.css'
import { COMMENTS } from '@/fragments/comments'
import { useMe } from './me'
import { forwardRef, useCallback, useEffect, useState, useRef } from 'react'
import Link from 'next/link'
import { FeeButtonProvider, postCommentBaseLineItems, postCommentUseRemoteLineItems } from './fee-button'
import { commentsViewedAfterComment } from '@/lib/new-comments'
import { commentSchema } from '@/lib/validate'
import { useToast } from './toast'
import { toastDeleteScheduled } from '@/lib/form'
import { ItemButtonBar } from './post'
import { useShowModal } from './modal'
import { Button } from 'react-bootstrap'
import { useRoot } from './root'
import { commentSubTreeRootId } from '@/lib/item'

export function ReplyOnAnotherPage ({ item }) {
  const rootId = commentSubTreeRootId(item)

  let text = 'reply on another page'
  if (item.ncomments > 0) {
    text = 'view replies'
  }

  return (
    <Link href={`/items/${rootId}?commentId=${item.id}`} as={`/items/${rootId}`} className='d-block py-3 fw-bold text-muted'>
      {text}
    </Link>
  )
}

export default forwardRef(function Reply ({ item, onSuccess, replyOpen, children, placeholder, onQuoteReply, onCancelQuote, quote }, ref) {
  const [reply, setReply] = useState(replyOpen || quote)
  const me = useMe()
  const parentId = item.id
  const replyInput = useRef(null)
  const toaster = useToast()
  const showModal = useShowModal()
  const root = useRoot()
  const sub = item?.sub || root?.sub

  useEffect(() => {
    if (replyOpen || quote || !!window.localStorage.getItem('reply-' + parentId + '-' + 'text')) {
      setReply(true)
    }
  }, [replyOpen, quote, parentId])

  const [upsertComment] = useMutation(
    gql`
      ${COMMENTS}
      mutation upsertComment($text: String!, $parentId: ID!, $hash: String, $hmac: String) {
        upsertComment(text: $text, parentId: $parentId, hash: $hash, hmac: $hmac) {
          ...CommentFields
          deleteScheduledAt
          comments {
            ...CommentsRecursive
          }
        }
      }`, {
      update (cache, { data: { upsertComment } }) {
        cache.modify({
          id: `Item:${parentId}`,
          fields: {
            comments (existingCommentRefs = []) {
              const newCommentRef = cache.writeFragment({
                data: upsertComment,
                fragment: COMMENTS,
                fragmentName: 'CommentsRecursive'
              })
              return [newCommentRef, ...existingCommentRefs]
            }
          }
        })

        const ancestors = item.path.split('.')

        // update all ancestors
        ancestors.forEach(id => {
          cache.modify({
            id: `Item:${id}`,
            fields: {
              ncomments (existingNComments = 0) {
                return existingNComments + 1
              }
            }
          })
        })

        // so that we don't see indicator for our own comments, we record this comments as the latest time
        // but we also have record num comments, in case someone else commented when we did
        const root = ancestors[0]
        commentsViewedAfterComment(root, upsertComment.createdAt)
      }
    }
  )

  const onSubmit = useCallback(async ({ amount, hash, hmac, ...values }, { resetForm }) => {
    const { data } = await upsertComment({ variables: { parentId, hash, hmac, ...values } })
    toastDeleteScheduled(toaster, data, 'upsertComment', false, values.text)
    resetForm({ text: '' })
    setReply(replyOpen || false)
  }, [upsertComment, setReply, parentId])

  useEffect(() => {
    if (replyInput.current && reply && !replyOpen) replyInput.current.focus()
  }, [reply])

  const onCancel = useCallback(() => {
    window.localStorage.removeItem('reply-' + parentId + '-' + 'text')
    setReply(false)
    onCancelQuote?.()
  }, [setReply, parentId, onCancelQuote])

  return (
    <div>
      {replyOpen
        ? <div className={styles.replyButtons} />
        : (
          <div className={styles.replyButtons}>
            <div
              className='pe-3'
              onClick={e => {
                if (reply) {
                  const text = window.localStorage.getItem('reply-' + parentId + '-' + 'text')
                  if (text?.trim()) {
                    showModal(onClose => (
                      <>
                        <p className='fw-bolder'>Are you sure? You will lose your work</p>
                        <div className='d-flex justify-content-end'>
                          <Button
                            variant='info' onClick={() => {
                              onCancel()
                              onClose()
                            }}
                          >yep
                          </Button>
                        </div>
                      </>
                    ))
                  } else {
                    onCancel()
                  }
                } else {
                  e.preventDefault()
                  onQuoteReply?.({ selectionOnly: true })
                  setReply(true)
                }
              }}
            >
              {reply ? 'cancel' : 'reply'}
            </div>
            {/* HACK if we need more items, we should probably do a comment toolbar */}
            {children}
          </div>)}
      {reply &&
        <div className={styles.reply}>
          <FeeButtonProvider
            baseLineItems={postCommentBaseLineItems({ baseCost: 1, comment: true, me: !!me })}
            useRemoteLineItems={postCommentUseRemoteLineItems({ parentId: item.id, me: !!me })}
          >
            <Form
              initial={{
                text: ''
              }}
              schema={commentSchema}
              invoiceable
              onSubmit={onSubmit}
              storageKeyPrefix={`reply-${parentId}`}
            >
              <MarkdownInput
                name='text'
                minRows={6}
                autoFocus={!replyOpen}
                required
                appendValue={quote}
                placeholder={placeholder}
                hint={sub?.moderated && 'this territory is moderated'}
              />
              <ItemButtonBar createText='reply' hasCancel={false} />
            </Form>
          </FeeButtonProvider>
        </div>}
    </div>
  )
})

export function ReplySkeleton () {
  return (
    <div className={`${styles.reply} ${styles.skeleton}`}>
      <div className={`${styles.input} clouds`} />
      <div className={`${styles.button} clouds`} />
    </div>
  )
}