import { Alert, Box, Button, Card, Divider, Group, Stack, Tabs } from '@tidbcloud/uikit'
import { FormRadioGroup } from '@tidbcloud/uikit/biz'
import { IconAlertCircle } from '@tidbcloud/uikit/icons'
import { useMemoizedFn } from 'ahooks'
import { useRef, useState } from 'react'
import { useFormContext } from 'react-hook-form'
import { useQuery } from 'react-query'

import TableFilterV2 from 'dbaas/components/TableFilter/TableFilterV2'
import { areValidEventFilters } from 'dbaas/features/Changefeed'
import { SharedCluster } from 'dbaas/features/ClusterManagement/cluster'
import { useOrgProjectClusterIds } from 'dbaas/features/Common'
import { ColumnSelector } from 'dbaas/screens/Changefeed/CreateOrEditChangefeed/step2/ColumnSelector'
import { EventFilter } from 'dbaas/screens/Changefeed/CreateOrEditChangefeed/step2/EventFilter'
import {
  useChangefeedServiceDescribeSchemaTable,
  useChangefeedServiceTestChangefeed
} from 'dbaas/services/api-clients/legacy/serverless'
import {
  ChangefeedTypeEnum,
  EventFilterRule,
  KafkaColumnSelector,
  TableModeEnum
} from 'dbaas/services/api-clients/legacy/serverless/interface'
import { getErrorMessage } from 'dbaas/services/errorCodes'
import { eventTracking } from 'dbaas/utils/tracking'

import type { CreateOrEditChangefeedEssentialFormData } from '../types'

import { FormKafkaReplicationEssential } from './FormKafka'
import { FormMySQLReplicationEssential } from './FormMySQL'

const TableModeOptions = [
  {
    label: 'Only replicate tables with valid keys (recommended)',
    value: TableModeEnum.IGNORE_NOT_SUPPORT_TABLE
  },
  {
    label: 'Replicate all selected tables.',
    value: TableModeEnum.FORCE_SYNC
  }
]

