import { Modal, Stack, Typography } from '@tidbcloud/uikit'
import { DateTimePicker, Form, FormSelect, FormTextInput } from '@tidbcloud/uikit/biz'
import dayjs from 'dayjs'
import { forwardRef, useMemo } from 'react'
import { Controller, useForm } from 'react-hook-form'

import { StarterCapacityAlert } from 'dbaas/screens/shared/starter-capacity/StarterCapacityAlert'
import { useStarterInventoryLimit } from 'dbaas/screens/shared/starter-capacity/use-starter-inventory-limit'
import { useCreateBranch, useGetBackupRetention } from 'dbaas/services/api-clients/legacy/serverless'
import {
  ConsoleBranchServiceCreateBranchBody as CreateBranchBody,
  ConsoleBasicBranch as ServerlessBasicBranch
} from 'dbaas/services/api-clients/legacy/serverless/interface'
import useStores from 'dbaas/stores/useStores'

import { getParentBranchCreateTime } from './helper'

type PropsType = {
  opened: boolean
  clusterId: string
  parentId?: string
  createTime: string
  branchList: ServerlessBasicBranch[]
  onConfirm: () => void
  onClose: () => void
}

type FormValues = {
  branchName: string
  parentId: string
  timeType: 'current' | 'specific'
  parentTime: Date
}

interface ItemProps extends React.ComponentPropsWithoutRef<'div'> {
  value: string
  label: string
  description: string
}

export const CreateBranchModal = ({
  opened,
  clusterId,
  parentId,
  branchList,
  createTime,
  onConfirm,
  onClose
}: PropsType) => {
  const {
    store: {
      lastVisitLocation: { orgId, projectId },
      tenantData: { timezone }
    }
  } = useStores()

  const branchOptions = useMemo(
    () => [
      { label: 'main', value: clusterId },
      ...(branchList.map((v) => ({ label: v.display_name, value: v.id })) ?? [])
    ],
    [branchList, clusterId]
  )

  const { mutateAsync: createAsync, isLoading } = useCreateBranch()
  const starterInventoryLimit = useStarterInventoryLimit({ enabled: opened })
  const isFormDisabled = starterInventoryLimit.isLimitReached
  const isCreateDisabled = starterInventoryLimit.isLoading || isFormDisabled

  const method = useForm<FormValues>({
    defaultValues: {
      branchName: '',
      timeType: 'current',
      parentId: parentId ? parentId : clusterId
    }
  })

  const timeType = method.watch('timeType')
  const selectedParentId = method.watch('parentId')
  const parentCreateTime = getParentBranchCreateTime({
    parentId: selectedParentId,
    clusterId,
    clusterCreateTime: createTime,
    branchList
  })

  const { isLoading: retentionIsLoading, data: retentionData } = useGetBackupRetention(orgId, projectId, clusterId, {
    query: {
      refetchOnMount: false,
      refetchOnWindowFocus: false
    }
  })

  const handleConfirm = async (value: FormValues) => {
    if (isCreateDisabled) {
      return
    }

    const data: CreateBranchBody = {
      display_name: value.branchName,
      parent_id: value.parentId
    }
    if (value.timeType === 'specific') {
      data.parent_timestamp = dayjs(value.parentTime).utc().format('YYYY-MM-DDTHH:mm:ss[Z]')
    }

    await createAsync({
      orgId,
      projectId,
      clusterId,
      data
    })

    handleClose()
    onConfirm()
  }

  const handleClose = () => {
    method.reset()
    onClose()
  }

  const SelectItem = forwardRef<HTMLDivElement, ItemProps>(
    ({ value, label, description, ...others }: ItemProps, ref) => (
      <Stack ref={ref} {...others} gap={4}>
        <Typography variant="body-lg" c="carbon.9">
          {label}
        </Typography>
        <Typography variant="label-md" c="carbon.7">
          {description}
        </Typography>
      </Stack>
    )
  )
  const timeTypeData = [
    { label: 'Current point in time', value: 'current', description: 'Include the latest available data' },
    {
      label: 'Specific date and time',
      value: 'specific',
      description: 'Include data up to a set date and time for recovery.'
    }
  ]

  return (
    <Modal size={480} title="Create Branch" centered trapFocus={false} opened={opened} onClose={handleClose}>
      <Form
        form={method}
        actionsProps={{
          confirmText: 'Create',
          confirmProps: {
            loading: isLoading || starterInventoryLimit.isLoading,
            disabled: isCreateDisabled,
            'data-mp-event': 'Serverless branch create branch'
          },
          cancelProps: {
            'data-mp-event': 'Cancel create branch Button Clicked'
          }
        }}
        onCancel={handleClose}
        onSubmit={handleConfirm}
      >
        {starterInventoryLimit.status && (
          <StarterCapacityAlert
            status={starterInventoryLimit.status}
            currentCount={starterInventoryLimit.currentCount}
            limit={starterInventoryLimit.limit}
          />
        )}
        <FormTextInput
          name="branchName"
          label="Name"
          rules={{ required: 'Name is required' }}
          autoFocus={!isFormDisabled}
          disabled={isFormDisabled}
          placeholder="Enter a branch name"
        />
        <FormSelect
          name="parentId"
          label="Parent branch"
          data={branchOptions}
          disabled={isFormDisabled}
          rules={{ required: 'Source branch is required' }}
        />
        <FormSelect
          name="timeType"
          label="Include data up to"
          rules={{ required: 'Include data up to is required' }}
          renderOption={(item: { option: (typeof timeTypeData)[number] }) => <SelectItem {...item.option} />}
          data={timeTypeData}
          disabled={isFormDisabled}
        />
        {timeType === 'specific' && (
          <Controller
            name="parentTime"
            control={method.control}
            disabled={retentionIsLoading || isFormDisabled}
            render={({ field }) => (
              <DateTimePicker
                utcOffset={timezone * 60}
                withinPortal
                startDate={dayjs
                  .max(dayjs(parentCreateTime), dayjs().subtract(retentionData?.retention_hours || 0, 'hours'))
                  .toDate()}
                endDate={dayjs().toDate()}
                value={field.value}
                disabled={retentionIsLoading || isFormDisabled}
                onChange={field.onChange}
              />
            )}
          />
        )}
      </Form>
    </Modal>
  )
}
