import {AlertComponent, attachmentAdpator, makeTranslator, render, type Schema, ToastComponent} from 'amis'

import 'amis/lib/themes/antd.css'
import 'amis/lib/helper.css'
import 'amis/sdk/iconfont.css'
import '@fortawesome/fontawesome-free/css/all.min.css'
import axios from 'axios'
import {isEqual} from 'licia'

export const commonInfo = {
  debug: isEqual(import.meta.env.MODE, 'development'),
  baseUrl: 'http://132.126.207.130:35690/hudi_services/service_web',
  baseAiUrl: 'http://132.126.207.130:35690/hudi_services/service_ai_web',
  // baseAiUrl: 'http://localhost:8080',
  authorizationHeaders: {
    'Authorization': 'Basic QXhoRWJzY3dzSkRiWU1IMjpjWXhnM2I0UHRXb1ZENVNqRmF5V3h0blNWc2p6UnNnNA==',
    'Content-Type': 'application/json',
  },
  clusters: {
    // hudi同步运行集群和yarn队列名称
    sync: {
      'b12': 'default',
    },
    sync_names() {
      return Object.keys(this.sync).join(',')
    },
    // hudi压缩运行集群和yarn队列名称
    compaction: {
      'b12': 'default',
      'b1': 'datalake',
      'a4': 'ten_iap.datalake',
    },
    compaction_names() {
      return Object.keys(this.compaction).join(',')
    },
  },
  loki: {
    // grafana链接，用于直接打开grafana日志查看
    grafanaUrl: 'http://132.126.207.125:35700',
    // grafana对应hudi使用的loki配置的datasource id
    hudi: {
      datasource: 'f648174e-7593-45cf-8fe8-8f8d5cf0fdde',
    },
    // grafana对应服务使用的loki配置的datasource id
    service: {
      datasource: 'b6fee51c-facd-4261-a0eb-8c69a975fba3',
    },
  },
}

const __ = makeTranslator('zh')

const responseAdaptor = () => (response: any) => {
  let payload = response.data || {} // blob 下可能会返回内容为空？
  if (payload.hasOwnProperty('errno')) {
    payload.status = payload.errno
    payload.msg = payload.errmsg
  } else if (payload.hasOwnProperty('no')) {
    payload.status = payload.no
    payload.msg = payload.error
  }
  return {
    ...response,
    data: payload,
  }
}

export const amisRender = (schema: Schema, data: Record<any, any> = {}) => {
  const theme = 'antd'
  const locale = 'zh-CN'
  return (
    <>
      <ToastComponent
        theme={theme}
        key="toast"
        position={'top-right'}
        locale={locale}
      />
      <AlertComponent theme={theme} key="alert" locale={locale}/>
      {render(
        schema,
        {
          data: data,
          theme: theme,
        },
        {
          enableAMISDebug: commonInfo.debug,
          fetcher: async (api: any) => {
            let {url, method, data, responseType, config, headers} = api
            config = config || {}
            config.url = url
            config.withCredentials = true
            responseType && (config.responseType = responseType)

            if (config.cancelExecutor) {
              config.cancelToken = new (axios as any).CancelToken(
                config.cancelExecutor,
              )
            }

            config.headers = headers || {}
            config.method = method
            config.data = data

            if (method === 'get' && data) {
              config.params = data
            } else if (data && data instanceof FormData) {
              // config.headers['Content-Type'] = 'multipart/form-data';
            } else if (
              data &&
              typeof data !== 'string' &&
              !(data instanceof Blob) &&
              !(data instanceof ArrayBuffer)
            ) {
              data = JSON.stringify(data)
              config.headers['Content-Type'] = 'application/json'
            }

            // 支持返回各种报错信息
            config.validateStatus = function () {
              return true
            }

            let response = await axios(config)
            response = await attachmentAdpator(response, __, api)
            response = responseAdaptor()(response)

            if (response.status >= 400) {
              if (response.data) {
                // 主要用于 raw: 模式下，后端自己校验登录，
                if (
                  response.status === 401 &&
                  response.data.location &&
                  response.data.location.startsWith('http')
                ) {
                  location.href = response.data.location.replace(
                    '{{redirect}}',
                    encodeURIComponent(location.href),
                  )
                  return new Promise(() => {
                  })
                } else if (response.data.msg) {
                  throw new Error(response.data.msg)
                } else {
                  throw new Error(
                    'System.requestError' + JSON.stringify(response.data, null, 2),
                  )
                }
              } else {
                throw new Error(
                  `${'System.requestErrorStatus'} ${response.status}`,
                )
              }
            }

            return response
          },
          isCancel: (value: any) => (axios as any).isCancel(value),
        },
      )}
    </>
  )
}

function generateLokiPanel(queries: Array<any>) {
  return {
    LWF: {
      queries: [
        ...queries.map(item => {
          let name = item['name']
          let datasource = item['datasource']
          let queryMap = item['queryMap']
          let query = Object.keys(queryMap)
            .sort()
            .map(key => `${key}="${queryMap[key]}"`)
          let match = '\\d{4}-(?P<time>\\d{2}-\\d{2}\\s*\\d{2}:\\d{2}:\\d{2}).+#@#\\s*(?P<content>[\\w\\W]+)'
          let format = '{{.time}} [{{.host}}] [{{.level}}] [{{.app}}] {{.content}}'
          // language=TEXT
          let expression = `{${query.join(',')}}\n| regexp "${match.replaceAll('\\', '\\\\')}"\n| line_format \`${format}\``
          return {
            refId: name,
            expr: expression,
            queryType: 'range',
            datasource: {
              type: 'loki',
              uid: datasource,
            },
            editorMode: 'code',
          }
        }),
      ],
      range: {
        from: 'now-1h',
        to: 'now',
      },
    },
  }
}

function generateQuery(name: string, datasource: string, queryMap: any) {
  return {
    name: name,
    datasource: datasource,
    queryMap: queryMap,
  }
}

function generateLokiUrl(baseUrl: string, queries: Array<any>) {
  return `${baseUrl}/explore?panes=${encodeURIComponent(JSON.stringify(generateLokiPanel(queries)))}&schemaVersion=1&orgId=1`
}

function targetHudiSyncLokiUrlByAlias(flinkJobId: number) {
  return generateLokiUrl(
    commonInfo.loki.grafanaUrl,
    [
      generateQuery(
        'Hudi 运行日志',
        commonInfo.loki.hudi.datasource,
        {'flink_job_id': flinkJobId},
      ),
    ],
  )
}

function targetHudiCompactionLokiUrlByAlias(alias: string) {
  return generateLokiUrl(
    commonInfo.loki.grafanaUrl,
    [
      generateQuery(
        'Hudi 运行日志',
        commonInfo.loki.hudi.datasource,
        {'alias': alias},
      ),
    ],
  )
}

function targetYarnApplicationLokiUrlByAppId(applicationId: string) {
  return generateLokiUrl(
    commonInfo.loki.grafanaUrl,
    [
      generateQuery(
        'Hudi 运行日志',
        commonInfo.loki.hudi.datasource,
        {'app_id': applicationId},
      ),
    ],
  )
}

export function serviceLogByAppName(name: string) {
  return generateLokiUrl(
    commonInfo.loki.grafanaUrl,
    [
      generateQuery(
        'Service 运行日志',
        commonInfo.loki.service.datasource,
        {'app': name},
      ),
    ],
  )
}

export function serviceLogByAppNameAndHost(name: string, host: string) {
  return generateLokiUrl(
    commonInfo.loki.grafanaUrl,
    [
      generateQuery(
        'Service 运行日志',
        commonInfo.loki.service.datasource,
        {'app': name, 'host': host},
      ),
    ],
  )
}

export function crudCommonOptions() {
  return {
    affixHeader: false,
    stopAutoRefreshWhenModalIsOpen: true,
    resizable: false,
    syncLocation: false,
    silentPolling: true,
    columnsTogglable: false,
  }
}

export function readOnlyDialogOptions() {
  return {
    actions: [],
    showCloseButton: false,
    closeOnEsc: true,
    closeOnOutside: true,
    disabled: true,
  }
}

export function paginationCommonOptions(perPage = true, maxButtons = 5) {
  let option = {
    type: 'pagination',
    layout: [
      'pager',
    ],
    maxButtons: maxButtons,
    showPageInput: false,
    perPageAvailable: [10, 15, 20, 50, 100, 200],
  }
  if (perPage) {
    option.layout.push('perPage')
  }
  return option
}

export function paginationTemplate(perPage = 20, maxButtons = 5) {
  return {
    perPage: perPage,
    headerToolbar: [
      'reload',
      paginationCommonOptions(true, maxButtons),
    ],
    footerToolbar: [
      'statistics',
      paginationCommonOptions(true, maxButtons),
    ],
  }
}

