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 { useTypedMutation, useTypedQuery } from '@inject/graphql/graphql'
import { SendEmail } from '@inject/graphql/mutations'
import { GetEmailAddresses, GetEmailContacts } from '@inject/graphql/queries'
import notEmpty from '@inject/shared/utils/notEmpty'
import type { FC } from 'react'
import { memo, useCallback, useMemo } from 'react'
import { useClient } from 'urql'
import InstructorHeaderArea from './InstructorHeaderArea'
import { form } from './classes'
import instructorMarkTodo from './instructorMarkTodo'
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 [{ fetching: loading }, sendEmailMutate] = useTypedMutation(SendEmail)
  const client = useClient()
  const { onSend } = useThreadSubmission({
    ...(emailThread
      ? { existingThreadId: emailThread.id }
      : {
          participantAddresses: selectedContacts,
          subject,
          bccAddresses: bccSelectedContacts,
        }),
    exerciseId,
    senderAddress,
    content,
    fileId: fileInfo?.id,
    onSendEmail: ({ threadId, allowActivateMilestone }: OnSendEmailInput) => {
      sendEmailMutate({
        sendEmailInput: {
          threadId,
          senderAddress,
          content,
          activateMilestone: allowActivateMilestone ? activateMilestone : '',
          deactivateMilestone: allowActivateMilestone
            ? deactivateMilestone
            : '',
          fileId: fileInfo?.id ?? null,
        },
      }).then(() => {
        discardDraft()
        instructorMarkTodo(client, threadId)
        onSuccess(threadId)
      })
    },
  })

  const [{ data: emailAddresses }] = useTypedQuery({
    query: GetEmailAddresses,
    variables: {
      threadId: emailThread?.id || '',
    },
    requestPolicy: 'network-only',
    pause: emailThread === undefined,
  })
  const [{ data: emailContacts }] = useTypedQuery({
    query: GetEmailContacts,
    variables: {
      visibleOnly: false,
    },
    requestPolicy: 'network-only',
  })

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

  const [{ data: emailContactsData }] = useTypedQuery({
    query: GetEmailContacts,
  })
  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)
