import ContentArea from '@/components/ContentArea'
import FileArea from '@/components/FileArea'
import MilestoneSelector from '@/instructor/MilestoneSelector/MilestoneSelector'
import { Button, ButtonGroup, Divider, FormGroup } from '@blueprintjs/core'
import { css } from '@emotion/css'
import { useSendEmail } from '@inject/graphql/mutations/SendEmail.generated'
import { useGetEmailAddresses } from '@inject/graphql/queries/GetEmailAddresses.generated'
import { useGetEmailContacts } from '@inject/graphql/queries/GetEmailContacts.generated'
import { useNotifyContext } from '@inject/shared/notification/contexts/NotifyContext'
import notEmpty from '@inject/shared/utils/notEmpty'
import type { FC } from 'react'
import { memo, useCallback, useMemo } from 'react'
import InstructorHeaderArea from './InstructorHeaderArea'
import { form } from './classes'
import type { EmailFormProps, OnSendEmailInput } from './typing'
import useThreadSubmission from './useThreadSubmission'

const footer = css`
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem;
`

const InstructorEmailForm: FC<EmailFormProps> = ({
  exerciseId,
  emailThread,
  teamId,
  onSuccess,
  formState: {
    fileInfo,
    setFileInfo,
    activateMilestone,
    deactivateMilestone,
    setActivateMilestone,
    setDeactivateMilestone,
    content,
    setContent,
    discardDraft,
    storeDraft,
    senderAddress,
    setSenderAddress,
    selectedContacts,
    setSelectedContacts,
    bccSelectedContacts,
    setBccSelectedContacts,
    subject,
    setSubject,
    template,
    setTemplate,
  },
}) => {
  const [sendEmailMutate, { loading }] = useSendEmail()
  const { notify } = useNotifyContext()

  const { onSend } = useThreadSubmission({
    ...(emailThread
      ? { existingThreadId: emailThread.id }
      : {
          participantAddresses: selectedContacts,
          subject,
          bccAddresses: bccSelectedContacts,
        }),
    exerciseId,
    senderAddress,
    content,
    fileId: fileInfo?.id,
    onSendEmail: ({ threadId, allowActivateMilestone }: OnSendEmailInput) => {
      sendEmailMutate({
        variables: {
          sendEmailInput: {
            threadId,
            senderAddress,
            content,
            fileId: fileInfo?.id,
            activateMilestone: allowActivateMilestone
              ? activateMilestone
              : undefined,
            deactivateMilestone: allowActivateMilestone
              ? deactivateMilestone
              : undefined,
          },
        },
        onCompleted: () => {
          discardDraft()
          onSuccess()
        },
        onError: err => {
          notify(err.message, {
            intent: 'danger',
          })
        },
      })
    },
  })

  const { data: emailAddresses } = useGetEmailAddresses({
    variables: {
      threadId: emailThread?.id || '',
    },
    fetchPolicy: 'network-only',
    skip: emailThread === undefined,
  })
  const { data: emailContacts } = useGetEmailContacts({
    variables: {
      visibleOnly: false,
    },
    fetchPolicy: 'network-only',
  })

  const instructorList = useMemo(
    () => (emailContacts?.emailContacts || []).filter(notEmpty),
    [emailContacts]
  )

  const { data: emailContactsData } = useGetEmailContacts()
  const definitionAddresses = useMemo(
    () =>
      emailContactsData?.emailContacts
        ?.map(participant => participant?.definitionAddress?.address)
        .filter(notEmpty) || [],
    [emailContactsData?.emailContacts]
  )
  const isDefinitionAddress = useCallback(
    (address: string) => definitionAddresses.includes(address),
    [definitionAddresses]
  )
  const senderList = useMemo(
    () =>
      emailThread
        ? (emailAddresses?.emailAddresses || []).filter(notEmpty)
        : selectedContacts.filter(isDefinitionAddress),
    [
      emailAddresses?.emailAddresses,
      emailThread,
      isDefinitionAddress,
      selectedContacts,
    ]
  )

  const onDiscard = useCallback(() => {
    discardDraft()
    onSuccess()
  }, [discardDraft, onSuccess])

  const onSave = useCallback(() => {
    storeDraft()
    onSuccess()
  }, [storeDraft, onSuccess])

  const onSubmit = useCallback(() => {
    onSend()
  }, [onSend])

  return (
    <div className={form}>
      <InstructorHeaderArea
        {...(emailThread
          ? {
              emailThread,
            }
          : {
              selectedContacts,
              setSelectedContacts,
              bccSelectedContacts,
              setBccSelectedContacts,
              subject,
              setSubject,
            })}
        contacts={instructorList}
        senderAddress={senderAddress}
        senderList={senderList}
        setSenderAddress={setSenderAddress}
        setContent={setContent}
        setActivateMilestone={setActivateMilestone}
        setDeactivateMilestone={setDeactivateMilestone}
        setFileInfo={setFileInfo}
        template={template}
        setTemplate={setTemplate}
        teamId={teamId}
        exerciseId={exerciseId}
      />

      <Divider style={{ margin: '0.5rem 0' }} />

      <MilestoneSelector
        teamId={teamId}
        activateMilestone={activateMilestone}
        setActivateMilestone={setActivateMilestone}
        deactivateMilestone={deactivateMilestone}
        setDeactivateMilestone={setDeactivateMilestone}
      />

      <ContentArea content={content} setContent={setContent} />

      <Divider style={{ margin: '0.5rem 0' }} />

      <div className={footer}>
        <FileArea
          exerciseId={exerciseId}
          fileInfo={fileInfo}
          setFileInfo={setFileInfo}
          teamId={teamId}
        />

        <FormGroup disabled={loading} style={{ margin: '0' }}>
          <ButtonGroup>
            <Button icon='trash' onClick={onDiscard}>
              Discard
            </Button>
            <Button icon='floppy-disk' onClick={onSave}>
              Save
            </Button>
            <Button
              type='submit'
              rightIcon='send-message'
              onClick={onSubmit}
              loading={loading}
            >
              Send
            </Button>
          </ButtonGroup>
        </FormGroup>
      </div>
    </div>
  )
}

export default memo(InstructorEmailForm)