export function timeAndFrom(field: string, fromNow: string, emptyText = '未停止', showSource = true) {
  let tpl = '${IF(' + field + ' === 0, \'(' + emptyText + ')\', CONCATENATE(\'<span class="font-bold">\',' + fromNow + ',\'</span>\'))}'
  if (showSource) {
    return {
      align: 'center',
      width: 80,
      type: 'tooltip-wrapper',
      content: '${DATETOSTR(DATE(' + field + '))}',
      inline: true,
      className: 'mr-2',
      disabledOn: `\${${field} === 0}`,
      body: {
        type: 'tpl',
        tpl: tpl,
      },
    }
  } else {
    return {
      align: 'center',
      width: 140,
      type: 'tpl',
      tpl: '${DATETOSTR(DATE(' + field + '))}',
    }
  }
}

export function applicationLogDialog() {
  return {
    type: 'action',
    level: 'link',
    actionType: 'dialog',
    dialog: {
      title: '应用日志',
      size: 'xl',
      actions: [],
      body: [
        {
          type: 'service',
          api: {
            method: 'GET',
            url: `${commonInfo.baseUrl}/log/query_application_log`,
            data: {
              application_id: '${id}',
            },
          },
          body: [
            {
              disabled: true,
              type: 'editor',
              name: 'detail',
              label: '应用日志',
              size: 'xxl',
              placeholder: '没有内容',
              options: {
                wordWrap: 'on',
              },
            },
          ],
        },
      ],
    },
  }
}

export function yarnQueueCrud(clusters?: string, queueNames?: string) {
  return {
    type: 'crud',
    api: {
      method: 'get',
      url: `${commonInfo.baseUrl}/yarn/queue_list`,
      data: {
        clusters: '${cluster|default:undefined}',
        names: '${queueName|default:undefined}',
      },
    },
    affixHeader: false,
    defaultParams: {
      ...(clusters ? {cluster: clusters} : {}),
      ...(queueNames ? {queueName: queueNames} : {}),
    },
    interval: 10000,
    syncLocation: false,
    silentPolling: true,
    headerToolbar: [
      'reload',
    ],
    columns: [
      {
        name: 'queueName',
        label: '队列名称',
        width: 130,
        type: 'tooltip-wrapper',
        body: '${TRUNCATE(queueName, 20)}',
        content: '${queueName}',
        inline: true,
      },
      {
        label: '当前容量',
        type: 'progress',
        value: '${ROUND((absoluteUsedCapacity * 100 / absoluteMaxCapacity), 0)}',
        stripe: true,
        animate: true,
        showLabel: false,
        map: [
          {
            value: 30,
            color: '#28a745',
          }, {
            value: 90,
            color: '#007bff',
          },
          {
            value: 100,
            color: '#dc3545',
          },
        ],
      },
      {
        label: '进度',
        width: 35,
        align: 'center',
        type: 'tpl',
        tpl: '${ROUND((absoluteUsedCapacity * 100 / absoluteMaxCapacity), 0)}%',
      },
      {
        type: 'operation',
        label: '操作',
        width: 100,
        fixed: 'right',
        buttons: [
          {
            label: '详情',
            type: 'button',
            level: 'link',
            tooltip: '查看队列详情',
            visibleOn: '${!root}',
            actionType: 'dialog',
            dialog: {
              closeOnEsc: true,
              closeOnOutside: true,
              size: 'md',
              close: true,
              title: '队列详情',
              body: {
                type: 'property',
                items: [
                  {label: 'CPU', content: '${resourcesUsed.vCores}'},
                  // 有空看看这个值的单位
                  {label: '内存', content: '${resourcesUsed.memory}', span: 2},
                  {label: '容量(%)', content: '${capacity}'},
                  {label: '最大容量(%)', content: '${maxCapacity}'},
                  {label: '已用容量(%)', content: '${usedCapacity}'},
                  {label: '绝对容量(%)', content: '${absoluteCapacity}'},
                  {label: '绝对最大容量(%)', content: '${absoluteMaxCapacity}'},
                  {label: '绝对已用容量(%)', content: '${absoluteUsedCapacity}'},
                  {label: '应用数量', content: '${numApplications}', span: 3},
                  {label: '最大应用数量', content: '${maxApplications}'},
                  {label: '活跃应用数量', content: '${numActiveApplications}'},
                  {label: '等待应用数量', content: '${numPendingApplications}'},
                  {label: '容器数量', content: '${numContainers}', span: 3},
                  {label: '已分配容器数量', content: '${numApplications}'},
                  {label: '预留容器数量数量', content: '${numApplications}'},
                  {label: '等待容器数量', content: '${numApplications}'},
                ],
              },
              actions: [],
            },
          },
          {
            visibleOn: '${webUrl}',
            label: '管理页面',
            type: 'action',
            level: 'link',
            tooltip: '打开管理页面',
            actionType: 'url',
            url: '${webUrl}',
            blank: true,
          },
        ],
      },
    ],
  }
}

