import {
  Box,
  Card,
  Dropzone,
  Group,
  LoadingOverlay,
  Menu,
  MIME_TYPES,
  notifier,
  Stack,
  Typography
} from '@tidbcloud/uikit'
import {
  IconCheckCircle,
  IconChevronUp,
  IconDatabaseCloud,
  IconFileImport02,
  IconLinkExternal01,
  IconXCircle
} from '@tidbcloud/uikit/icons'
import { rgba } from '@tidbcloud/uikit/utils'
import { observer } from 'mobx-react'
import { useState } from 'react'

import { AccessCheck, AccessDeniedHoverHint } from 'dbaas/contexts/access-control'
import { CloudProvider, CloudProviderConst } from 'dbaas/features/Project'
import { MAX_UPLOAD_FILE_SIZE } from 'dbaas/screens/DataImportV2/constant'

export const ImportDropzone = ({
  onNavigateToImportCreation,
  showDropzone = false,
  onDropFile = () => {},
  isInvalid = false,
  mysqlCliDocLink,
  accessCheckProps
}: {
  showDropzone?: boolean
  onNavigateToImportCreation: (from: CloudProvider | (string & {})) => void
  onDropFile?: (file: File[]) => void
  isInvalid?: boolean
  mysqlCliDocLink?: string
  accessCheckProps: Omit<Parameters<typeof AccessCheck>[0], 'children'>
}) => {
  const [menuOpened, setMenuOpened] = useState(false)

  const goToCreateImport = (from: CloudProvider | (string & {})) => {
    onNavigateToImportCreation(from)
    setTimeout(() => {
      notifier.clear()
    }, 300)
  }

  const maxWidth = 'calc(50%)'

  return (
    <Group sx={{ position: 'relative' }} wrap="wrap">
      <LoadingOverlay
        visible={isInvalid}
        loaderProps={{ children: <div /> }}
        overlayProps={{ opacity: 0.7 }}
        sx={{ cursor: 'not-allowed' }}
      />

      {showDropzone && (
        <Box sx={{ flex: 1, flexShrink: 1, minWidth: 396, maxWidth: maxWidth, position: 'relative' }}>
          <AccessDeniedHoverHint
            {...accessCheckProps}
            reason={{
              targetWrapperProps: {
                sx: { display: 'block' }
              }
            }}
          >
            {({ accessible }) => (
              <>
                {!accessible && <Box sx={{ position: 'absolute', inset: 0, zIndex: 1, cursor: 'not-allowed' }} />}
                <Dropzone
                  data-testid="import-dropzone"
                  multiple={false}
                  maxFiles={1}
                  onDrop={onDropFile}
                  onReject={(errors) => {
                    if (errors.length > 1) {
                      notifier.warn('Only one file is supported')
                      return
                    }
                    const error = errors[0]
                    const size = error.file.size
                    if (size > MAX_UPLOAD_FILE_SIZE.value) {
                      notifier.warn(
                        <span>
                          The file exceeds the {MAX_UPLOAD_FILE_SIZE.label} limit for local upload. Please upload the
                          file to other cloud storage and then import data to TiDB Cloud from Clound Stroage.
                        </span>
                      )
                    }
                  }}
                  styles={(theme) => {
                    const backgroundColor = theme.colors.carbon[2]
                    return {
                      root: {
                        padding: `24px 16px`,
                        overflow: 'hidden',
                        backgroundColor,
                        borderWidth: 1,
                        borderColor: theme.colors.carbon[6],
                        boxShadow: `${rgba(theme.colors.carbon[9], 0.04)} 0px 2px 4px`,
                        opacity: accessible ? 1 : 0.7,
                        cursor: accessible ? 'pointer' : 'not-allowed',
                        '&:hover': {
                          backgroundColor
                        },
                        '&[data-accept]': {
                          backgroundColor: theme.colors.peacock[1],
                          borderColor: theme.colors.peacock[7],

                          '& .mantine-Text-root': {
                            color: theme.colors.peacock[7]
                          }
                        },
                        '&[data-reject]': {
                          backgroundColor: theme.colors.red[1],
                          borderColor: theme.colors.red[7],

                          '& .mantine-Text-root': {
                            color: theme.colors.red[7]
                          }
                        }
                      }
                    }
                  }}
                  maxSize={MAX_UPLOAD_FILE_SIZE.value}
                  accept={[MIME_TYPES.csv]}
                >
                  <Group style={{ pointerEvents: 'none' }} wrap="nowrap">
                    <Dropzone.Accept>
                      <IconCheckCircle size={24} c="peacock.7" sx={{ flexShrink: 0 }} />
                    </Dropzone.Accept>
                    <Dropzone.Reject>
                      <IconXCircle size={24} c="red.7" sx={{ flexShrink: 0 }} />
                    </Dropzone.Reject>
                    <Dropzone.Idle>
                      <IconFileImport02 size={24} strokeWidth={1.5} c="gray.7" sx={{ flexShrink: 0 }} />
                    </Dropzone.Idle>

                    <Stack gap={0} data-testid="import-dropzone-title">
                      <Typography variant="title-md">Upload a local file</Typography>
                      <Typography variant="body-lg" truncate>
                        Click or drop a CSV file less than {MAX_UPLOAD_FILE_SIZE.label} to upload
                      </Typography>
                    </Stack>
                  </Group>
                </Dropzone>
              </>
            )}
          </AccessDeniedHoverHint>
        </Box>
      )}

      <Menu width="target" onOpen={() => setMenuOpened(true)} onClose={() => setMenuOpened(false)} disabled>
        <Menu.Target>
          <Box sx={{ flex: 1, minWidth: 340, maxWidth }}>
            <AccessDeniedHoverHint
              {...accessCheckProps}
              reason={{
                targetWrapperProps: {
                  sx: { display: 'block' }
                }
              }}
            >
              {({ accessible }) => (
                <Card
                  onClick={() => {
                    if (!accessible) {
                      return
                    }
                    goToCreateImport('')
                  }}
                  mod={{
                    invalid: !!isInvalid,
                    disabled: !accessible
                  }}
                  py="xl"
                  px="md"
                  sx={(theme, u) => ({
                    cursor: 'pointer',
                    '&[data-disabled]': {
                      cursor: 'not-allowed',
                      maxWidth: 'initial',
                      '&:not([data-invalid])': {
                        opacity: 0.7,
                        backgroundColor: rgba(theme.colors.carbon[0], 0.75),
                        [u.dark]: {
                          backgroundColor: rgba(theme.colors.carbon[4], 0.75)
                        }
                      }
                    }
                  })}
                >
                  <Group wrap="nowrap">
                    <IconDatabaseCloud size={24} c="gray.7" strokeWidth={1.5} sx={{ flexShrink: 0 }} />

                    <Group justify="space-between" wrap="nowrap" flex={1}>
                      <Stack gap={0} sx={{ userSelect: 'none' }}>
                        <Typography variant="title-md">Import data from Cloud Storage</Typography>
                        <Typography variant="body-lg" truncate>
                          Support CSV, Parquet, and SQL files
                        </Typography>
                      </Stack>

                      {false && (
                        <IconChevronUp
                          size={24}
                          c="carbon.8"
                          sx={{
                            transform: menuOpened ? 'rotate(0deg)' : 'rotate(-180deg)',
                            transition: 'transform 0.3s'
                          }}
                        />
                      )}
                    </Group>
                  </Group>
                </Card>
              )}
            </AccessDeniedHoverHint>
          </Box>
        </Menu.Target>
        <Menu.Dropdown>
          <Menu.Item onClick={() => goToCreateImport(CloudProviderConst.ALICLOUD)}>Alibaba Cloud OSS</Menu.Item>
          <Menu.Item onClick={() => goToCreateImport(CloudProviderConst.AWS)}>Amazon S3</Menu.Item>
          <Menu.Item onClick={() => goToCreateImport(CloudProviderConst.GCP)}>Google Cloud Storage</Menu.Item>
          <Menu.Item onClick={() => goToCreateImport(CloudProviderConst.AZURE)}>Azure Blob Storage</Menu.Item>
        </Menu.Dropdown>
      </Menu>

      <Card
        py={24}
        px={16}
        miw={230}
        maw={maxWidth}
        sx={{ flex: 1, cursor: 'pointer' }}
        onClick={() => {
          window.open(mysqlCliDocLink)
        }}
      >
        <Group wrap="nowrap">
          <IconLinkExternal01 size={24} c="gray.7" strokeWidth={1.5} sx={{ flexShrink: 0 }} />
          <Stack gap={0} sx={{ userSelect: 'none' }}>
            <Typography variant="title-md">Third Party Tools</Typography>
            <Typography variant="body-lg" truncate>
              Use MySQL CLI to import data
            </Typography>
          </Stack>
        </Group>
      </Card>
    </Group>
  )
}

export default observer(ImportDropzone)
