import HelpIcon from '@/components/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 { useTypedQuery } from '@inject/graphql/graphql'
import {
  AddDefinitionAccess,
  RemoveDefinitionAccess,
} from '@inject/graphql/mutations'
import { GetDefinition } from '@inject/graphql/queries'
import { notify } from '@inject/shared/notification/engine'
import type { FC } from 'react'
import { useCallback, useState } from 'react'
import { useLocation } from 'react-router-dom'
import { useClient } from 'urql'
import UserTableSelection from '../UserTableSelection'

interface DefinitionAssignmentProps {
  definitionId: string
}

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

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

  const [{ data }, refetch] = useTypedQuery({
    query: GetDefinition,
    variables: {
      definitionId,
    },
    requestPolicy: 'network-only',
  })
  const { name, maintainers } = data?.definition || {}

  const handleAdd = useCallback(
    (ids: string[]) => {
      client
        .mutation(AddDefinitionAccess, {
          definitionId,
          userIds: ids,
        })
        .toPromise()
        .then(() => {
          setAddOpen(false)
        })
        .catch(error => {
          notify(error.message, {
            intent: 'danger',
          })
        })
    },
    [client, definitionId]
  )

  const handleRemove = useCallback(
    (ids: string[]) => {
      client
        .mutation(RemoveDefinitionAccess, {
          definitionId,
          userIds: ids,
        })
        .toPromise()
        .catch(error => {
          notify(error.message, {
            intent: 'danger',
          })
        })
    },
    [client, definitionId]
  )

  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 padded>
          <UsersSelection
            users={maintainers || []}
            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