export function yarnCrudColumns() {
  return [
    {
      label: '名称',
      className: 'nowrap',
      type: 'tpl',
      tpl: '${IF(syncApplication, \'<span class="rounded-xl label label-primary">S</span>\', IF(compactionApplication, \'<span class="rounded-xl label label-primary">C</span>\', IF(taskApplication, \'<span class="rounded-xl label label-primary">T</span>\', \'\')))}${IF(hudiApplication || taskApplication, \'<span class="mx-2"/>\', \'\')}${IF(syncApplication, flinkJobName, IF(compactionApplication, alias, IF(taskApplication, taskName, name)))}',
    },
    {
      name: 'cluster',
      label: '集群',
      width: 65,
      align: 'center',
      type: 'tpl',
      tpl: '<span class="label label-info">${cluster}</span>',
    },
    {
      label: '用户',
      width: 80,
      type: 'tooltip-wrapper',
      body: '${TRUNCATE(user, 8)}',
      content: '${user}',
      align: 'center',
    },
    {
      name: 'state',
      label: '运行状态',
      width: 70,
      align: 'center',
      type: 'mapping',
      canAccessSuperData: false,
      map: {
        'NEW': '<span class=\'label bg-pink-300\'>创建中</span>',
        'NEW_SAVING': '<span class=\'label bg-purple-300\'>已创建</span>',
        'SUBMITTED': '<span class=\'label bg-indigo-300\'>已提交</span>',
        'ACCEPTED': '<span class=\'label bg-cyan-300\'>调度中</span>',
        'RUNNING': '<span class=\'label label-success\'>运行中</span>',
        'FINISHED': '<span class=\'label label-default\'>已结束</span>',
        'FAILED': '<span class=\'label label-danger\'>已失败</span>',
        'KILLED': '<span class=\'label label-warning\'>被停止</span>',
        '*': '<span class=\'label bg-gray-300\'>${state}</span>',
      },
      filterable: {
        multiple: true,
        options: [
          {label: '创建中', value: 'NEW'},
          {label: '已创建', value: 'NEW_SAVING'},
          {label: '已提交', value: 'SUBMITTED'},
          {label: '调度中', value: 'ACCEPTED'},
          {label: '运行中', value: 'RUNNING'},
          {label: '已结束', value: 'FINISHED'},
          {label: '已失败', value: 'FAILED'},
          {label: '被停止', value: 'KILLED'},
        ],
      },
    },
    {
      name: 'finalStatus',
      label: '最终状态',
      width: 70,
      align: 'center',
      type: 'mapping',
      canAccessSuperData: false,
      map: {
        'UNDEFINED': '<span class=\'label label-info\'>运行</span>',
        'SUCCEEDED': '<span class=\'label label-success\'>成功</span>',
        'FAILED': '<span class=\'label label-danger\'>失败</span>',
        'KILLED': '<span class=\'label label-warning\'>终止</span>',
        'ENDED': '<span class=\'label label-default\'>结束</span>',
        '*': '<span class=\'label bg-gray-300\'>${state}</span>',
      },
      filterable: {
        multiple: true,
        options: [
          {label: '运行', value: 'UNDEFINED'},
          {label: '成功', value: 'SUCCEEDED'},
          {label: '失败', value: 'FAILED'},
          {label: '终止', value: 'KILLED'},
          {label: '结束', value: 'ENDED'},
        ],
      },
    },
    {
      name: 'startedTime',
      label: '启动时间',
      ...timeAndFrom('startedTime', 'startTimeFromNow'),
      sortable: true,
      canAccessSuperData: false,
    },
    {
      name: 'finishedTime',
      label: '停止时间',
      ...timeAndFrom('finishedTime', 'finishTimeFromNow'),
      sortable: true,
      align: 'center',
      canAccessSuperData: false,
    },
    {
      type: 'operation',
      width: 160,
      label: '操作',
      fixed: 'right',
      className: 'nowrap',
      buttons: [
        /*{
            disabled: true,
            label: "停止",
            type: "button",
            level: "link",
            tooltip: '从队列中移除该任务',
            actionType: 'dialog',
            dialog: {
                closeOnEsc: true,
                closeOnOutside: true,
                size: 'sm',
                close: true,
                title: '停止确认',
                body: '确认停止任务: <br>${name}<br> ?',
                actions: [
                    {
                        type: 'button',
                        label: '取消',
                        actionType: 'cancel'
                    },
                    {
                        type: 'button',
                        label: '确认移除',
                        level: 'danger',
                        actionType: 'ajax',
                        api: '',
                        primary: true,
                        message: {
                            success: '操作成功',
                            failed: '操作失败'
                        }
                    }
                ]
            }
        },*/
        {
          visibleOn: 'flinkJobId',
          label: 'FID',
          type: 'action',
          actionType: 'copy',
          content: '${flinkJobId}',
          level: 'link',
          tooltip: '${flinkJobId}',
        },
        {
          visibleOn: 'alias',
          label: 'ALIAS',
          type: 'action',
          actionType: 'copy',
          content: '${alias}',
          level: 'link',
          tooltip: '${alias}',
        },
        {
          disabledOn: '${finalStatus != \'SUCCEEDED\' || state != \'FINISHED\'}',
          disabledTip: '无结果',
          visibleOn: 'taskId',
          label: '结果',
          level: 'link',
          type: 'action',
          actionType: 'dialog',
          dialog: {
            title: '结果',
            ...readOnlyDialogOptions(),
            size: 'xl',
            body: [
              {
                type: 'service',
                api: {
                  method: 'get',
                  url: `${commonInfo.baseUrl}/task/results`,
                  data: {
                    task_id: '${taskId|default:undefined}',
                  },
                },
                body: {
                  type: 'editor',
                  disabled: true,
                  name: 'text',
                  options: {
                    wordWrap: 'on',
                    fontFamily: 'monospace',
                  },
                },
              },
            ],
          },
        },
        {
          label: 'ID',
          type: 'action',
          actionType: 'copy',
          content: '${id}',
          level: 'link',
          tooltip: '${id}',
        },
        {
          disabledOn: '${trackingUrl == null}',
          disabledTip: '无应用页面',
          label: '页面',
          type: 'action',
          level: 'link',
          tooltip: '打开应用页面: ${trackingUrl}',
          actionType: 'url',
          url: '${trackingUrl}',
          blank: true,
        },
        {
          disabledOn: '${id == null || !(hudiApplication | taskApplication)}',
          disabledTip: '找不到id或非hudi服务管理的任务',
          label: '日志',
          type: 'action',
          level: 'link',
          tooltip: '打开Grafana日志',
          onEvent: {
            click: {
              actions: [
                {
                  actionType: 'custom',
                  // @ts-ignore
                  script: (context, doAction, event) => {
                    let isSyncApplication = context.props.data?.syncApplication ?? false
                    let isCompactionApplication = context.props.data?.compactionApplication ?? false
                    let flinkJobId = context.props.data?.flinkJobId ?? 0
                    let alias = context.props.data?.alias ?? ''
                    let appId = context.props.data?.id ?? ''
                    let url = ''
                    if (isSyncApplication) {
                      url = targetHudiSyncLokiUrlByAlias(flinkJobId)
                    } else if (isCompactionApplication) {
                      url = targetHudiCompactionLokiUrlByAlias(alias)
                    } else {
                      url = targetYarnApplicationLokiUrlByAppId(appId)
                    }
                    window.open(url, '_blank')
                  },
                },
              ],
            },
          },
        },
      ],
    },
  ]
}

export function simpleYarnDialog(cluster: string, title: string, filterField: string) {
  return {
    title: title,
    actions: [],
    data: {
      base: '${base}',
      name: `\${${filterField}}`,
      flinkJob: '${flinkJob}',
      tableMeta: '${tableMeta}',
    },
    size: 'xl',
    body: [
      {
        type: 'service',
        api: {
          method: 'get',
          url: `${commonInfo.baseUrl}/yarn/job_current`,
          data: {
            clusters: `${cluster}`,
            name: '${name}',
          },
        },
        silentPolling: false,
        body: [
          {
            type: 'wrapper',
            size: 'none',
            visibleOn: '${hasCurrent}',
            body: [
              {
                type: 'service',
                api: {
                  method: 'get',
                  url: `${commonInfo.baseUrl}/flink/overview`,
                  data: {
                    url: '${current.trackingUrl}',
                  },
                },
                silentPolling: false,
                body: [
                  {
                    type: 'property',
                    title: 'Flink 基本信息',
                    column: 4,
                    items: [
                      {label: 'Flink 版本', content: '${flinkVersion}'},
                      {label: 'Flink 小版本', content: '${flinkCommit}', span: 3},
                      {label: '运行中', content: '${jobsRunning}'},
                      {label: '已结束', content: '${jobsFinished}'},
                      {label: '已失败', content: '${jobsFailed}'},
                      {label: '被取消', content: '${jobsCanceled}'},
                      {
                        label: 'Slot (可用/总数)',
                        content: '${slotsAvailable}/${slotsTotal}',
                        span: 4,
                      },
                    ],
                  },
                ],
              },
              {
                type: 'service',
                api: {
                  method: 'get',
                  url: `${commonInfo.baseUrl}/flink/jobs`,
                  data: {
                    url: '${current.trackingUrl}',
                    schema: '${tableMeta.schema}',
                    table: '${tableMeta.table}',
                    mode: '${flinkJob.runMode}',
                  },
                },
                silentPolling: false,
                body: [
                  {
                    type: 'table',
                    title: '任务详情',
                    source: '${items}',
                    affixHeader: false,
                    columns: [
                      {
                        name: 'name',
                        label: '名称',
                        width: 2000,
                      },
                      {
                        label: 'Checkpoint',
                        width: 60,
                        align: 'center',
                        fixed: 'right',
                        type: 'tpl',
                        tpl: '${IF(checkpointMetrics, checkpointMetrics.complete + \'/\' + checkpointMetrics.inProgress +\'/\' + checkpointMetrics.failed, \'-\')}',
                      },
                      {
                        name: 'metrics.readRecords',
                        label: '读记录数',
                        width: 60,
                        align: 'center',
                        fixed: 'right',
                      },
                      {
                        name: 'metrics.writeRecords',
                        label: '写记录数',
                        width: 60,
                        align: 'center',
                        fixed: 'right',
                      },
                      {
                        label: '操作',
                        width: 60,
                        align: 'center',
                        fixed: 'right',
                        type: 'wrapper',
                        size: 'none',
                        body: [
                          {
                            disabled: true,
                            type: 'button',
                            label: '详情',
                            level: 'link',
                            size: 'xs',
                            actionType: 'url',
                            blank: true,
                            url: '${page}',
                          },
                        ],
                      },
                    ],
                  },
                ],
              },
            ],
          },
          {
            type: 'tpl',
            tpl: '没有正在运行的任务',
            visibleOn: '${!hasCurrent}',
          },
        ],
      },
      {type: 'divider'},
      {
        type: 'crud',
        api: {
          method: 'get',
          url: `${commonInfo.baseUrl}/yarn/job_list`,
          data: {
            clusters: `${cluster}`,
            page: '${page|default:undefined}',
            count: '${perPage|default:undefined}',
            order: '${orderBy|default:undefined}',
            direction: '${orderDir|default:undefined}',
            filter_state: '${state|default:undefined}',
            filter_final_status: '${finalStatus|default:undefined}',
            search_id: '${id|default:undefined}',
            search_name: '${name}',
            precise: true,
          },
        },
        affixHeader: false,
        interval: 10000,
        syncLocation: false,
        silentPolling: true,
        resizable: false,
        perPage: 10,
        headerToolbar: [
          'reload',
          paginationCommonOptions(),
        ],
        footerToolbar: [],
        columns: yarnCrudColumns(),
      },
    ],
  }
}

