import { useCreateThread } from '@inject/graphql/mutations/CreateThread.generated'
import { useNotifyContext } from '@inject/shared/notification/contexts/NotifyContext'
import { useCallback } from 'react'
import type { OnSendEmailInput } from './typing'

type ThreadSubmissionProps = (
  | {
      // existing thread
      existingThreadId: string
      participantAddresses?: undefined
      bccAddresses?: undefined
      subject?: undefined
    }
  | {
      // new thread
      existingThreadId?: undefined
      participantAddresses: string[]
      subject: string | undefined
      bccAddresses?: string[]
    }
) & {
  exerciseId: string
  content?: string
  fileId?: string
  senderAddress: string
  onSendEmail: (input: OnSendEmailInput) => void
}

const useThreadSubmission = ({
  exerciseId,
  existingThreadId,
  participantAddresses,
  senderAddress,
  bccAddresses,
  subject,
  onSendEmail,
  content,
  fileId,
}: ThreadSubmissionProps) => {
  const [createThread] = useCreateThread()
  const { notify } = useNotifyContext()

  const onSend = useCallback(async () => {
    if (existingThreadId === undefined) {
      if (participantAddresses.length < 2) {
        notify('Select at least two participants', {
          intent: 'danger',
        })
        return
      }
      if (!subject) {
        notify('Add a subject', {
          intent: 'danger',
        })
        return
      }
    }

    if (!senderAddress) {
      notify('Select a sender', {
        intent: 'danger',
      })
      return
    }
    if (!content && !fileId) {
      notify('Add a message or an attachment', {
        intent: 'danger',
      })
      return
    }

    if (existingThreadId !== undefined) {
      onSendEmail({ threadId: existingThreadId, allowActivateMilestone: true })
      return
    }

    await createThread({
      variables: {
        exerciseId,
        participantAddresses,
        // false positive TS error
        subject: subject || '',
      },
      onError: err => {
        notify(err.message, {
          intent: 'danger',
        })
      },
      onCompleted: data => {
        onSendEmail({
          threadId: data.createThread?.thread?.id || '',
          allowActivateMilestone: true,
        })

        if (!bccAddresses) {
          return
        }

        bccAddresses.forEach(async bccAddress => {
          await createThread({
            variables: {
              exerciseId,
              participantAddresses: [bccAddress, senderAddress],
              // false positive TS error
              subject: subject || '',
            },
            onError: err => {
              notify(err.message, {
                intent: 'danger',
              })
            },
            onCompleted: data => {
              onSendEmail({
                threadId: data.createThread?.thread?.id || '',
                allowActivateMilestone: false,
              })
            },
          })
        })
      },
    })
  }, [
    bccAddresses,
    content,
    createThread,
    exerciseId,
    existingThreadId,
    fileId,
    notify,
    onSendEmail,
    participantAddresses,
    senderAddress,
    subject,
  ])

  return {
    onSend,
  }
}

export default useThreadSubmission
