import HelpIcon from '@/analyst/HelpIcon'
import LinkButton from '@/components/LinkButton'
import { useNavigate } from '@/router'
import UsersSelection from '@/users/UsersSelection'
import { Button, NonIdealState, Section, SectionCard } from '@blueprintjs/core'
import Reloader from '@inject/graphql/components/Reloader'
import { useAddDefinitionAccess } from '@inject/graphql/mutations/AddDefinitionAccess.generated'
import { useRemoveDefinitionAccess } from '@inject/graphql/mutations/RemoveDefinitionAccess.generated'
import {
  GetDefinitionDocument,
  useGetDefinition,
} from '@inject/graphql/queries/GetDefinition.generated'
import { useNotifyContext } from '@inject/shared/notification/contexts/NotifyContext'
import notEmpty from '@inject/shared/utils/notEmpty'
import type { FC } from 'react'
import { useCallback, useState } from 'react'
import { useLocation } from 'react-router-dom'
import UserTableSelection from '../UserTableSelection'

interface DefinitionAssignmentProps {
  definitionId: string
}

const DefinitionAssignment: FC<DefinitionAssignmentProps> = ({
  definitionId,
}) => {
  const { notify } = useNotifyContext()
  const nav = useNavigate()
  const { state } = useLocation()

  const [addOpen, setAddOpen] = useState(false)
  const [selectedUsers, setSelectedUsers] = useState<string[]>([])

  const { data, refetch } = useGetDefinition({
    variables: {
      definitionId,
    },
    fetchPolicy: 'network-only',
  })
  const { name, userSet } = data?.definition || {}

  const [addDefinitionAccess] = useAddDefinitionAccess()
  const handleAdd = useCallback(
    (ids: string[]) => {
      addDefinitionAccess({
        variables: {
          definitionId,
          userIds: ids,
        },
        refetchQueries: [GetDefinitionDocument],
        onCompleted: () => {
          setAddOpen(false)
        },
        onError: error => {
          notify(error.message, {
            intent: 'danger',
          })
        },
      })
    },
    [addDefinitionAccess, definitionId, notify]
  )

  const [removeDefinitionAccess] = useRemoveDefinitionAccess()
  const handleRemove = useCallback(
    (ids: string[]) => {
      removeDefinitionAccess({
        variables: {
          definitionId,
          userIds: ids,
        },
        refetchQueries: [GetDefinitionDocument],
        onError: error => {
          notify(error.message, {
            intent: 'danger',
          })
        },
      })
    },
    [removeDefinitionAccess, definitionId, notify]
  )

  if (!data || !data.definition) {
    return (
      <NonIdealState
        icon='low-voltage-pole'
        description='Unable to display users'
      />
    )
  }

  return (
    <>
      {state?.fromUserDetail ? (
        <Button
          type='button'
          minimal
          icon='chevron-left'
          onClick={() => {
            nav(-1)
          }}
        >
          Back
        </Button>
      ) : (
        <LinkButton
          link={['/exercise-panel']}
          button={{
            text: 'Back',
            icon: 'chevron-left',
            minimal: true,
          }}
        />
      )}

      <Section
        title='Manage access to definition'
        subtitle={name}
        icon={
          <HelpIcon
            text='Instructors with access to a definition are able to
          create exercises from it. They can also start, stop, and delete
          them, and assign participants to them.'
          />
        }
        rightElement={<Reloader minimal onRefetch={refetch} />}
      >
        <SectionCard>
          <UsersSelection
            users={userSet?.filter(notEmpty) || []}
            onRemove={(ids: string[]) => handleRemove(ids)}
            onAdd={() => setAddOpen(true)}
          />
        </SectionCard>
      </Section>

      <UserTableSelection
        groups={['ADMIN', 'INSTRUCTOR']}
        open={addOpen}
        setOpen={setAddOpen}
        onAdd={(ids: string[]) => handleAdd(ids)}
        selectedUsers={selectedUsers}
        setSelectedUsers={setSelectedUsers}
      />
    </>
  )
}

export default DefinitionAssignment