export function hdfsDialog(hdfsField: string) {
  return {
    title: {
      type: 'tpl',
      tpl: `\${${hdfsField}}`,
    },
    ...readOnlyDialogOptions(),
    size: 'xl',
    body: {
      type: 'crud',
      api: {
        method: 'get',
        url: `${commonInfo.baseUrl}/hudi/hdfs_list`,
        data: {
          root: `\${${hdfsField}|default:undefined}`,
        },
      },
      deferApi: {
        method: 'get',
        url: `${commonInfo.baseUrl}/hudi/hdfs_list_children`,
        data: {
          root: '${path|default:undefined}',
        },
      },
      ...crudCommonOptions(),
      perPage: 10,
      headerToolbar: [
        'reload',
        paginationCommonOptions(undefined, 10),
      ],
      footerToolbar: [
        paginationCommonOptions(undefined, 10),
      ],
      columns: [
        {
          name: 'name',
          label: '文件名',
          className: 'font-mono',
        },
        {
          name: 'group',
          label: '组',
          width: 70,
        },
        {
          name: 'owner',
          label: '用户',
          width: 70,
        },
        {
          label: '大小',
          width: 90,
          type: 'tpl',
          tpl: '${sizeText}',
        },
        {
          label: '修改时间',
          width: 140,
          type: 'tpl',
          tpl: '${DATETOSTR(DATE(modifyTime), \'YYYY-MM-DD HH:mm:ss\')}',
        },
        {
          type: 'operation',
          label: '操作',
          width: 160,
          fixed: 'right',
          buttons: [
            {
              label: '完整路径',
              type: 'action',
              level: 'link',
              size: 'xs',
              actionType: 'copy',
              content: '${path}',
              tooltip: '复制 ${path}',
            },
            {
              disabledOn: 'folder || size > 1048576',
              label: '查看',
              type: 'action',
              level: 'link',
              size: 'xs',
              actionType: 'dialog',
              dialog: {
                title: {
                  type: 'tpl',
                  tpl: '文件内容：${path}',
                },
                size: 'md',
                ...readOnlyDialogOptions(),
                body: {
                  type: 'service',
                  api: {
                    method: 'get',
                    url: `${commonInfo.baseUrl}/hudi/hdfs_read`,
                    data: {
                      root: '${path|default:undefined}',
                    },
                  },
                  body: {
                    type: 'textarea',
                    name: 'text',
                    readOnly: true,
                  },
                },
              },
            },
            {
              disabledOn: 'folder',
              label: '下载',
              type: 'action',
              level: 'link',
              size: 'xs',
              onEvent: {
                click: {
                  actions: [
                    {
                      actionType: 'custom',
                      // @ts-ignore
                      script: (context, action, event) => {
                        let downloadUrl = `${event.data.base}/hudi/hdfs_download?root=${encodeURI(event.data.path)}`
                        window.open(downloadUrl, '_blank')
                      },
                    },
                  ],
                },
              },
            },
          ],
        },
      ],
    },
  }
}

export function copyField(field: string, tips = '复制', ignoreLength = 0) {
  let tpl = ignoreLength === 0 ? `\${${field}}` : `\${TRUNCATE(${field}, ${ignoreLength})}`
  return {
    type: 'wrapper',
    size: 'none',
    body: [
      {
        type: 'tpl',
        className: 'mr-1',
        tpl: tpl,
      },
      {
        type: 'action',
        level: 'link',
        label: '',
        icon: 'fa fa-copy',
        size: 'xs',
        actionType: 'copy',
        content: `\$${field}`,
        tooltip: `${tips}`,
      },
    ],
  }
}

export function flinkJobProperty(id: string, name: string, runMode: string, tags: string) {
  return {
    type: 'property',
    title: 'Flink Job 配置',
    items: [
      {label: 'ID', content: copyField(id, '复制 ID')},
      {label: '任务名称', content: copyField(name, '复制任务名')},
      {
        label: '任务模式',
        content: {
          ...mappingField(`${runMode}`, runModeMapping),
        },
      },
      {
        label: '标签',
        content: {
          type: 'each',
          source: `\${SPLIT(${tags}, ",")}`,
          items: mappingField('item', tagsMapping),
        },
        span: 3,
      },
    ],
  }
}

export function runMetaProperty(runMode: string) {
  return {
    type: 'property',
    title: `${runMode} 运行时信息`,
    items: [
      {label: '运行集群', content: `\${${runMode}Runtime.cluster}`},
      {label: '运行主机', content: copyField(`${runMode}Runtime.host`)},
      {label: '进程', content: copyField(`${runMode}Runtime.jvmPid`)},
      {label: '任务 ID', content: copyField(`${runMode}Runtime.applicationId`), span: 2},
      {label: 'Jar 版本', content: `\${${runMode}Runtime.executorVersion}`},
      {label: '任务名称', content: `\${${runMode}Runtime.flinkJobName}`},
      {label: '容器 ID', content: `\${${runMode}Runtime.containerId}`, span: 2},
      {label: '容器路径', content: copyField(`${runMode}Runtime.containerPath`, undefined, 120), span: 3},
    ],
  }
}

export function statisticsProperty(title: string, statistic: string) {
  return {
    type: 'property',
    title: title,
    column: 3,
    items: [
      {label: '扫描总时间', content: `\${${statistic}.totalScanTime}`},
      {label: '压缩日志文件总数', content: `\${${statistic}.totalLogFilesCompacted}`},
      {label: '压缩日志文件大小', content: `\${${statistic}.totalLogFilesSize}`},
      {label: '删除记录数', content: `\${${statistic}.totalRecordsDeleted}`},
      {label: '更新记录数', content: `\${${statistic}.totalRecordsUpdated}`},
      {label: '压缩日志数', content: `\${${statistic}.totalRecordsCompacted}`},
    ],
  }
}

export function flinkJobDialog() {
  return {
    title: 'Flink job 详情',
    actions: [],
    closeOnEsc: true,
    closeOnOutside: true,
    showCloseButton: false,
    size: 'md',
    body: [
      flinkJobProperty('flinkJobId', 'flinkJob.name', 'flinkJob.runMode', 'flinkJob.tags'),
      {type: 'divider'},
      {
        type: 'action',
        label: '打开同步详情',
        actionType: 'dialog',
        dialog: simpleYarnDialog(commonInfo.clusters.sync_names(), '同步详情', 'syncJobName'),
      },
      {type: 'divider'},
      {
        type: 'service',
        api: {
          method: 'get',
          url: `${commonInfo.baseUrl}/table/list_metas`,
          data: {
            flink_job_id: '${flinkJobId}',
          },
        },
        canAccessSuperData: true,
        body: [
          {
            type: 'table',
            title: '包含 Hudi 同步表',
            source: '${items}',
            columns: [
              {
                label: '别名',
                type: 'wrapper',
                size: 'none',
                body: [
                  {
                    type: 'action',
                    level: 'link',
                    label: '${tableMeta.alias}',
                    size: 'xs',
                    actionType: 'dialog',
                    tooltip: '查看详情',
                    dialog: tableMetaDialog(),
                  },
                  {
                    type: 'action',
                    level: 'link',
                    label: '',
                    icon: 'fa fa-copy',
                    size: 'xs',
                    actionType: 'copy',
                    content: '${tableMeta.alias}',
                    tooltip: '复制别名',
                  },
                ],
              },
              {
                label: '并行度',
                name: 'tableMeta.hudi.writeTasks',
                align: 'center',
              },
              {
                label: 'Bucket 数量',
                name: 'tableMeta.hudi.bucketIndexNumber',
                align: 'center',
              },
              {
                label: '写并行度',
                name: 'tableMeta.hudi.writeTasks',
                align: 'center',
              },
              {
                label: '压缩并行度',
                name: 'tableMeta.hudi.compactionTasks',
                align: 'center',
              },
            ],
          },
        ],
      },
    ],
  }
}

