import React, { useState } from 'react'

import {
  Button,
  Card,
  Group,
  Stack,
  TextInput,
  ThemeIcon,
  Title,
  Tooltip,
  Modal,
  Text,
  Alert,
  LoadingOverlay
} from '@mantine/core'
import { showNotification } from '@mantine/notifications'
import { IconAlertCircle, IconQuestionMark } from '@tabler/icons-react'
import { useNavigate } from 'react-router-dom'
import useSWR from 'swr'

import { OrgUser, OrgRole } from '@clinic/client'
import {
  delOrg,
  delUser,
  inviteUser,
  orgUsers,
  updateOrg,
  editUserRole
} from '~/api'
import { useCurOrg } from '~/hooks/state'
import { useMutation } from '~/hooks/use-mutation'
import { settingsTelemetry } from '~/telemetry/settings'
import { CloudUIProvider, OnPremUIProvider } from '~/utils/tenant-type'

import InviteUersForm from './components/InviteUsersForm'
import ShareWithTable from './components/ShareWithTable'
import UsersTable from './components/UsersTable'

// TODO:
// this component is copied from DeleteClusterConfirm
// so we can extra a component to handle delete confirm: DeleteConfirm
const DeleteOrgConfirm: React.FC<{
  onCancel?: () => void
  onOK?: () => void
  processing?: boolean
}> = ({ onCancel, onOK, processing }) => {
  return (
    <Stack sx={{ position: 'relative' }}>
      <Title order={4}>Delete Org</Title>
      <Text color='dimmed'>
        This org will be deleted, along with all of its data.
      </Text>
      <Alert icon={<IconAlertCircle size={16} />} color='red'>
        This action is not reversible, please be certain.
      </Alert>
      <Group position='right'>
        <Button variant='default' onClick={onCancel}>
          Cancel
        </Button>
        <Button color='red' onClick={onOK}>
          Delete
        </Button>
      </Group>
      <LoadingOverlay visible={processing ?? false} />
    </Stack>
  )
}

