import {
  Alert,
  Button,
  Group,
  Loader,
  LoadingOverlay,
  notifier,
  Select,
  Stack,
  Text,
  Typography
} from '@tidbcloud/uikit'
import { IconAlertCircle } from '@tidbcloud/uikit/icons'
import { observer } from 'mobx-react'
import React, { useMemo } from 'react'
import { Controller, useForm } from 'react-hook-form'
import { useQuery } from 'react-query'

import { renderDescriptiveSelectOption } from 'dbaas/screens/Changefeed/CreateOrEditChangefeed/renderDescriptiveSelectOption'
import { calChangefeedFee, useListChangefeedInstanceTypes, useScaleChangefeed } from 'dbaas/services/dataflow'
import { DataflowConnector, ScaleChangefeedBody } from 'dbaas/services/dataflow/interface'
import { getErrorMessage } from 'dbaas/services/errorCodes'
import useStores from 'dbaas/stores/useStores'

function Fee({ n, deprecated }: { n?: number; deprecated?: boolean }) {
  return (
    <Text span fz={20} c={deprecated ? 'carbon.6' : 'carbon.7'} td={deprecated ? 'line-through' : undefined}>
      <Text span fw={700} c={deprecated ? 'carbon.6' : 'carbon.9'}>
        {`$${n?.toFixed(4) ?? 0}`}
      </Text>
      {!deprecated && (
        <Text span fz={14}>
          /hour
        </Text>
      )}
    </Text>
  )
}

export const ChangefeedScale: React.FC<
  React.PropsWithChildren<{ connector: DataflowConnector; onCancel: () => void; onConfirm: () => void }>
> = observer(({ connector, onCancel, onConfirm }) => {
  const {
    store: { tenantData, activeProjectId, currentCluster }
  } = useStores()

  const { watch, control, handleSubmit, formState, setValue } = useForm<ScaleChangefeedBody>({
    defaultValues: {
      changefeed_instance_type: connector.changefeed_instance_type
    }
  })
  const instanceType = watch('changefeed_instance_type')
  const { data, isLoading } = useListChangefeedInstanceTypes(
    {
      connector_type: connector.connector_type,
      cluster_id: connector.request?.cluster_id
    },
    {
      query: {
        onSuccess(data) {
          const defaultItem = data.items.find((i) => i.name !== connector.changefeed_instance_type)
          if (defaultItem) {
            setValue('changefeed_instance_type', defaultItem.name!)
          }
        }
      }
    }
  )
  const options = useMemo(() => {
    return (
      data?.items.map((i) => ({
        label: `${i.rcu_num} RCUs`,
        description: `The maximum replication performance is ${i.rps_limit} rows/s`,
        value: i.name!,
        disabled: i.name === connector.changefeed_instance_type
      })) ?? []
    )
  }, [data, connector.changefeed_instance_type])

  const currentOption = options.find((i) => i.value === connector.changefeed_instance_type)
  const scaleChangefeed = useScaleChangefeed()

  const { data: currentFeeData } = useQuery(
    ['/cal_changefeed_fee'],
    () =>
      calChangefeedFee(tenantData.id, activeProjectId, {
        cloud_provider_name: currentCluster?.provider,
        region_name: currentCluster?.region,
        changefeed_instance_type: connector.changefeed_instance_type,
        duration: '60' // 60 means per hour
      }),
    {
      refetchOnWindowFocus: false
    }
  )

  const { data: feeData, isFetching } = useQuery(
    ['/cal_changefeed_fee', instanceType],
    () =>
      calChangefeedFee(tenantData.id, activeProjectId, {
        cloud_provider_name: currentCluster?.provider,
        region_name: currentCluster?.region,
        changefeed_instance_type: instanceType,
        duration: '60' // 60 means per hour
      }),
    {
      enabled: Boolean(instanceType),
      refetchOnWindowFocus: false
    }
  )

  const onSubmit = async (d: ScaleChangefeedBody) => {
    await scaleChangefeed.mutateAsync({
      orgId: tenantData.id,
      projectId: activeProjectId,
      clusterId: currentCluster?.id!,
      changefeedId: connector.connector_id!,
      data: {
        changefeed_instance_type: d.changefeed_instance_type
      }
    })
    notifier.success('Changefeed is scaling...')
    onConfirm()
  }

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <LoadingOverlay visible={isLoading} overlayProps={{ blur: 2 }} />

      <Stack>
        <Stack gap={4}>
          <Text c="carbon.8" fz={14} fw={600}>
            Current Specification
          </Text>
          {currentOption && (
            <Group wrap="nowrap" gap={4}>
              <Typography fw={700} c="carbon.8">
                {currentOption?.label}
              </Typography>
              <Typography c="carbon.7">({currentOption?.description})</Typography>
            </Group>
          )}
        </Stack>

        <Controller
          name="changefeed_instance_type"
          control={control}
          rules={{ required: 'Required' }}
          render={({ field }) => (
            <Select
              {...field}
              onChange={(val) => field.onChange(val)}
              error={formState.errors?.changefeed_instance_type?.message}
              data={options.filter((i) => !i.disabled)}
              label="Change Specification to"
              renderOption={renderDescriptiveSelectOption}
              placeholder="Select the number of RCU"
            />
          )}
        />

        {scaleChangefeed.error && (
          <Alert color="red" icon={<IconAlertCircle size={14} />}>
            {getErrorMessage(scaleChangefeed.error)}
          </Alert>
        )}

        <Group justify="space-between">
          {isFetching ? (
            <Loader size="xs" />
          ) : feeData?.fee === currentFeeData?.fee ? (
            <Fee n={feeData?.fee} />
          ) : (
            <Group gap={8}>
              <Fee n={currentFeeData?.fee} deprecated />
              <Fee n={feeData?.fee} />
            </Group>
          )}

          <Group>
            <Button variant="default" onClick={onCancel} data-mp-event="Cancel Changefeed Scale Clicked">
              Cancel
            </Button>
            <Button type="submit" loading={scaleChangefeed.isLoading} data-mp-event="Submit Changefeed Scale Clicked">
              Submit
            </Button>
          </Group>
        </Group>
      </Stack>
    </form>
  )
})
