import { Box, Group, HoverCard, Radio, Stack, Typography } from '@tidbcloud/uikit'
import { DateTimePicker, DEFAULT_TIME_FORMAT_WITH_TIMEZONE, FormTextInput } from '@tidbcloud/uikit/biz'
import { IconInfoCircle } from '@tidbcloud/uikit/icons'
import dayjs from 'dayjs'
import { useMemo } from 'react'
import { Controller, useFormContext } from 'react-hook-form'

import { useIsEditingChangefeed } from 'dbaas/features/Changefeed'
import { tso2date } from 'dbaas/features/Changefeed/tso'
import {
  DescribeSchemaTableResp,
  StartModeEnum,
  StartPosition
} from 'dbaas/services/api-clients/legacy/serverless/interface'

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

const StartPositionOptions = [
  {
    text: `From now on`,
    value: StartModeEnum.FROM_NOW
  },
  {
    text: `From a specific TSO`,
    value: StartModeEnum.FROM_TSO
  },
  {
    text: `From a specific time`,
    value: StartModeEnum.FROM_TIME
  }
]

interface FormStartPositionEssentialProps {
  disabled?: boolean
  schemaTableData?: DescribeSchemaTableResp
}

export function getStartPosition(data?: StartPosition) {
  const startPosition: StartPosition = {
    mode: data?.mode
  }
  if (data?.mode === StartModeEnum.FROM_TSO) {
    startPosition.tso = data.tso
  }
  if (data?.mode === StartModeEnum.FROM_TIME) {
    startPosition.time = data.time
  }

  return startPosition
}

export function useTsoDescription(tso: string) {
  return useMemo(() => {
    const tsoDate = tso ? tso2date(tso) : undefined
    if (!tsoDate) return undefined

    // is future time
    if (dayjs(tsoDate).isAfter(new Date())) {
      return `This corresponds to a future time: ${dayjs(tsoDate).format(DEFAULT_TIME_FORMAT_WITH_TIMEZONE)}`
    }

    return `This corresponds to time: ${dayjs(tsoDate).format(DEFAULT_TIME_FORMAT_WITH_TIMEZONE)}`
  }, [tso])
}

function TSOTip() {
  return (
    <HoverCard shadow="md" withArrow>
      <HoverCard.Target>
        <IconInfoCircle size={14} />
      </HoverCard.Target>
      <HoverCard.Dropdown>
        <Typography variant="body-md">
          Set the starting position for your sink.{' '}
          <a
            href="https://docs.pingcap.com/tidb/stable/sql-statement-show-master-status/"
            target="_blank"
            rel="noreferrer"
          >
            See doc for instructions.
          </a>
        </Typography>
      </HoverCard.Dropdown>
    </HoverCard>
  )
}

export const FormStartPositionEssential = ({ disabled, schemaTableData }: FormStartPositionEssentialProps) => {
  const { setValue, watch, control } = useFormContext<CreateOrEditChangefeedEssentialFormData>()
  const startPositionMode = watch('start_position.mode') as StartModeEnum
  const isEditing = useIsEditingChangefeed()
  const isDisabled = disabled ?? isEditing
  const tso = watch('start_position.tso') ?? ''
  const time = watch('start_position.time') ?? ''
  const tsoDesciption = useTsoDescription(tso)

  const tsoValidationRules = {
    required: {
      value: startPositionMode === StartModeEnum.FROM_TSO,
      message: 'TSO is required'
    },
    pattern: {
      value: /^\d{18}$/,
      message: 'TSO must be an 18-digit number'
    }
  }

  return (
    <Stack>
      <Controller
        name="start_position.mode"
        control={control}
        render={({ field }) => (
          <Stack>
            <Radio.Group
              {...field}
              onChange={(value) => {
                field.onChange(value)
                if (value === StartModeEnum.FROM_TIME && !time) {
                  setValue('start_position.time', new Date().toISOString())
                }
              }}
              sx={{ 'div[role="radiogroup"]': { paddingTop: 0 } }}
            >
              <Group align="flex-start" gap={48}>
                {StartPositionOptions.map((i) => (
                  <Box key={i.value}>
                    {i.value === StartModeEnum.FROM_TSO ? (
                      <Group gap={8}>
                        <Radio disabled={isDisabled} label={i.text} value={i.value} />
                        <TSOTip />
                      </Group>
                    ) : (
                      <Radio disabled={isDisabled} label={i.text} value={i.value} />
                    )}
                  </Box>
                ))}
              </Group>
            </Radio.Group>
          </Stack>
        )}
      />

      {startPositionMode === StartModeEnum.FROM_TSO && (
        <FormTextInput
          name="start_position.tso"
          inputWrapperOrder={['input', 'error', 'description']}
          description={tsoDesciption}
          descriptionProps={{ sx: { position: 'absolute' } }}
          disabled={isDisabled}
          placeholder="Enter TSO"
          rules={tsoValidationRules}
          sx={{ width: '100%' }}
        />
      )}

      {startPositionMode === StartModeEnum.FROM_TIME && (
        <Controller
          control={control}
          name="start_position.time"
          rules={{ required: 'Required' }}
          render={({ field }) => (
            <Group>
              <input {...field} hidden />
              <DateTimePicker
                startDate={schemaTableData?.gc_safe_point ? new Date(schemaTableData?.gc_safe_point) : undefined}
                endDate={new Date()}
                value={field.value ? new Date(field.value) : new Date()}
                disabled={isDisabled}
                onChange={(val) => {
                  setValue(`start_position.time`, val.toISOString())
                }}
                sx={{ width: '100%' }}
              />
            </Group>
          )}
        />
      )}
    </Stack>
  )
}
