import { Button, Card, Divider, Group, Modal, ScrollArea, SimpleGrid, Stack, Text, Typography } from '@tidbcloud/uikit'
import { PropertyCard } from '@tidbcloud/uikit/biz'
import { capitalize } from 'lodash-es'
import { observer } from 'mobx-react'
import { useMemo, useState } from 'react'
import { useFormContext } from 'react-hook-form'
import { useHistory } from 'react-router-dom'

import { FormErrorMessage } from 'dbaas/components/Form'
import { getModeLabel } from 'dbaas/features/DataMigration'
import type { PremiumDMFormData } from 'dbaas/screens/DataMigration/CreateDataMigrationPremium.types'
import SelectedObjects from 'dbaas/screens/DataMigration/DMJobDetail/SelectedObject'
import type { PremiumStep1FormData } from 'dbaas/screens/DataMigration/steps/Step1/PremiumDMStep1'
import type { PremiumStep2FormData } from 'dbaas/screens/DataMigration/steps/Step2/PremiumDMStep2'
import { useSharedTiDBContext } from 'dbaas/screens/NextGen/tidb-mgmt-container/shared/tidb-context'
import { useCreatePremiumMigration } from 'dbaas/services/dataflow'
import { getErrorMessage } from 'dbaas/services/errorCodes'
import { eventTracking } from 'dbaas/utils/tracking'

export type PremiumStep4FormData = Pick<
  PremiumStep1FormData,
  | 'name'
  | 'data_source'
  | 'connect_method'
  | 'connect_method_display_name'
  | 'host'
  | 'sink_endpoint_id'
  | 'sink_endpoint_name'
  | 'port'
  | 'username'
  | 'ssl'
  | 'cluster_username'
  | 'cluster_password'
> &
  Pick<
    PremiumStep2FormData,
    'migration_mode' | 'selectObjectMethod' | 'sources' | 'import_mode' | 'full_instance_migrate'
  >

