import Table from '@/components/Table'
import {
  Alert,
  Button,
  Dialog,
  DialogBody,
  DialogFooter,
} from '@blueprintjs/core'
import { css, cx } from '@emotion/css'
import type { User } from '@inject/graphql/fragment-types'
import { useTypedMutation } from '@inject/graphql/graphql'
import { AssignUsersEqually } from '@inject/graphql/mutations'
import { dialogBody, maximizedDialog } from '@inject/shared/css/dialog'
import type { FC } from 'react'
import { useCallback, useState } from 'react'
import { AUTH_GROUPS } from '../UserTable/utils'
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 [open, setOpen] = useState(false)
  const [selectedUsers, setSelectedUsers] = useState<string[]>([])
  const [warningOpen, setWarningOpen] = useState(false)

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

  //Q@xvesely please dedupe assign equally and by tags somehow, this is ugly
  const [{ fetching: loading }, assignEqually] =
    useTypedMutation(AssignUsersEqually)
  const handleSubmit = useCallback(() => {
    if (!selectedUsers) return

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

    assignEqually({
      exerciseId,
      userIds: selectedUsers,
    }).then(() => reset())
  }, [assignEqually, exerciseId, reset, selectedUsers, teamCount, warningOpen])

  const tableProps = useUserTableSelection({
    groups: AUTH_GROUPS,
    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<User> {...tableProps} />
        </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
