import {
  Button,
  Classes,
  Dialog,
  DialogBody,
  DialogFooter,
  InputGroup,
  Label,
  MenuItem,
  NumericInput,
} from '@blueprintjs/core'
import { Select } from '@blueprintjs/select'
import type { Definition } from '@inject/graphql/fragment-types'
import { useTypedMutation, useTypedQuery } from '@inject/graphql/graphql'
import { CreateExercises } from '@inject/graphql/mutations'
import { GetDefinitions } from '@inject/graphql/queries'
import { dialog } from '@inject/shared/css/dialog'
import { notify } from '@inject/shared/notification/engine'
import notEmpty from '@inject/shared/utils/notEmpty'
import type { Dispatch, FC, SetStateAction } from 'react'
import { useCallback, useState } from 'react'

const TEAMS_MAX = 20

interface ExerciseCreatorProps {
  open: boolean
  setOpen: Dispatch<SetStateAction<boolean>>
}

const ExerciseCreator: FC<ExerciseCreatorProps> = ({ open, setOpen }) => {
  const [name, setName] = useState<string>('')
  const [definition, setDefinition] = useState<Definition>()
  const [count, setCount] = useState<undefined | number>()

  const reset = useCallback(() => {
    setName('')
    setDefinition(undefined)
    setCount(undefined)
    setOpen(false)
  }, [setOpen])

  const [{ fetching: loading }, addExercise] = useTypedMutation(CreateExercises)
  const [{ data: definitionData }] = useTypedQuery({
    query: GetDefinitions,
  })

  const handleSubmit = useCallback(() => {
    if (!definition || !count) return

    addExercise({
      id: definition.id,
      teamCount: count,
      name,
    })
      .then(() => reset())
      .catch(err => {
        notify(err.message, {
          intent: 'danger',
        })
      })
  }, [definition, count, addExercise, name, reset])

  return (
    <Dialog
      className={dialog}
      isOpen={open}
      onClose={reset}
      icon='add'
      title='Create an exercise'
    >
      <DialogBody>
        <Label style={{ width: '100%' }}>
          Definition
          <Select<Definition>
            fill
            onItemSelect={definition => setDefinition(definition)}
            items={definitionData?.definitions?.filter(notEmpty) || []}
            popoverProps={{ minimal: true }}
            itemRenderer={(item, { handleClick }) => (
              <MenuItem
                key={item.id}
                onClick={handleClick}
                text={`${item.name} (ID: ${item.id})`}
                active={item.id === definition?.id}
              />
            )}
            filterable={false}
          >
            <Button
              alignText='left'
              fill
              rightIcon='double-caret-vertical'
              text={
                definition
                  ? `${definition.name} (ID: ${definition.id})`
                  : 'Select a definition'
              }
            />
          </Select>
        </Label>

        <Label style={{ width: '100%' }}>
          Number of teams
          {definition?.roles.length ? (
            <>
              {' '}
              <span
                className={Classes.TEXT_MUTED}
              >{`(multiple of the number of roles - ${definition.roles.length})`}</span>
            </>
          ) : (
            ''
          )}
          <NumericInput
            fill
            value={count}
            disabled={!definition}
            stepSize={definition?.roles.length || 1}
            minorStepSize={null}
            majorStepSize={null}
            onValueChange={value => {
              if (
                value >= (definition?.roles.length || 1) &&
                value <= Math.max(TEAMS_MAX, definition?.roles.length || 1) &&
                value % (definition?.roles.length || 1) === 0
              ) {
                setCount(value)
              }
            }}
            min={definition?.roles.length || 1}
            max={Math.max(TEAMS_MAX, definition?.roles.length || 1)}
            title='Number of teams'
            placeholder='Number of teams'
            style={{ margin: 0 }}
          />
        </Label>

        <Label style={{ width: '100%' }}>
          Name <span className={Classes.TEXT_MUTED}>(optional)</span>
          <InputGroup
            placeholder='Exercise name'
            value={name}
            onChange={e => setName(e.target.value)}
          />
        </Label>
      </DialogBody>
      <DialogFooter
        actions={
          <Button
            onClick={handleSubmit}
            intent='primary'
            disabled={!definition || !count}
            title={
              definition && count ? undefined : 'Fill in all required fields'
            }
            loading={loading}
          >
            Submit
          </Button>
        }
      />
    </Dialog>
  )
}

export default ExerciseCreator
