import { Typography, Stack, Card, Group, ActionIcon, Box, Button, Alert } from '@tidbcloud/uikit'
import { FormSelect, FormTextInput } from '@tidbcloud/uikit/biz'
import { IconAlertCircle, IconPlus, IconTrash01 } from '@tidbcloud/uikit/icons'
import { useMemo } from 'react'
import { useForm, useFieldArray, FormProvider, DeepPartial, DeepRequired } from 'react-hook-form'

import { DataFormat, DataSourceType } from 'dbaas/features/Import'
import { validateBucketURI } from 'dbaas/features/Import/validator'
import { CreateImportBody } from 'dbaas/services/dataflow/interface'

export type MappingFormData = DeepRequired<Pick<CreateImportBody, 'target_table_infos'>>

export const Mapping = ({
  tableData,
  onCancel,
  onReset,
  onConfirm,
  defaultValues,
  sourceType,
  dataFormat
}: {
  tableData?: {
    schema_name?: string
    tables?: {
      schema_name?: string
      table_name?: string
    }[]
  }[]
  sourceType: DataSourceType
  dataFormat: DataFormat
  defaultValues?: DeepPartial<MappingFormData>
  onCancel: () => void
  onReset: () => void
  onConfirm: (mapping: MappingFormData) => void
}) => {
  const methods = useForm<MappingFormData>({
    defaultValues: {
      ...defaultValues,
      target_table_infos: [
        ...(defaultValues?.target_table_infos ?? []),
        {
          target_table: {
            schema: '',
            table: ''
          },
          custom_file: ''
        }
      ]
    }
  })
  const { control, watch, handleSubmit, reset } = methods
  const { fields, append, remove } = useFieldArray({
    control,
    name: 'target_table_infos'
  })
  const tableMappings = watch('target_table_infos')

  const dbSelectData = useMemo(() => {
    return tableData?.map((i) => ({ label: i.schema_name!, value: i.schema_name! })) ?? []
  }, [tableData])

  return (
    <Stack>
      {dataFormat === DataFormat.aurora && (
        <Alert color="yellow" icon={<IconAlertCircle size={14} />}>
          It is not available when importing Aurora Snapshots.
        </Alert>
      )}

      {tableData?.length === 0 && (
        <Alert color="yellow" icon={<IconAlertCircle size={14} />}>
          Please select the tables you want to import data first
        </Alert>
      )}

      <Typography variant="body-md">
        Configure the mapping relationships between the source files and the target tables, learn more about{' '}
        <a
          href="https://docs.pingcap.com/tidbcloud/import-csv-files#step-4-import-csv-files-to-tidb-cloud"
          target="_blank"
          rel="noopener noreferrer"
        >
          Mapping
        </a>
        .
      </Typography>

      <FormProvider {...methods}>
        <form onSubmit={handleSubmit(onConfirm)}>
          <Card withBorder p={0} shadow="unset">
            <Group
              p={16}
              justify="space-between"
              wrap="nowrap"
              bg="carbon.1"
              sx={(theme) => ({ borderBottom: `1px solid ${theme.colors.carbon[4]}` })}
            >
              <Typography variant="label-lg" w="22%">
                Target Database
              </Typography>
              <Typography variant="label-lg" w="22%">
                Target Tables
              </Typography>
              <Typography variant="label-lg" w="44%">
                Source File URIs and Names
              </Typography>
              <Typography variant="label-lg" w="11%" ta="center">
                Actions
              </Typography>
            </Group>

            {fields.map((field, index) => (
              <Group px={16} py={8} justify="space-between" wrap="nowrap" key={field.id} align="flex-start">
                <FormSelect
                  name={`target_table_infos.${index}.target_table.schema`}
                  data={dbSelectData}
                  rules={{ required: 'Required' }}
                  size="xs"
                  w="22%"
                  placeholder="db1"
                  searchable
                />
                <FormSelect
                  name={`target_table_infos.${index}.target_table.table`}
                  data={
                    tableData
                      ?.find((i) => i.schema_name === tableMappings?.[index]?.target_table?.schema)
                      ?.tables?.map((i) => ({
                        label: i.table_name!,
                        value: i.table_name!,
                        disabled: tableMappings?.some(
                          (item) =>
                            item.target_table?.schema === i.schema_name && item.target_table?.table === i.table_name
                        )
                      })) ?? []
                  }
                  rules={{ required: 'Required' }}
                  size="xs"
                  w="22%"
                  placeholder="table1"
                  searchable
                />
                <FormTextInput
                  name={`target_table_infos.${index}.custom_file`}
                  rules={{
                    required: 'Required',
                    validate: (val) => validateBucketURI(val, { sourceType: sourceType! })
                  }}
                  size="xs"
                  w="44%"
                  placeholder="s3://sampledate/injest/TableName.01.csv"
                />
                <Group w="11%" justify="center">
                  <ActionIcon variant="default" onClick={() => remove(index)}>
                    <Box component={IconTrash01} c="carbon.8" size={13} />
                  </ActionIcon>
                </Group>
              </Group>
            ))}

            <Group
              pl={16}
              pb={8}
              pt={8}
              pr={38}
              justify="flex-end"
              sx={(theme) => ({ borderTop: `1px solid ${theme.colors.carbon[4]}` })}
            >
              <ActionIcon
                variant="default"
                onClick={() =>
                  append({
                    target_table: {
                      schema: '',
                      table: ''
                    },
                    custom_file: '',
                    matched_uri: ''
                  })
                }
              >
                <Box component={IconPlus} c="carbon.8" size={16} />
              </ActionIcon>
            </Group>
          </Card>

          <Group justify="flex-end" mt={16}>
            <Button variant="default" type="button" onClick={onCancel} data-mp-event="Cancel Mapping Settings Clicked">
              Cancel
            </Button>
            <Button
              variant="default"
              type="button"
              onClick={() => {
                reset()
                onReset()
              }}
              data-mp-event="Reset Mapping Settings Clicked"
            >
              Reset
            </Button>
            <Button
              type="submit"
              data-mp-event="Confirm Mapping Settings Clicked"
              disabled={tableData?.length === 0 || dataFormat === DataFormat.aurora || tableMappings?.length === 0}
            >
              Confirm
            </Button>
          </Group>
        </form>
      </FormProvider>
    </Stack>
  )
}