export function timelineColumns() {
  return [
    {
      name: 'timestamp',
      label: '时间点',
      width: 150,
      sortable: true,
    },
    {
      name: 'action',
      label: '类型',
      width: 100,
      ...mappingField('action', hudiTimelineActionMapping),
      filterable: filterableField(hudiTimelineActionMapping, false),
    },
    {
      name: 'state',
      label: ' 状态',
      width: 80,
      align: 'center',
      ...mappingField('state', hudiTimelineStateMapping),
      filterable: filterableField(hudiTimelineStateMapping, true),
    },
    {
      name: 'fileTime',
      label: ' 文件时间',
      width: 150,
      align: 'center',
      type: 'tpl',
      tpl: '${DATETOSTR(DATE(fileTime), \'YYYY-MM-DD HH:mm:ss\')}',
    },
    {
      name: 'fileName',
      label: '文件名',
      type: 'wrapper',
      size: 'none',
      className: 'nowrap',
      body: [
        {
          type: 'tpl',
          tpl: '${fileName}',
        },
        {
          visibleOn: 'action === \'compaction\'',
          type: 'action',
          icon: 'fa fa-eye ml-1',
          level: 'link',
          tooltip: '查看压缩计划',
          size: 'xs',
          actionType: 'dialog',
          dialog: {
            title: '压缩计划详情',
            actions: [],
            size: 'lg',
            body: {
              type: 'crud',
              api: {
                method: 'get',
                url: `${commonInfo.baseUrl}/hudi/read_compaction_plan`,
                data: {
                  hdfs: '${hdfs|default:undefined}',
                  flink_job_id: '${flinkJobId|default:undefined}',
                  alias: '${tableMeta.alias|default:undefined}',
                  instant: '${timestamp|default:undefined}',
                },
                // @ts-ignore
                adaptor: (payload, response) => {
                  return {
                    items: (payload['data']['operations'] ? payload['data']['operations'] : [])
                      // @ts-ignore
                      .map(operation => {
                        if (operation['deltaFilePaths']) {
                          operation.deltaFilePaths = operation.deltaFilePaths
                            // @ts-ignore
                            .map(p => {
                              return {
                                path: p,
                              }
                            })
                        }
                        return operation
                      }),
                  }
                },
              },
              ...crudCommonOptions(),
              loadDataOnce: true,
              ...paginationTemplate(20, 8),
              columns: [
                {
                  name: 'fileId',
                  label: '文件 ID',
                  searchable: true,
                },
                {
                  name: 'baseInstantTime',
                  label: '版本时间点',
                  width: 120,
                  align: 'center',
                },
                {
                  name: 'partitionPath',
                  label: '分区',
                  width: 50,
                  align: 'center',
                },
                {
                  label: '读/写(MB)/数',
                  type: 'tpl',
                  tpl: '${metrics[\'TOTAL_IO_READ_MB\']} / ${metrics[\'TOTAL_IO_WRITE_MB\']} / ${metrics[\'TOTAL_LOG_FILES\']}',
                  align: 'center',
                  width: 90,
                },
                {
                  type: 'operation',
                  label: '操作',
                  width: 150,
                  buttons: [
                    {
                      label: '数据文件名',
                      type: 'action',
                      level: 'link',
                      size: 'xs',
                      actionType: 'copy',
                      content: '${dataFilePath}',
                      tooltip: '复制 ${dataFilePath}',
                    },
                    {
                      label: '日志文件',
                      type: 'action',
                      level: 'link',
                      size: 'xs',
                      actionType: 'dialog',
                      dialog: {
                        title: '操作日志文件列表',
                        size: 'md',
                        ...readOnlyDialogOptions(),
                        body: {
                          type: 'crud',
                          source: '${deltaFilePaths}',
                          mode: 'list',
                          ...crudCommonOptions(),
                          loadDataOnce: true,
                          title: null,
                          listItem: {
                            title: '${path}',
                          },
                        },
                      },
                    },
                  ],
                },
              ],
            },
          },
        },
        {
          visibleOn: 'action === \'rollback\'',
          type: 'action',
          icon: 'fa fa-eye ml-1',
          level: 'link',
          tooltip: '查看回滚计划',
          size: 'xs',
          actionType: 'dialog',
          dialog: {
            title: '回滚计划详情',
            actions: [],
            size: 'lg',
            body: {
              type: 'service',
              api: {
                method: 'get',
                url: `${commonInfo.baseUrl}/hudi/read_rollback_plan`,
                data: {
                  hdfs: '${hdfs|default:undefined}',
                  flink_job_id: '${flinkJobId|default:undefined}',
                  alias: '${tableMeta.alias|default:undefined}',
                  instant: '${timestamp|default:undefined}',
                },
              },
              body: [
                {
                  type: 'property',
                  title: '回滚目标',
                  items: [
                    {
                      label: 'Action',
                      content: {
                        ...mappingField('instantToRollback.action', hudiTimelineActionMapping),
                      },
                    },
                    {label: '时间点', content: '${instantToRollback.commitTime}', span: 2},
                  ],
                },
                {
                  type: 'crud',
                  source: '${rollbackRequests}',
                  ...crudCommonOptions(),
                  columns: [
                    {
                      name: 'fileId',
                      label: '文件 ID',
                      searchable: true,
                    },
                    {
                      name: 'partitionPath',
                      label: '分区',
                      width: 50,
                    },
                    {
                      name: 'latestBaseInstant',
                      label: '数据文件版本',
                    },
                  ],
                },
              ],
            },
          },
        },
        {
          visibleOn: 'action === \'clean\'',
          type: 'action',
          icon: 'fa fa-eye ml-1',
          level: 'link',
          tooltip: '查看清理计划',
          size: 'xs',
          actionType: 'dialog',
          dialog: {
            title: '清理计划详情',
            actions: [],
            size: 'xl',
            body: {
              type: 'service',
              api: {
                method: 'get',
                url: `${commonInfo.baseUrl}/hudi/read_cleaner_plan`,
                data: {
                  hdfs: '${hdfs|default:undefined}',
                  flink_job_id: '${flinkJobId|default:undefined}',
                  alias: '${tableMeta.alias|default:undefined}',
                  instant: '${timestamp|default:undefined}',
                },
                // @ts-ignore
                adaptor: (payload, response) => {
                  if (payload.data['filePathsToBeDeletedPerPartition']) {
                    let map = payload.data['filePathsToBeDeletedPerPartition']
                    let list: Array<Record<string, any>> = []
                    Object.keys(map)
                      .forEach(key => {
                        // @ts-ignore
                        map[key].forEach(file => list.push({
                          partitionPath: key,
                          file: file['filePath'],
                        }))
                      })
                    payload.data['filePathsToBeDeletedPerPartition'] = list
                  }
                  return payload
                },
              },
              body: [
                {
                  type: 'property',
                  title: '最早回滚时间点',
                  items: [
                    {label: '策略', content: '${policy}', span: 3},
                    {
                      label: '操作',
                      content: {
                        ...mappingField('earliestInstantToRetain.action', hudiTimelineActionMapping),
                      },
                    },
                    {
                      label: '状态',
                      content: {
                        ...mappingField('earliestInstantToRetain.state', hudiTimelineStateMapping),
                      },
                    },
                    {label: '时间点', content: '${earliestInstantToRetain.timestamp}'},
                  ],
                },
                {
                  type: 'crud',
                  source: '${filePathsToBeDeletedPerPartition}',
                  ...crudCommonOptions(),
                  ...paginationTemplate(20, 8),
                  loadDataOnce: true,
                  title: '分区删除文件',
                  columns: [
                    {
                      name: 'partitionPath',
                      label: '分区',
                      width: 50,
                      align: 'center',
                    },
                    {
                      name: 'file',
                      label: '清理文件',
                      className: 'nowrap',
                    },
                    {
                      type: 'operation',
                      label: '操作',
                      width: 100,
                      buttons: [
                        {
                          label: '复制路经',
                          type: 'action',
                          level: 'link',
                          size: 'xs',
                          actionType: 'copy',
                          content: '${file}',
                          tooltip: '复制 ${file}',
                        },
                      ],
                    },
                  ],
                },
              ],
            },
          },
        },
      ],
    },
    {
      name: 'type',
      label: '来源',
      width: 60,
      align: 'center',
      ...mappingField('type', hudiTimelineTypeMapping),
      filterable: filterableField(hudiTimelineTypeMapping, true),
    },
  ]
}