export const ConfigureReplicaEssential = ({
  onFinish,
  onCancel,
  onGoPrev,
  cluster
}: {
  onFinish: () => void
  onGoPrev: () => void
  onCancel: () => void
  cluster: SharedCluster
}) => {
  const { orgId, projectId } = useOrgProjectClusterIds()
  const methods = useFormContext<CreateOrEditChangefeedEssentialFormData>()
  const containerRef = useRef<HTMLDivElement>(null)
  const [filterTab, setFilterTab] = useState<'table-filter' | 'event-filter' | 'column-selectors'>('table-filter')
  const [eventFilterValidateError, setEventFilterValidateError] = useState(false)
  const [columnSelectorsValidateError, setColumnSelectorsValidateError] = useState(false)
  const [filterApplyKey, setFilterApplyKey] = useState(0)
  const { handleSubmit, setValue, watch, getValues } = methods
  const filterRules = watch('filter.filter_rule') ?? []
  const changefeedType = watch('changefeed_type')
  const columnSelectors = watch('kafka.column_selectors')
  const caseSensitive = watch('filter.case_sensitive') ?? false
  const defaultFilter = getValues('filter')

  const testChangefeedMutation = useChangefeedServiceTestChangefeed({
    mutation: { retry: false },
    request: { timeout: 120 * 1000 }
  })
  const error = testChangefeedMutation.error

  const describeSchemaTable = useChangefeedServiceDescribeSchemaTable()
  const {
    data: describeSchemaTableData,
    isFetching: isLoadingDescribeSchemaTable,
    error: describeSchemaTableError
  } = useQuery({
    queryKey: ['describeSchemaTable', orgId, projectId, cluster.id, filterRules, caseSensitive, filterApplyKey],
    queryFn: () =>
      describeSchemaTable.mutateAsync({
        orgId,
        projectId,
        clusterId: cluster.id!,
        data: {
          filter_rules: filterRules,
          case_sensitive: caseSensitive
        }
      }),
    enabled: filterRules.length > 0,
    refetchOnWindowFocus: false,
    refetchOnReconnect: false,
    refetchOnMount: false,
    keepPreviousData: true
  })
  const onTableFilterChange = useMemoizedFn((rules: string[]) => {
    setValue('filter.filter_rule', rules)
    setFilterApplyKey((value) => value + 1)
  })

  const onEventFilterChange = useMemoizedFn((rules: EventFilterRule[]) => {
    setValue('filter.event_filter_rule', rules)
  })

  const onColumnSelectorsChange = useMemoizedFn((selectors: KafkaColumnSelector[]) => {
    setValue('kafka.column_selectors', selectors)
  })

  const onSubmit = async (data: CreateOrEditChangefeedEssentialFormData) => {
    // Validate event filters
    const eventFiltersRules = data.filter.event_filter_rule
    if (eventFiltersRules && eventFiltersRules.length > 0) {
      if (areValidEventFilters(eventFiltersRules)) {
        setEventFilterValidateError(false)
      } else {
        setFilterTab('event-filter')
        setEventFilterValidateError(true)
        containerRef.current?.scrollIntoView({ behavior: 'smooth' })
        return
      }
    }

    // Validate column selectors (only for Kafka)
    if (changefeedType === ChangefeedTypeEnum.KAFKA) {
      const columnSelectorsData = data.kafka.column_selectors
      if (columnSelectorsData && columnSelectorsData.length > 0) {
        if (
          columnSelectorsData.every(
            (i) => i.matcher && i.matcher.length > 0 && i.columns && i.columns.filter(Boolean).length > 0
          )
        ) {
          setColumnSelectorsValidateError(false)
        } else {
          setFilterTab('column-selectors')
          setColumnSelectorsValidateError(true)
          containerRef.current?.scrollIntoView({ behavior: 'smooth' })
          return
        }
      }
    }

    try {
      onFinish()
    } catch (_e) {
      eventTracking('Failed when precheck in changefeed', {
        'Cluster Type': 'Essential'
      })
    }
  }

  return (
    <Card p={0}>
      <form onSubmit={handleSubmit(onSubmit)}>
        <Box ref={containerRef}></Box>

        <Tabs p={24} value={filterTab} onChange={(value) => setFilterTab(value as any)}>
          <Tabs.List>
            <Tabs.Tab value="table-filter">Table Filter</Tabs.Tab>
            <Tabs.Tab value="event-filter">Event Filter</Tabs.Tab>
            {changefeedType === 'KAFKA' && <Tabs.Tab value="column-selectors">Column Selector</Tabs.Tab>}
          </Tabs.List>

          <Tabs.Panel value="table-filter" pt="xs">
            <Stack>
              <FormRadioGroup label="Replication Scope" name="filter.mode" data={TableModeOptions} />

              <TableFilterV2
                tablesWithValidKeys={describeSchemaTableData?.handle_key_tables || []}
                tablesWithoutValidKeys={describeSchemaTableData?.non_handle_key_tables || []}
                defaultRules={filterRules}
                onChange={onTableFilterChange}
                error={describeSchemaTableError}
                loading={isLoadingDescribeSchemaTable}
                placeholder="Enter one filter rule per line"
              />
            </Stack>
          </Tabs.Panel>

          <Tabs.Panel value="event-filter" pt="xs">
            <EventFilter
              defaultValue={defaultFilter.event_filter_rule ?? []}
              onChange={onEventFilterChange}
              validateError={eventFilterValidateError}
              simpleMode
            />
          </Tabs.Panel>

          <Tabs.Panel value="column-selectors" pt="xs">
            <ColumnSelector
              defaultValue={columnSelectors ?? []}
              onChange={onColumnSelectorsChange}
              validateError={columnSelectorsValidateError}
            />
          </Tabs.Panel>
        </Tabs>

        <Divider />

        {changefeedType === 'KAFKA' && (
          <FormKafkaReplicationEssential cluster={cluster} schemaTableData={describeSchemaTableData} />
        )}
        {changefeedType === 'MYSQL' && <FormMySQLReplicationEssential schemaTableData={describeSchemaTableData} />}

        {error && (
          <Alert icon={<IconAlertCircle size={16} />} color="red" m={24}>
            <Box
              sx={{ wordBreak: 'break-all' }}
              dangerouslySetInnerHTML={{
                __html: getErrorMessage(error)
              }}
            />
          </Alert>
        )}

        <Divider />

        <Group m={24} justify="flex-end">
          <Button
            variant="default"
            type="button"
            onClick={onCancel}
            data-mp-event="Configure Replica Cancel Button Clicked"
          >
            Cancel
          </Button>
          <Button
            variant="default"
            type="button"
            onClick={onGoPrev}
            data-mp-event="Configure Replica Previous Button Clicked"
          >
            Previous
          </Button>
          <Button
            type="submit"
            loading={testChangefeedMutation.isLoading}
            data-mp-event="Configure Replica Next Button Clicked"
          >
            Next
          </Button>
        </Group>
      </form>
    </Card>
  )
}