const Step4 = ({ onCancel, onGoPrev }: { onCancel: () => void; onGoPrev: () => void }) => {
  const tidb = useSharedTiDBContext()
  const history = useHistory()
  const { handleSubmit, watch, getValues } = useFormContext<PremiumDMFormData>()
  const [modalOpen, setModalOpen] = useState(false)
  const [errorMessage, setErrorMessage] = useState('')

  const createMigrationMutation = useCreatePremiumMigration()

  const formData = getValues() as PremiumStep4FormData
  const migrationMode = watch('migration_mode')
  const isPrivateConnect = formData.connect_method?.toLowerCase().includes('private')

  const jobType = useMemo(() => {
    return getModeLabel(migrationMode)
  }, [migrationMode])

  const selectedObjectRules = useMemo(() => {
    const rules = formData.sources?.[0]?.premium_migration_rules
    if (!rules?.length) return undefined
    const doDbs = new Set<string>()
    const doTables: Array<{ schema: string; table?: string }> = []

    rules.forEach((rule) => {
      const schema = rule.source_table?.schema_pattern
      if (!schema) return
      const table = rule.source_table?.table_pattern
      if (!table || table === '*') {
        doDbs.add(schema)
        return
      }
      doTables.push({ schema, table })
    })

    return {
      do_dbs: doDbs.size ? Array.from(doDbs) : undefined,
      do_tables: doTables.length ? doTables : undefined
    }
  }, [formData.sources])

  const onSubmit = async (data: PremiumStep4FormData) => {
    setErrorMessage('')

    try {
      const response = await createMigrationMutation.mutateAsync({
        tidbId: tidb.tidbId!,
        data: {
          display_name: data.name,
          sources: data.sources,
          import_mode: data.import_mode,
          target: {
            user: data.cluster_username,
            password: data.cluster_password
          },
          mode: data.migration_mode
        }
      })

      eventTracking('Premium DM Job Created')
      history.push(`/tidbs/${tidb.tidbId}/data-migration/${response.migration_id}`)
    } catch (error) {
      setErrorMessage(getErrorMessage(error, true) || 'Failed to create migration job')
    }
  }

  return (
    <Card withBorder shadow="none" p={0}>
      <form onSubmit={handleSubmit((values) => onSubmit(values as PremiumStep4FormData))}>
        <Stack m={24}>
          <Typography variant="headline-sm">Job Configuration</Typography>

          <Stack>
            <PropertyCard.Item label="Name">
              <Typography c="carbon.9">{formData.name}</Typography>
            </PropertyCard.Item>

            <PropertyCard.Item label="Type">
              <Typography c="carbon.9">{jobType}</Typography>
            </PropertyCard.Item>
          </Stack>
        </Stack>

        <Divider />

        <Stack m={24}>
          <Typography variant="headline-sm">Source Connection Profile</Typography>

          <SimpleGrid cols={2}>
            <PropertyCard.Item label="Data Source">
              <Typography c="carbon.9">{formData.data_source}</Typography>
            </PropertyCard.Item>

            {isPrivateConnect ? (
              <PropertyCard.Item label="Private Endpoint" labelProps={{ miw: 140 }}>
                <Typography c="carbon.9">{formData.sink_endpoint_name ?? formData.sink_endpoint_id ?? '-'}</Typography>
              </PropertyCard.Item>
            ) : (
              <PropertyCard.Item label="Host" labelProps={{ miw: 140 }}>
                <Typography c="carbon.9">{formData.host}</Typography>
              </PropertyCard.Item>
            )}

            <PropertyCard.Item label="Port">
              <Typography c="carbon.9">{formData.port}</Typography>
            </PropertyCard.Item>

            <PropertyCard.Item label="Connectivity Method" labelProps={{ miw: 140 }}>
              <Typography c="carbon.9">{formData.connect_method_display_name}</Typography>
            </PropertyCard.Item>

            <PropertyCard.Item label="Username">
              <Typography c="carbon.9">{formData.username}</Typography>
            </PropertyCard.Item>

            <PropertyCard.Item label="SSL/TLS" labelProps={{ miw: 140 }}>
              <Typography c="carbon.9">{formData.ssl ? 'Enabled' : 'Disabled'}</Typography>
            </PropertyCard.Item>

            <PropertyCard.Item label="Selected Objects">
              {formData.selectObjectMethod === 'customize' ? (
                <a onClick={() => setModalOpen(true)}>Show Detail</a>
              ) : (
                <Typography c="carbon.9">All</Typography>
              )}
            </PropertyCard.Item>

            <PropertyCard.Item label="Import Mode" labelProps={{ miw: 140 }}>
              <Typography c="carbon.9">
                {formData.import_mode ? capitalize(formData.import_mode.replace('IMPORTMODE_', '')) : '-'}
              </Typography>
            </PropertyCard.Item>
          </SimpleGrid>
        </Stack>

        <Divider />

        <Stack m={24}>
          <Typography variant="headline-sm">Target Connection Profile</Typography>

          <SimpleGrid cols={2}>
            <PropertyCard.Item label="Region">
              <Typography c="carbon.9">{tidb.regionDisplayName}</Typography>
            </PropertyCard.Item>

            <PropertyCard.Item label="Cluster ID">
              <Typography c="carbon.9">{tidb.tidbId}</Typography>
            </PropertyCard.Item>

            <PropertyCard.Item label="Cluster Name">
              <Typography c="carbon.9">{tidb.displayName}</Typography>
            </PropertyCard.Item>

            <PropertyCard.Item label="Username">
              <Typography c="carbon.9">{formData.cluster_username}</Typography>
            </PropertyCard.Item>
          </SimpleGrid>
        </Stack>

        <Divider />

        <FormErrorMessage message={errorMessage} />

        <Group m={24} justify="flex-end" gap={12}>
          <Button variant="default" type="button" onClick={onCancel}>
            Cancel
          </Button>

          <Button variant="outline" type="button" onClick={onGoPrev}>
            Previous
          </Button>

          <Button type="submit" loading={createMigrationMutation.isLoading}>
            Create Job and Start
          </Button>
        </Group>
      </form>

      <Modal
        opened={modalOpen}
        centered
        size="xl"
        title={
          <Text fw={700} fz={20}>
            Selected Migration Objects
          </Text>
        }
        onClose={() => setModalOpen(false)}
      >
        <ScrollArea.Autosize mah={300}>
          <SelectedObjects rules={selectedObjectRules} />
        </ScrollArea.Autosize>
      </Modal>
    </Card>
  )
}

export const PremiumDMStep4 = observer(Step4)
