import {
  Alert,
  Button,
  Dialog,
  DialogBody,
  DialogFooter,
} from '@blueprintjs/core'
import { css, cx } from '@emotion/css'
import { useAssignUsersEqually } from '@inject/graphql/mutations/AssignUsersEqually.generated'
import { GetExerciseDocument } from '@inject/graphql/queries/GetExercise.generated'
import { dialogBody, maximizedDialog } from '@inject/shared/css/dialog'
import { useNotifyContext } from '@inject/shared/notification/contexts/NotifyContext'
import type { FC } from 'react'
import { useCallback, useState } from 'react'
import useUserTableSelection from '../UserTableSelection/useUserTableSelection'

const body = css`
  display: flex;
  flex-direction: column;
  gap: 1rem;
  overflow: auto;
`

interface AssignEquallyProps {
  exerciseId: string
  teamCount: number
}

const AssignEqually: FC<AssignEquallyProps> = ({ exerciseId, teamCount }) => {
  const { notify } = useNotifyContext()

  const [open, setOpen] = useState(false)
  const [selectedUsers, setSelectedUsers] = useState<string[]>([])
  const [warningOpen, setWarningOpen] = useState(false)

  const reset = useCallback(() => {
    setOpen(false)
    setSelectedUsers([])
  }, [])

  const [AssignEqually, { loading }] = useAssignUsersEqually()
  const handleSubmit = useCallback(() => {
    if (!selectedUsers) return

    if (!warningOpen && selectedUsers.length % teamCount !== 0) {
      setWarningOpen(true)
      return
    }

    AssignEqually({
      variables: {
        exerciseId,
        userIds: selectedUsers,
      },
      onCompleted: reset,
      onError: err => notify(err.message),
      refetchQueries: [GetExerciseDocument],
    })
  }, [
    AssignEqually,
    exerciseId,
    notify,
    reset,
    selectedUsers,
    teamCount,
    warningOpen,
  ])

  const { table } = useUserTableSelection({
    groups: ['INSTRUCTOR', 'TRAINEE'],
    onCancel: reset,
    onAdd: (ids: string[]) => setSelectedUsers(ids),
    selectedUsers,
    setSelectedUsers,
  })

  return (
    <>
      <Button
        icon='align-justify'
        text='Assign equally'
        onClick={() => setOpen(true)}
        active={open}
      />

      <Dialog
        isOpen={open}
        onClose={reset}
        className={maximizedDialog}
        title='Assign users to teams equally'
        icon='align-justify'
      >
        <DialogBody className={cx(dialogBody, body)}>{table}</DialogBody>
        <DialogFooter
          actions={
            <Button
              onClick={handleSubmit}
              intent='primary'
              disabled={selectedUsers.length === 0}
              title={selectedUsers.length > 0 ? undefined : 'Select some users'}
              loading={loading}
            >
              {`Assign (${selectedUsers.length})`}
            </Button>
          }
        />
      </Dialog>

      <Alert
        isOpen={warningOpen}
        canEscapeKeyCancel
        canOutsideClickCancel
        cancelButtonText='Cancel'
        onCancel={() => setWarningOpen(false)}
        confirmButtonText='Confirm'
        icon='warning-sign'
        intent='warning'
        onConfirm={handleSubmit}
        onClose={() => setWarningOpen(false)}
        loading={loading}
      >
        <p>{`Some teams will have more users than others, because the number of selected users (${selectedUsers.length}) is not divisible by the number of teams (${teamCount}).`}</p>
        <p>Do you want to proceed?</p>
      </Alert>
    </>
  )
}

export default AssignEqually
