import { Alert, Button, Form, Input, Modal, Progress, Select } from 'antd'
import { FormInstance } from 'antd/es/form/Form'
import React, { useCallback, useRef, useState } from 'react'
import { Link } from 'react-router-dom'

import {
  operationControllerCreateInstance,
  operationControllerPreviewInstance
} from 'apiClient/services/devops'
import {
  ClusterGetClusterResp,
  OperationActionStartPolicy,
  OperationCreateInstanceReq,
  OperationOperationTarget
} from 'apiClient/services/devops/interface'
import ModalForm from 'components/ModalForm'
import { capitalize } from 'utils/string'

import CreateInstanceForm, {
  CreateInstanceFormType,
  AppendCategoryFromDeployType,
  COMPOSITE_AZ_OPERATION_NAMES
} from './Forms/CreateInstanceForm'

interface CreateOperationProps {
  target_type?: OperationOperationTarget
  target_id?: string
  reload?: () => Promise<void>
  cluster?: ClusterGetClusterResp
  op: string
  init_categories?: string[]
  bottom_name?: string
  triggerStyle?: React.CSSProperties
}

const CreateOperation: React.FC<CreateOperationProps> = ({
  target_type,
  target_id,
  reload,
  cluster,
  op,
  init_categories,
  bottom_name,
  triggerStyle
}) => {
  const [createForm, setCreateForm] = useState(false)
  const [advisoryProgress, setAdvisoryProgress] = useState<number | null>(null)
  const progressTimerRef = useRef<ReturnType<typeof setInterval> | null>(null)

  const renderFormFields = useCallback(
    (form: FormInstance) => {
      return (
        <CreateInstanceForm
          form={form}
          target_type={target_type}
          target_id={target_id}
          init_categories={AppendCategoryFromDeployType(
            init_categories ? init_categories : [],
            cluster?.deploy_type
          )}
          op={op}
          cluster={cluster}
        />
      )
    },
    [createForm, target_type, target_id, init_categories, cluster, op]
  )

  const handleCreate = useCallback(async (payload: CreateInstanceFormType) => {
    if (
      COMPOSITE_AZ_OPERATION_NAMES.has(payload.operation) &&
      !payload.actions?.some((a) => a.choose)
    ) {
      Modal.error({
        title: 'Validation Error',
        content: 'Select at least one action to execute.'
      })
      return
    }
    const keysMap: { [key: string]: string } = {}
    Object.keys(payload.params).forEach((key) => {
      if (Array.isArray(payload.params[key])) {
        keysMap[key] = payload.params[key].join(',')
      } else {
        keysMap[key] = payload.params[key]
      }
    })
    const req: OperationCreateInstanceReq = {
      actions: payload.actions
        .filter((a) => a.choose)
        .map((val) => {
          return {
            name: val.name,
            start_policy:
              OperationActionStartPolicy[
                val.start_policy as keyof typeof OperationActionStartPolicy
              ],
            start_schedule_at: val.schedule_time
              ? val.schedule_time.unix()
              : undefined
          }
        }),
      operation: payload.operation,
      params: keysMap,
      reason: payload.reason,
      type: payload.type,
      is_draft: payload.is_draft
    }
    const executionWindowRange = payload.execution_window_range
    if (
      payload.execution_window_enabled &&
      executionWindowRange?.[0] &&
      executionWindowRange?.[1] &&
      executionWindowRange[0].isBefore(executionWindowRange[1])
    ) {
      req.execution_window = {
        start_at: executionWindowRange[0].unix(),
        end_at: executionWindowRange[1].unix()
      }
    }

    const doCreate = async () => {
      try {
        const data = await operationControllerCreateInstance(req)
        const id = data.data.instance_id
        Modal.success({
          title: 'Info',
          content: (
            <div>
              <p>
                Operation <b>{id}</b> is awaiting approval and can only be
                started after approval.
                <br></br>
                <br></br>
                To check the progress of this operation, please refer to the{' '}
                <a href={`/operations/${id}`}>Detail</a> page.
              </p>
            </div>
          ),
          onOk() {}
        })
        setCreateForm(false)
        if (reload) {
          reload()
        }
      } catch (error) {
        Modal.error({
          title: error.response.data.errcode,
          content: error.response.data.errmsg
        })
        if (reload) {
          reload()
        }
      }
    }

    // Double Confirm
    let confirmText: React.ReactNode | undefined
    if (payload.operation === 'ScaleClusterPDSize') {
      confirmText = (
        <div>
          <p>
            Given the enhanced PD size allocation logic, the PD size you
            configured in Ops may be adjusted for better performance when the
            customer scales up their TiKV nodes in the future.
            <br />
            For more details, you can refer to{' '}
            <a
              target="_blank"
              href="https://pingcap.feishu.cn/wiki/JZpKwtmuFi0k4YkqqQgcugZ8nWe"
              rel="noreferrer"
            >
              [Spec] New PD Compute Logic
            </a>
            .
          </p>
        </div>
      )
    }

    const proceedWithCreate = async () => {
      if (confirmText) {
        Modal.confirm({
          title: 'Confirm Operation',
          content: confirmText,
          onOk: doCreate,
          onCancel() {}
        })
      } else {
        await doCreate()
      }
    }

    setAdvisoryProgress(0)
    progressTimerRef.current = setInterval(() => {
      setAdvisoryProgress((prev) => {
        if (prev === null) return null
        return Math.min(prev + (90 - prev) * 0.08 + 0.5, 90)
      })
    }, 500)

    try {
      const preview = await operationControllerPreviewInstance(req)
      const warnings = (preview.data.advisories ?? []).filter(
        (a) => a.level === 'warning'
      )
      if (warnings.length > 0) {
        Modal.confirm({
          title: 'Advisory',
          content: (
            <div>
              {warnings.map((w, i) => (
                <Alert
                  key={i}
                  type="warning"
                  message={w.message}
                  style={{ marginBottom: 8 }}
                  showIcon
                />
              ))}
              <p style={{ marginTop: 8 }}>Do you still want to proceed?</p>
            </div>
          ),
          onOk: proceedWithCreate,
          onCancel() {}
        })
        return
      }
    } catch (err) {
      Modal.confirm({
        title: 'Advisory Check Failed',
        content: (
          <div>
            <Alert
              type="error"
              message={err?.response?.data?.errmsg ?? String(err)}
              style={{ marginBottom: 8 }}
              showIcon
            />
            <p style={{ marginTop: 8 }}>Do you still want to proceed?</p>
          </div>
        ),
        onOk: proceedWithCreate,
        onCancel() {}
      })
      return
    } finally {
      if (progressTimerRef.current) {
        clearInterval(progressTimerRef.current)
        progressTimerRef.current = null
      }
      setAdvisoryProgress(null)
    }

    await proceedWithCreate()
  }, [])

  const handleCancelCreate = useCallback(() => {
    setCreateForm(false)
    if (reload) {
      reload()
    }
  }, [])

  return (
    <div>
      {op === 'other Operations' ? (
        <a
          onClick={() => {
            setCreateForm(true)
          }}
          style={{
            display: 'block',
            width: '100%',
            textAlign: 'left',
            ...triggerStyle
          }}
        >
          {capitalize(op)}
        </a>
      ) : (
        <a
          onClick={() => {
            setCreateForm(true)
          }}
          style={{
            display: 'block',
            width: '100%',
            textAlign: 'left',
            ...triggerStyle
          }}
        >
          {bottom_name ? bottom_name : capitalize(op)}
        </a>
      )}
      <ModalForm<CreateInstanceFormType>
        visible={!!createForm}
        name="user"
        title={'Create Operation'}
        getFields={renderFormFields}
        onSubmit={handleCreate}
        onCancel={handleCancelCreate}
        width={1000}
        destoryOnClose={true}
      />
      <Modal
        open={advisoryProgress !== null}
        footer={null}
        closable={false}
        title="Running advisory checks..."
      >
        <Progress percent={Math.round(advisoryProgress ?? 0)} status="active" />
        <p style={{ textAlign: 'center', marginTop: 12, color: '#666' }}>
          Performing soft checks, please wait...
        </p>
      </Modal>
    </div>
  )
}

export default CreateOperation