export function tableMetaDialog() {
  return {
    title: 'Table 详情',
    actions: [],
    closeOnEsc: true,
    closeOnOutside: true,
    showCloseButton: false,
    size: 'lg',
    body: [
      {
        type: 'wrapper',
        size: 'none',
        body: [
          {
            type: 'tpl',
            className: 'block font-bold mb-2',
            tpl: '常用操作',
          },
          {
            type: 'button-group',
            tiled: false,
            buttons: [
              {
                label: '同步情况',
                type: 'button',
                icon: 'fa fa-arrows-rotate',
                actionType: 'dialog',
                dialog: simpleYarnDialog(commonInfo.clusters.sync_names(), '同步详情', 'syncJobName'),
              },
              {
                label: '压缩情况',
                type: 'action',
                icon: 'fa fa-minimize',
                actionType: 'dialog',
                dialog: simpleYarnDialog(commonInfo.clusters.compaction_names(), '压缩详情', 'compactionJobName'),
              },
              {
                label: '历史压缩',
                type: 'action',
                icon: 'fa fa-list',
                actionType: 'dialog',
                dialog: {
                  title: 'Hudi 表时间线',
                  actions: [],
                  size: 'lg',
                  body: {
                    type: 'crud',
                    api: {
                      method: 'get',
                      url: `${commonInfo.baseUrl}/table/list_compaction_metrics`,
                      data: {
                        page: '${page|default:undefined}',
                        count: '${perPage|default:undefined}',
                        order: '${orderBy|default:update_time}',
                        direction: '${orderDir|default:DESC}',
                        search_flink_job_id: '${flinkJobId|default:undefined}',
                        search_alias: '${tableMeta.alias|default:undefined}',
                        filter_completes: '${complete|default:undefined}',
                      },
                      defaultParams: {
                        filter_type: 'active',
                      },
                    },
                    ...crudCommonOptions(),
                    perPage: 15,
                    headerToolbar: [
                      'reload',
                      paginationCommonOptions(),
                    ],
                    footerToolbar: [
                      paginationCommonOptions(),
                    ],
                    columns: [
                      {
                        name: 'compactionPlanInstant',
                        label: '压缩时间点',
                        width: 180,
                        ...copyField('compactionPlanInstant'),
                      },
                      {
                        name: 'cluster',
                        label: '集群',
                        width: 65,
                        align: 'center',
                        type: 'tpl',
                        tpl: '<span class="label label-info">${cluster}</span>',
                      },
                      {
                        name: 'applicationId',
                        label: '应用',
                        ...copyField('applicationId'),
                      },
                      {
                        name: 'complete',
                        label: '状态',
                        ...mappingField('complete', compactionMetricsStateMapping),
                        filterable: filterableField(compactionMetricsStateMapping, false),
                      },
                      {
                        name: 'startedTime',
                        label: '启动时间',
                        ...timeAndFrom('startedTime', 'startedTimeFromNow'),
                        sortable: true,
                        canAccessSuperData: false,
                      },
                      {
                        name: 'finishedTime',
                        label: '停止时间',
                        ...timeAndFrom('finishedTime', 'finishedTimeFromNow'),
                        sortable: true,
                        align: 'center',
                        canAccessSuperData: false,
                      },
                      {
                        type: 'operation',
                        width: 50,
                        label: '操作',
                        fixed: 'right',
                        className: 'nowrap',
                        buttons: [
                          {
                            label: '详情',
                            type: 'action',
                            level: 'link',
                            actionType: 'dialog',
                            dialog: {
                              title: '压缩详情',
                              size: 'xl',
                              actions: [],
                              closeOnEsc: true,
                              closeOnOutside: true,
                              showCloseButton: false,
                              body: [
                                statisticsProperty('压缩预扫描', 'before'),
                                {type: 'divider'},
                                statisticsProperty('压缩成果', 'after'),
                              ],
                            },
                          },
                        ],
                      },
                    ],
                  },
                },
              },
              {
                type: 'button',
                label: '时间线',
                icon: 'fa fa-timeline',
                actionType: 'dialog',
                dialog: {
                  title: 'Hudi 表时间线',
                  actions: [],
                  size: 'lg',
                  body: {
                    type: 'crud',
                    api: {
                      method: 'get',
                      url: `${commonInfo.baseUrl}/hudi/timeline/list`,
                      data: {
                        page: '${page|default:undefined}',
                        count: '${perPage|default:undefined}',
                        order: '${orderBy|default:undefined}',
                        direction: '${orderDir|default:undefined}',
                        flink_job_id: '${flinkJobId|default:undefined}',
                        alias: '${tableMeta.alias|default:undefined}',
                        filter_type: '${type|default:active}',
                        filter_action: '${action|default:undefined}',
                        filter_state: '${state|default:undefined}',
                      },
                    },
                    ...crudCommonOptions(),
                    perPage: 15,
                    headerToolbar: [
                      'reload',
                      paginationCommonOptions(),
                    ],
                    footerToolbar: [
                      paginationCommonOptions(),
                    ],
                    columns: timelineColumns(),
                  },
                },
              },
              {
                type: 'button',
                label: '数据目录',
                icon: 'fa fa-folder',
                actionType: 'dialog',
                dialog: hdfsDialog('tableMeta.hudi.targetHdfsPath'),
              },
              {
                type: 'button',
                label: 'Pulsar 队列',
                icon: 'fa fa-message',
                actionType: 'dialog',
                dialog: {
                  title: '队列详情',
                  actions: [],
                  size: 'xl',
                  body: {
                    type: 'service',
                    api: {
                      method: 'get',
                      url: `${commonInfo.baseUrl}/pulsar/topic`,
                      data: {
                        pulsar_url: '${tableMeta.pulsarAddress|default:undefined}',
                        topic: '${tableMeta.topic|default:undefined}',
                      },
                    },
                    body: [
                      {
                        type: 'property',
                        title: '基本信息',
                        items: [
                          {label: 'Topic', content: copyField('name'), span: 2},
                          {label: '最末位移', content: copyField('lastMessageId')},
                        ],
                      },
                      {type: 'divider'},
                      {
                        type: 'property',
                        title: '指标信息',
                        column: 4,
                        items: [
                          {label: '入队列消息速率', content: '${state.messageRateIn}'},
                          {
                            label: '出队列消息速率',
                            content: '${state.messageRateOut}',
                          },
                          {
                            label: '入队列消息吞吐量',
                            content: '${state.messageThroughputIn}',
                          },
                          {
                            label: '出队列消息吞吐量',
                            content: '${state.messageThroughputOut}',
                          },
                          {
                            label: '入队列消息数量',
                            content: '${state.messageInCounter}',
                          },
                          {
                            label: '出队列消息数量',
                            content: '${state.messageOutCounter}',
                          },
                          {
                            label: '入队列消息字节数',
                            content: '${state.byteInCounter}',
                          },
                          {
                            label: '出队列消息字节数',
                            content: '${state.byteOutCounter}',
                          },
                          {label: '存储消息大小', content: '${state.storageSize}'},
                          {label: '积压消息大小', content: '${state.backlogSize}'},
                          {
                            label: '平均消息大小',
                            content: '${state.averageMessageSize}',
                          },
                        ],
                      },
                      {type: 'divider'},
                      {
                        type: 'table',
                        title: '消费者们',
                        source: '${subscriptionStateVOS}',
                        itemAction: {
                          type: 'action',
                          actionType: 'dialog',
                          dialog: {
                            title: '详情',
                            closeOnEsc: true,
                            closeOnOutside: true,
                            showCloseButton: false,
                            actions: [],
                            size: 'md',
                            body: [
                              {
                                type: 'property',
                                column: 1,
                                items: [
                                  {
                                    label: '在此订阅上传递的消息的总速率(msg/s)',
                                    content: '${messageRateOut}',
                                  },
                                  {
                                    label: '此订阅提供的总吞吐量(字节/秒)',
                                    content: '${messageThroughputOut}',
                                  },
                                  {
                                    label: '传送给消费者的总字节数(字节)',
                                    content: '${bytesOutCounter}',
                                  },
                                  {
                                    label: '传递给消费者的消息总数(msg)',
                                    content: '${messageOutCounter}',
                                  },
                                  {
                                    label: '此订阅上重新传递的消息的总速率(msg/s)',
                                    content: '${messageRateRedeliver}',
                                  },
                                  {
                                    label: '分块消息调度速率',
                                    content: '${chunkedMessageRate}',
                                  },
                                  {
                                    label: '积压的大小(字节)',
                                    content: '${backlogSize}',
                                  },
                                  {
                                    label: '积压中不包含延迟消息的消息数',
                                    content: '${messageBacklogNoDelayed}',
                                  },
                                  {
                                    label: '验证订阅是否由于达到未确认消息的阈值而被阻止',
                                    content: '${blockedSubscriptionOnUnackedMessages}',
                                  },
                                  {
                                    label: '当前正在跟踪的延迟消息数',
                                    content: '${messageDelayed}',
                                  },
                                  {
                                    label: '订阅的未确认消息数',
                                    content: '${unackedMessages}',
                                  },
                                  {
                                    label: '单个活跃消费者订阅处于活跃状态的消费者名称(故障转移、独占)',
                                    content: '${activeConsumerName}',
                                  },
                                  {
                                    label: '此订阅上过期的消息总速率(msg/s)',
                                    content: '${messageRateExpired}',
                                  },
                                  {
                                    label: '此订阅上过期的消息总数',
                                    content: '${totalMessageExpired}',
                                  },
                                  {
                                    label: '最后一条消息过期时间',
                                    content: {
                                      type: 'tpl',
                                      tpl: '${lastExpireTimestamp|date:YYYY-MM-DD HH\\:mm\\:ss:x}',
                                    },
                                  },
                                  {
                                    label: '上次接收的消费流命令时间',
                                    content: {
                                      type: 'tpl',
                                      tpl: '${lastConsumedFlowTimestamp|date:YYYY-MM-DD HH\\:mm\\:ss:x}',
                                    },
                                  },
                                  {
                                    label: '上次消费消息时间',
                                    content: {
                                      type: 'tpl',
                                      tpl: '${lastConsumedTimestamp|date:YYYY-MM-DD HH\\:mm\\:ss:x}',
                                    },
                                  },
                                  {
                                    label: '上次确认消息时间',
                                    content: {
                                      type: 'tpl',
                                      tpl: '${lastAckedTimestamp|date:YYYY-MM-DD HH\\:mm\\:ss:x}',
                                    },
                                  },
                                  {
                                    label: '此订阅是持久订阅还是临时订阅',
                                    content: '${durable}',
                                  },
                                  {
                                    label: '标记订阅状态在不同区域之间保持同步',
                                    content: '${replicated}',
                                  },
                                ],
                              },
                            ],
                          },
                        },
                        columns: [
                          {
                            name: 'name',
                            label: '订阅名称',
                            ...copyField('name'),
                          },
                          {
                            name: 'type',
                            label: '订阅类型',
                            fixed: 'right',
                            ...mappingField('type', subscriptionTypeMapping),
                          },
                          {name: 'messageBacklog', label: '积压', fixed: 'right'},
                        ],
                      },
                      {type: 'divider'},
                      {
                        type: 'table',
                        title: '生产者们',
                        source: '${state.publishers}',
                        itemAction: {
                          type: 'action',
                          actionType: 'dialog',
                          dialog: {
                            title: '详情',
                            closeOnEsc: true,
                            closeOnOutside: true,
                            showCloseButton: false,
                            actions: [],
                            size: 'md',
                            body: [
                              {
                                type: 'property',
                                column: 1,
                                items: [
                                  {
                                    label: '发布消息速率(msg/s)',
                                    content: '${messageRateIn}',
                                  },
                                  {
                                    label: '发布消息吞吐量(字节/秒)',
                                    content: '${messageThroughputIn}',
                                  },
                                  {
                                    label: '消息平均大小(字节)',
                                    content: '${averageMessageSize}',
                                  },
                                  {
                                    label: '接收到的分块消息总数(msg)',
                                    content: '${chunkedMessageRate}',
                                  },
                                  {label: '生产者地址', content: '${address}'},
                                  {label: '客户端版本', content: '${clientVersion}'},
                                ],
                              },
                            ],
                          },
                        },
                        columns: [
                          {
                            name: 'producerId',
                            label: 'ID',
                            width: 50,
                          },
                          {
                            name: 'producerName',
                            label: '名称',
                            ...copyField('producerName'),
                          },
                          {
                            name: 'connectedSince',
                            label: '连接时间',
                            type: 'tpl',
                            tpl: '${connectedSince}',
                          },
                          {
                            name: 'accessMode',
                            label: '发布类型',
                            fixed: 'right',
                            ...mappingField('accessMode', publishTypeMapping),
                          },
                        ],
                      },
                    ],
                  },
                },
              },
              {
                type: 'button',
                label: 'Hudi 表结构',
                icon: 'fa fa-table',
                actionType: 'dialog',
                dialog: {
                  title: 'Hudi 表结构',
                  actions: [],
                  body: {
                    type: 'service',
                    api: {
                      method: 'get',
                      url: `${commonInfo.baseUrl}/hudi/schema`,
                      data: {
                        flink_job_id: '${flinkJobId|default:undefined}',
                        alias: '${tableMeta.alias|default:undefined}',
                      },
                    },
                    body: {
                      type: 'page',
                      body: {
                        type: 'json',
                        source: '${detail}',
                        levelExpand: 3,
                      },
                    },
                  },
                },
              },
            ],
          },
        ],
      },
      {type: 'divider', visibleOn: '${syncRuntime}'},
      {
        visibleOn: '${syncRuntime}',
        ...runMetaProperty('sync'),
      },
      {type: 'divider', visibleOn: '${compactionRuntime}'},
      {
        visibleOn: '${compactionRuntime}',
        ...runMetaProperty('compaction'),
      },
      {type: 'divider'},
      flinkJobProperty('flinkJobId', 'flinkJob.name', 'flinkJob.runMode', 'flinkJob.tags'),
      {type: 'divider'},
      {
        type: 'property',
        title: 'Table 配置',
        items: [
          {label: '别名', content: copyField('tableMeta.alias', '复制别名')},
          {
            label: '分片表',
            content: '${IF(tableMeta.type === \'sharding\', \'是\', \'否\')}',
          },
          {label: '分区字段', content: copyField('tableMeta.partitionField', '复制分区字段')},
          {label: '源端', content: copyField('tableMeta.source', '复制源端')},
          {label: '源库名', content: copyField('tableMeta.schema', '复制库名')},
          {label: '源表名', content: copyField('tableMeta.table', '复制表名')},
          {label: '源表类型', content: '${tableMeta.sourceType}'},
          {label: '优先级', content: '${tableMeta.priority}', span: 2},
          {
            label: '标签',
            content: {
              type: 'each',
              source: '${SPLIT(tableMeta.tags, ",")}',
              items: mappingField('item', tagsMapping),
            },
            span: 3,
          },
          {label: '订阅 Topic', content: copyField('tableMeta.topic', '复制 Topic'), span: 3},
          {
            label: 'Pulsar 地址',
            content: copyField('tableMeta.pulsarAddress', '复制地址', 130),
            span: 3,
          },
          {label: '过滤模式', content: mappingField('tableMeta.filterType', filterModeMapping)},
          {label: '过滤字段', content: '${tableMeta.filterField}', span: 2},
          {
            label: '过滤内容',
            content: {
              type: 'each',
              source: '${SPLIT(tableMeta.filterValues, ",")}',
              items: {
                type: 'tpl',
                tpl: '<span class=\'label bg-info mr-1\'>${item}</span>',
              },
            },
            span: 3,
          },
        ],
      },
      {type: 'divider'},
      {
        type: 'property',
        title: 'Hudi 配置',
        items: [
          {label: '表类型', content: mappingField('tableMeta.hudi.targetTableType', hudiTableTypeMapping)},
          {label: '库名', content: copyField('tableMeta.hudi.targetDataSource', '复制库名')},
          {label: '表名', content: copyField('tableMeta.hudi.targetTable', '复制表名')},
          {
            label: 'HDFS',
            content: copyField('tableMeta.hudi.targetHdfsPath', '复制路径'),
            span: 3,
          },
          {
            label: 'Bucket 数量',
            content: '${tableMeta.hudi.bucketIndexNumber}',
          },
          {
            label: '保留文件版本',
            content: '${tableMeta.hudi.keepFileVersion}',
          },
          {
            label: '保留提交个数',
            content: '${tableMeta.hudi.keepCommitVersion}',
          },
          {label: '写并行度', content: '${tableMeta.hudi.writeTasks}'},
          {label: '读并行度', content: '${tableMeta.hudi.sourceTasks}'},
          {
            label: '压缩并行度',
            content: '${tableMeta.hudi.compactionTasks}',
          },
          {
            label: '写任务最大内存',
            content: '${tableMeta.hudi. writeTaskMaxMemory}M',
          },
          {
            label: '写批次大小',
            content: '${tableMeta.hudi.writeBatchSize}M',
          },
          {
            label: '写限速',
            content: '${tableMeta.hudi.writeRateLimit}条/秒',
          },
          {
            label: '压缩策略',
            content: '${tableMeta.hudi. compactionStrategy}',
          },
          {
            label: '压缩增量个数',
            content: '${tableMeta.hudi.compactionDeltaCommits}',
          },
          {
            label: '压缩增量时间',
            content: '${tableMeta.hudi.compactionDeltaSeconds}秒',
          },
        ],
      },
      {type: 'divider'},
      {
        type: 'property',
        title: 'Yarn 配置',
        column: 2,
        items: [
          {
            label: '同步 JM 内存',
            content: '${tableMeta.syncYarn.jobManagerMemory}M',
          },
          {
            label: '同步 TM 内存',
            content: '${tableMeta.syncYarn.taskManagerMemory}M',
          },
          {
            label: '压缩 JM 内存',
            content: '${tableMeta.compactionYarn.jobManagerMemory}M',
          },
          {
            label: '压缩 TM 内存',
            content: '${tableMeta.compactionYarn.taskManagerMemory}M',
          },
        ],
      },
      {type: 'divider'},
      {
        type: 'property',
        title: '其他配置',
        column: 4,
        items: [
          {
            label: '指标发布地址',
            content: copyField('tableMeta.config.metricPublishUrl'),
            span: 4,
          },
          {
            label: '指标打点延迟',
            content: '${tableMeta.config.metricPublishDelay}',
          },
          {
            label: '指标打点间隔',
            content: '${tableMeta.config.metricPublishPeriod}',
          },
          {
            label: '指标发布超时',
            content: '${tableMeta.config.metricPublishTimeout}',
          },
          {
            label: '指标批次数量',
            content: '${tableMeta.config.metricPublishBatch}',
          },
          {
            label: 'Prometheus 地址',
            content: copyField('tableMeta.config.metricPrometheusUrl'),
            span: 4,
          },
          {
            label: '事件提交服务地址',
            content: copyField('tableMeta.config.metricApiUrl', '复制 URL', 130),
            span: 4,
          },
          {
            label: 'Checkpoint 存储',
            content: copyField('tableMeta.config.checkpointRootPath'),
            span: 4,
          },
          {
            label: 'Zookeeper 地址',
            content: copyField('tableMeta.config.zookeeperUrl'),
            span: 4,
          },
        ],
      },
      {type: 'divider'},
      {
        type: 'table',
        title: '表字段详情',
        source: '${tableMeta.fields}',
        resizable: false,
        columns: [
          {name: 'sequence', label: '排序', width: 50, align: 'center'},
          {name: 'name', label: '字段名'},
          {name: 'type', label: '字段类型', width: 100},
          {name: 'length', label: '字段长度', width: 60, align: 'center'},
          {name: 'scala', label: '字段精度', width: 60, align: 'center'},
          {
            label: '是否主键',
            align: 'center',
            width: 50,
            type: 'tpl',
            tpl: '${primaryKey|isTrue:\'<i class="fa fa-check-circle text-success text-md p-0"></i>\':\'<i></i>\'|raw}',
          },
          {
            label: '是否分片键',
            align: 'center',
            width: 70,
            type: 'tpl',
            tpl: '${partitionKey|isTrue:\'<i class="fa fa-check-circle text-success text-md p-0"></i>\':\'<i></i>\'|raw}',
          },
        ],
      },
    ],
  }
}

