import { Button, ButtonGroup, Card, Overlay2 } from '@blueprintjs/core'
import { css, cx } from '@emotion/css'
import type { EmailThread, FileInfo } from '@inject/graphql/fragment-types'
import { maximizedDialog } from '@inject/shared/css/dialog'
import type { FC } from 'react'
import { useCallback, useEffect, useState } from 'react'
import useFormState from '../EmailForm/useFormState'
import Content from './Content'

const header = css`
  display: flex;
  gap: 1rem;
  align-items: center;
  justify-content: space-between;
`

const headerText = css`
  margin-left: 0.5rem;
`

const card = css`
  min-height: 50vh;
  min-width: clamp(40vw, 45rem, 90vw);
  max-width: clamp(40vw, 45rem, 90vw);
  padding: 0 !important;
  display: flex;
  flex-direction: column;
  right: 0;
  bottom: 0;
  margin: 0 1rem;
`

const cardMaximized = css`
  right: calc(50% - min(60rem, 90vw) / 2);
  bottom: calc(50% - min(60rem, 90vh) / 2);
`

const cardMinimized = css`
  min-height: unset;
  min-width: unset;
`

//Q@xvesely wouldn't it be better to have this in a separate file?
export const OPEN_COMPOSE_EVENT_TYPE = 'openCompose'
export const OPEN_REPLY_EVENT_TYPE = 'openReply'
declare global {
  interface WindowEventMap {
    [OPEN_COMPOSE_EVENT_TYPE]: CustomEvent<OpenComposeEventPayload>
    [OPEN_REPLY_EVENT_TYPE]: CustomEvent<OpenReplyEventPayload>
  }
}

interface ComposeInitialValues {
  content?: string
  fileInfo?: FileInfo
  subject?: string
  email?: string
}

type OpenComposeEventPayload = ComposeInitialValues | undefined

interface OpenReplyEventPayload {
  emailThread: EmailThread
}

const EmailFormOverlay: FC<
  {
    loading?: boolean
    error?: Error
    teamId: string
    exerciseId: string
    onSuccess: (threadId?: string) => void
  } & (
    | { emailForm: 'trainee'; teamAddress: string }
    | { emailForm: 'instructor'; teamAddress?: undefined }
  )
> = ({
  loading,
  error,
  teamId,
  emailForm,
  teamAddress,
  exerciseId,
  onSuccess,
}) => {
  const [open, setOpen] = useState(false)
  const [emailThread, setEmailThread] = useState<EmailThread | undefined>()
  const [maximized, setMaximized] = useState(false)
  const [minimized, setMinimized] = useState(false)

  const formState = useFormState({
    teamAddress: emailForm === 'trainee' ? teamAddress : undefined,
    inInstructor: emailForm === 'instructor',
    teamId,
  })
  const { reload } = formState

  const handleOpen = useCallback(() => {
    setOpen(true)
    setMaximized(false)
    setMinimized(false)
  }, [])
  const handleClose = useCallback((threadId?: string) => {
    setOpen(false)
    setMaximized(false)
    setMinimized(false)
    onSuccess(threadId)
  }, [])

  const handleOpenCompose = useCallback(
    (event: CustomEvent<OpenComposeEventPayload>) => {
      handleOpen()
      setEmailThread(undefined)

      if (event.detail) {
        const { content, fileInfo, subject, email } = event.detail
        reload({
          emailThreadId: undefined,
          loadDraft: false,
          content,
          fileInfo,
          subject,
          selectedContacts: email ? [email] : undefined,
        })
      } else {
        reload({ emailThreadId: undefined, loadDraft: true })
      }
    },
    [reload]
  )
  useEffect(() => {
    window.addEventListener(OPEN_COMPOSE_EVENT_TYPE, handleOpenCompose)
    return () => {
      window.removeEventListener(OPEN_COMPOSE_EVENT_TYPE, handleOpenCompose)
    }
  }, [handleOpenCompose])

  const handleOpenReply = useCallback(
    (event: CustomEvent<OpenReplyEventPayload>) => {
      handleOpen()
      setEmailThread(event.detail.emailThread)
      reload({ emailThreadId: event.detail.emailThread.id, loadDraft: true })
    },
    [handleOpen, reload]
  )
  useEffect(() => {
    window.addEventListener(OPEN_REPLY_EVENT_TYPE, handleOpenReply)
    return () => {
      window.removeEventListener(OPEN_REPLY_EVENT_TYPE, handleOpenReply)
    }
  }, [handleOpenReply])

  useEffect(() => {
    handleClose()
  }, [handleClose, teamId])

  return (
    <Overlay2
      isOpen={open}
      autoFocus={false}
      canEscapeKeyClose={maximized}
      canOutsideClickClose={maximized}
      enforceFocus={false}
      hasBackdrop={maximized}
      transitionDuration={0}
      onClose={() => {
        setMaximized(false)
      }}
    >
      <Card
        className={cx({
          [card]: true,
          [cardMaximized]: maximized,
          [maximizedDialog]: maximized,
          [cardMinimized]: minimized,
        })}
        compact
        elevation={4}
      >
        <div className={header}>
          {minimized && <span className={headerText}>New email</span>}

          <ButtonGroup minimal style={{ marginLeft: 'auto' }}>
            <Button
              icon={minimized ? 'chevron-up' : 'minus'}
              onClick={() => {
                setMaximized(false)
                setMinimized(prev => !prev)
              }}
            />
            <Button
              icon={maximized ? 'minimize' : 'maximize'}
              onClick={() => {
                setMinimized(false)
                setMaximized(prev => !prev)
              }}
            />
            <Button icon='cross' onClick={() => handleClose()} />
          </ButtonGroup>
        </div>

        {!minimized && (
          <Content
            emailForm={emailForm}
            exerciseId={exerciseId}
            formState={formState}
            onSuccess={handleClose}
            loading={loading}
            teamId={teamId}
            emailThread={emailThread}
            error={error}
          />
        )}
      </Card>
    </Overlay2>
  )
}

export default EmailFormOverlay