const Page: React.FC = () => {
  const { curOrg, reloadCurOrg } = useCurOrg()

  // update org
  const [orgName, setOrgName] = useState(curOrg!.name)
  const updateOrgMut = useMutation(updateOrg)

  function handleUpdateOrg() {
    settingsTelemetry.editOrgName(curOrg?.id!, curOrg?.name!, orgName!)

    updateOrgMut.run(
      { oid: curOrg?.id!, org: { name: orgName } },
      () => reloadCurOrg()
      // reloadCurOrg // this usage has bug
    )
  }

  // users
  const { data: usersRes, mutate: orgUsersReload } = useSWR(
    curOrg?.id ? ['/users', curOrg.id] : null,
    () => orgUsers(curOrg?.id!)
  )

  // invite users
  const [showInviteUserModal, setShowInviteUserModal] = useState(false)
  async function handleInvite(values: any) {
    settingsTelemetry.inviteUsers(values)

    return inviteUser(curOrg?.id!, values).then(() => {
      setShowInviteUserModal(false)
      orgUsersReload()
    })
  }

  // delete user
  const delUserMut = useMutation(delUser)
  function handleDelUser(user: OrgUser) {
    settingsTelemetry.confirmDeleteInviteUser(user.userID!)

    delUserMut.run({ oid: curOrg?.id!, userId: user.userID! }, function () {
      showNotification({
        color: 'teal',
        message: `${user.userName} is removed from the organization successfully`
      })
      orgUsersReload()
    })
  }

  // edit user role
  const editUserOrgRoleMut = useMutation(editUserRole)
  function handleEditUserOrgRole(user: {
    userId: number
    userName: string
    orgRole: OrgRole
  }) {
    settingsTelemetry.editUserOrgRole(user!.userId, user.orgRole.name!)

    editUserOrgRoleMut.run(
      {
        oid: curOrg?.id!,
        userId: user.userId,
        orgRole: user.orgRole
      },
      function () {
        showNotification({
          color: 'teal',
          message: `Modify ${user.userName}'s org role successfully`
        })
        orgUsersReload()
      }
    )
  }

  // del org
  const [delOrgModalOpen, setDelOrgModalOpen] = useState(false)
  const delOrgMut = useMutation(delOrg)
  const navigate = useNavigate()

  async function handleDelOrg() {
    settingsTelemetry.confirmDeleteOrg(curOrg?.id!)

    await delOrgMut.run(curOrg?.id!, function () {
      showNotification({
        color: 'teal',
        message: `Organization ${curOrg?.name} is deleted successfully`
      })
      navigate('/orgs')
    })
    setDelOrgModalOpen(false)
  }

  return (
    <Stack>
      {/* basic info for cloud org */}
      <CloudUIProvider>
        <Card withBorder>
          <Text fw={500}>Org Name</Text>
          <Text color='dimmed' mt={2}>
            {orgName}
          </Text>
        </Card>
      </CloudUIProvider>

      {/* basic info for op org, update org */}
      <OnPremUIProvider>
        <Card withBorder>
          <Stack maw={480}>
            <TextInput
              label='Org Name'
              value={orgName}
              onChange={(e) => setOrgName(e.target.value)}
              withAsterisk
              error={orgName?.trim() === '' && 'Org name must not be empty'}
            />
          </Stack>

          <Card.Section withBorder inheritPadding mt='md' py='sm'>
            <Group position='right'>
              <Button
                onClick={handleUpdateOrg}
                loading={updateOrgMut.loading}
                disabled={orgName?.trim() === ''}
              >
                Save
              </Button>
            </Group>
          </Card.Section>
        </Card>
      </OnPremUIProvider>

      {/* share data with */}
      <Card withBorder>
        <Stack>
          <Group spacing='xs'>
            <Title order={3}>Share diagnostic data with</Title>
            <Tooltip
              withArrow
              multiline
              position='right'
              label='Support team can access the diagnostic data you uploaded for diagnostic purpose'
            >
              <ThemeIcon variant='default' size='xs' radius='xl'>
                <IconQuestionMark />
              </ThemeIcon>
            </Tooltip>
          </Group>

          <ShareWithTable />
        </Stack>
      </Card>

      {/* users */}
      <Card withBorder>
        <Stack>
          <Group position='apart'>
            <Title order={3}>Users</Title>
            <Button
              variant='default'
              size='xs'
              onClick={() => {
                settingsTelemetry.clickInviteUser()
                setShowInviteUserModal(true)
              }}
            >
              Invite Users
            </Button>
          </Group>

          <UsersTable
            users={usersRes?.data.items || []}
            onDel={handleDelUser}
            onEditUserRole={handleEditUserOrgRole}
          />
        </Stack>
      </Card>

      {/* delete org */}
      <OnPremUIProvider>
        <Card withBorder sx={(theme) => ({ borderColor: theme.colors.red[5] })}>
          <Title order={3}>Delete Org</Title>
          <Text>
            Permanently remove this org and all of its data from TiDB Clinic
            platform. This action is not reversible, so please continue with
            caution.
          </Text>

          <Card.Section withBorder inheritPadding mt='md' py='sm'>
            <Group position='right'>
              <Button
                color='red'
                loading={delOrgMut.loading}
                onClick={() => {
                  settingsTelemetry.clickDeleteOrg()
                  setDelOrgModalOpen(true)
                }}
              >
                Delete
              </Button>
            </Group>
          </Card.Section>
        </Card>
      </OnPremUIProvider>

      {/* invite new users modal */}
      <Modal
        title='Invite New Users'
        opened={showInviteUserModal}
        onClose={() => setShowInviteUserModal(false)}
      >
        <InviteUersForm onInvite={handleInvite} />
      </Modal>

      {/* confirm delete org modal */}
      <Modal
        opened={delOrgModalOpen}
        withCloseButton={false}
        onClose={() => setDelOrgModalOpen(false)}
      >
        <DeleteOrgConfirm
          onCancel={() => setDelOrgModalOpen(false)}
          onOK={handleDelOrg}
          processing={delOrgMut.loading}
        />
      </Modal>
    </Stack>
  )
}

export default Page