export function mappingItem(label: string, value: string, color = 'bg-info') {
  return {
    label: label,
    value: value,
    color: color,
  }
}

export const runModeMapping = [
  mappingItem('1对1', 'ONE_IN_ONE', 'bg-pink-300'),
  mappingItem('1对多', 'ALL_IN_ONE', 'bg-purple-300'),
  mappingItem('按表1对多', 'ALL_IN_ONE_BY_TABLE', 'bg-cyan-300'),
  mappingItem('按库1对多', 'ALL_IN_ONE_BY_SCHEMA', 'bg-indigo-300'),
]

export const compactionStatusMapping = [
  mappingItem('调度', 'SCHEDULE'),
  mappingItem('开始', 'START', 'bg-primary'),
  mappingItem('完成', 'FINISH', 'bg-success'),
  mappingItem('失败', 'FAIL', 'bg-danger'),
]

export const tagsMapping = [
  mappingItem('不压缩', 'NO_COMPACT'),
  mappingItem('不调度压缩', 'NO_SCHEDULE_COMPACT'),
  mappingItem('备份Pulsar消息', 'PULSAR_BACKUP'),
  mappingItem('无预合并', 'NO_PRE_COMBINE'),
  mappingItem('不忽略写日志错误', 'NO_IGNORE_FAILED'),
  mappingItem('取消算子合并', 'DISABLE_CHAINING'),
  mappingItem('跟踪压缩op_ts', 'TRACE_LATEST_OP_TS'),
  mappingItem('不使用HSync', 'DISABLE_HSYNC'),
  mappingItem('测试包', 'USE_TEST_JAR'),
]

