import { Loader } from '@tidbcloud/uikit'
import { useMemoizedFn, useSetState } from 'ahooks'
import { mergeWith } from 'lodash-es'
import { observer } from 'mobx-react'
import { useMemo, useState } from 'react'
import { useHistory } from 'react-router-dom'

import StepsWizard from 'dbaas/components/StepsWizard'
import { useGetConnector } from 'dbaas/services/dataflow'
import useStores from 'dbaas/stores/useStores'
import { eventTracking } from 'dbaas/utils/tracking'
import { useGetClusterOnInitialLoad } from 'dbaas/utils/useGetClusterOnload'

import { ConfigureTarget } from './step1'
import { ConfigureReplica } from './step2'
import { Review } from './step3'
import type { FormData } from './types'

/**
 * This component is used to create or edit a changefeed.
 *
 * For editing, there are 3 parts that are not allowed to be updated:
 * 1. network info
 * 2. replication->start replication position
 * 3. specification->rcu
 *
 * For more details, please refer to: https://pingcap.feishu.cn/wiki/Swz9wtI3ii1COek2AjzcdpN0n1g
 */
const CreateChangefeed = () => {
  useGetClusterOnInitialLoad()
  const [step, setStep] = useState(0)
  const history = useHistory()

  const [formData, setFormData] = useSetState<FormData>({})
  const {
    store: { tenantData, activeProjectId, currentCluster }
  } = useStores()
  const cluster = currentCluster!

  const urlSearchParams = useMemo(() => new URLSearchParams(window.location.search), [])
  const connectorIdFromUrl = urlSearchParams.get('id') as string
  const duplicateFromId = urlSearchParams.get('from_id') as string
  const isDuplicating = Boolean(duplicateFromId)
  const { isFetching } = useGetConnector(
    tenantData.id,
    activeProjectId,
    currentCluster?.id!,
    connectorIdFromUrl || duplicateFromId,
    {
      query: {
        enabled:
          !!tenantData.id && !!activeProjectId && !!currentCluster?.id && (!!connectorIdFromUrl || !!duplicateFromId),
        refetchOnWindowFocus: false,
        refetchOnReconnect: false,
        onSuccess(data) {
          setFormData({
            connector_id: isDuplicating ? undefined : data.connector_id,
            connector_type: data.connector_type,
            mysql_info: data.request?.mysql_info,
            kafka_info: data.request?.kafka_info,
            serverless_tidb_info: data.request?.serverless_tidb_info,
            s3_info: data.request?.s3_info,
            gcs_info: data.request?.gcs_info,
            azure_blob_storage_info: data.request?.azure_blob_storage_info,
            name: isDuplicating ? `${data.request?.name}_copy` : data.request?.name,
            changefeed_instance_type: data.changefeed_instance_type,
            network_info: data.request?.network_info,
            pulsar_info: data.request?.pulsar_info
          })
        }
      }
    }
  )

  const onFinish = useMemoizedFn((data, toStep?: number) => {
    setFormData((prev) =>
      mergeWith({}, prev, data, (_, srcObj, _key) => {
        if (Array.isArray(srcObj)) {
          return srcObj
        }
      })
    )
    setStep((s) => toStep ?? s + 1)
  })
  const onGoPrev = useMemoizedFn(() => {
    setStep((s) => s - 1)
  })
  const onCancel = useMemoizedFn(() => {
    eventTracking('Cancel changefeed creating')
    history.push(`/clusters/${cluster?.id}/changefeed`)
  })

  const stepItems = [
    {
      name: 'Destination',
      content: (
        <ConfigureTarget
          formData={formData}
          cluster={cluster}
          onFinish={useMemoizedFn((data) => onFinish(data, 1))}
          onCancel={onCancel}
        />
      )
    },
    {
      name: 'Replication',
      content: (
        <ConfigureReplica
          formData={formData}
          cluster={cluster}
          onFinish={onFinish}
          onGoPrev={onGoPrev}
          onCancel={onCancel}
        />
      )
    },

    {
      name: 'Specification and Review',
      content: <Review cluster={cluster} formData={formData} onGoPrev={onGoPrev} onCancel={onCancel} />
    }
  ]

  if (!cluster || isFetching) {
    return <Loader size="xs" />
  }

  return <StepsWizard steps={stepItems} current={step} />
}

export default observer(CreateChangefeed)