export const hudiTableTypeMapping = [
  mappingItem('MOR', 'MERGE_ON_READ'),
  mappingItem('COW', 'COPY_ON_WRITE'),
]

export const filterModeMapping = [
  mappingItem('无', 'NONE', 'bg-pink-500'),
  mappingItem('包含模式', 'INCLUDE', 'bg-purple-500'),
  mappingItem('排除模式', 'EXCLUDE', 'bg-cyan-500'),
]

export const subscriptionTypeMapping = [
  mappingItem('独占', 'Exclusive', 'bg-pink-500'),
  mappingItem('共享', 'Shared', 'bg-purple-500'),
  mappingItem('灾备', 'Failover', 'bg-cyan-500'),
  mappingItem('Key', 'Key_Shared', 'bg-green-500'),
]

export const publishTypeMapping = [
  mappingItem('共享', 'Shared', 'bg-pink-500'),
  mappingItem('独占', 'Exclusive', 'bg-purple-500'),
  mappingItem('等待独占', 'WaiteForExclusive', 'bg-cyan-500'),
]

export const hudiTimelineActionMapping = [
  mappingItem('Commit', 'commit'),
  mappingItem('Delta Commit', 'deltacommit'),
  mappingItem('Clean', 'clean', 'bg-cyan-500'),
  mappingItem('Rollback', 'rollback', 'label-danger'),
  mappingItem('Savepoint', 'savepoint'),
  mappingItem('Replace Commit', 'replacecommit', 'label-warning'),
  mappingItem('Compaction', 'compaction', 'bg-purple-500'),
  mappingItem('Restore', 'restore', 'label-warning'),
  mappingItem('Indexing', 'indexing'),
  mappingItem('Schema Commit', 'schemacommit', 'label-warning'),
]

export const hudiTimelineStateMapping = [
  mappingItem('已提交', 'REQUESTED'),
  mappingItem('操作中', 'INFLIGHT', 'label-warning'),
  mappingItem('已完成', 'COMPLETED', 'label-success'),
  mappingItem('错误', 'INVALID', 'label-danger'),
]

export const hudiTimelineTypeMapping = [
  mappingItem('活跃', 'active'),
  mappingItem('归档', 'archive', 'bg-gray-300'),
]

export const tableRunningStateMapping = [
  mappingItem('运行中', 'true', 'label-success'),
  mappingItem('未运行', 'false'),
]

export const versionUpdateStateMapping = [
  mappingItem('已跨天', 'true', 'label-success'),
  mappingItem('未跨天', 'false', 'label-danger'),
]

export const compactionMetricsStateMapping = [
  mappingItem('成功', 'true', 'label-success'),
  mappingItem('失败', 'false', 'label-danger'),
]

export function mappingField(field: string, mapping: Array<Record<string, string>>) {
  let mapData: Record<string, string> = {
    '*': `<span class='label bg-gray-300'>\${${field}}</span>`,
  }
  mapping.forEach(item => {
    mapData[item['value']] = `<span class='label ${item['color']}'>${item['label']}</span>`
  })
  return {
    type: 'mapping',
    value: `\${${field}}`,
    map: mapData,
  }
}

export function filterableField(mapping: Array<Record<string, any>>, multiple = false) {
  return {
    multiple: multiple,
    options: [
      ...mapping,
    ],
  }
}

export function formReloadFlinkJobIdTextInputAndAliasTextInput(id: string) {
  return {
    onEvent: {
      change: {
        actions: [
          {
            actionType: 'reload',
            componentId: `flink-job-id-input-select-${id}`,
          },
          {
            actionType: 'reload',
            componentId: `alias-input-select-${id}`,
          },
        ],
      },
    },
  }
}

export function flinkJobIdTextInput(id: string, require = false) {
  return {
    id: `flink-job-id-input-select-${id}`,
    type: 'select',
    name: 'flinkJobId',
    label: 'Flink job id',
    placeholder: '通过 ID 搜索',
    clearable: true,
    required: require,
    searchable: true,
    source: {
      method: 'get',
      url: `${commonInfo.baseUrl}/table/all_flink_job_id`,
      data: {
        alias: '${alias|default:undefined}',
      },
    },
    /*onEvent: {
        change: {
            actions: [
                {
                    actionType: 'reload',
                    componentId: `alias-input-select-${id}`,
                },
            ]
        }
    }*/
  }
}

export function aliasTextInput(id: string, require = false) {
  return {
    id: `alias-input-select-${id}`,
    type: 'select',
    name: 'alias',
    label: '别名',
    placeholder: '通过别名搜索',
    clearable: true,
    required: require,
    searchable: true,
    source: {
      method: 'get',
      url: `${commonInfo.baseUrl}/table/all_alias`,
      data: {
        flink_job_id: '${flinkJobId|default:undefined}',
      },
    },
    /*onEvent: {
        change: {
            actions: [
                {
                    actionType: 'reload',
                    componentId: `flink-job-id-input-select-${id}`
                },
            ]
        }
    }*/
  }
}

export function time(field: string) {
  return {
    type: 'tpl',
    tpl: `\${IF(${field}, DATETOSTR(${field}, 'YYYY-MM-DD HH:mm:ss'), undefined)}`,
  }
}