<template>
  <div class="home-container">
    <el-container>
      <el-header class="page-header openDesignHeader">
        <el-page-header class="text-color-second" :title="t('physical.index.reback')" @back="backToIndex">
          <template #content>
            <span class="text-color font-600 mr-3">{{ t('physical.index.createServer') }}</span>
          </template>
        </el-page-header>
      </el-header>
      <el-main>
        <el-space direction="vertical" fill fill-ratio="100" size="15px" style="width: -webkit-fill-available;" wrap>
          <el-card class="box-card">
            <div class="card-header">
              <el-text tag="b">{{ t('physical.index.serverConfig') }}</el-text>
            </div>
            <div>
              <el-form ref="formServerRef" class="openDesignForm" :model="data.serverData" :rules="formServerRules"
                       label-position="left" label-width="150px">
                <el-form-item :label="$t('components.AddHost.name')" prop="name">
                  <el-input v-model.trim="data.serverData.name" :placeholder="$t('components.AddHost.namePlaceholder')"
                            class="input-width" maxlength="101" />
                </el-form-item>
                <el-form-item :label="$t('components.AddHost.ipAddress')" prop="privateIp" validate-trigger="blur">
                  <el-input v-model.trim="data.serverData.privateIp" :disabled="!isAdd"  maxlength="101"
                            :placeholder="$t('components.AddHost.5mphy3snxdo0')" class="input-width"/>
                </el-form-item>
                <el-form-item :label="$t('components.AddHost.5mphy3snxis0')" prop="publicIp" validate-trigger="blur">
                  <el-input v-model.trim="data.serverData.publicIp" :disabled="!isAdd"  maxlength="101"
                            :placeholder="$t('components.AddHost.5mphy3snxmw0')" class="input-width"
                            @blur="handleBlur"/>
                </el-form-item>
                <el-form-item :label="$t('components.AddHost.5mphy3snxtc0')" prop="port" validate-trigger="blur">
                  <el-input-number v-model="data.serverData.port" :max="65535" :min="0" :placeholder="$t('components.AddHost.5mphy3snxzk0')"
                                   class="input-width inner-class" controls-position="right"/>
                </el-form-item>
                <el-form-item v-if="isAdd" :label="$t('components.AddHost.username')" prop="username"
                              validate-trigger="blur">
                  <el-input v-model.trim="data.serverData.username"  maxlength="101"
                            :placeholder="$t('components.AddHost.usernamePlaceholder')" class="input-width"/>
                </el-form-item>
                <el-form-item v-if="isAdd" :label="$t('components.AddHost.5mphy3sny4w0')" prop="password"
                              validate-trigger="blur">
                  <el-input ref="formPwdRef" v-model="data.serverData.password"  maxlength="101"
                            :invisible-button="data.serverData.password !== data.emptyPwd" show-password
                            :placeholder="$t('components.AddHost.5mphy3snyao0')" class="input-width" clearable
                            type="password" @blur="passwordBlur"
                            @focus="passwordFocus"/>
                </el-form-item>
                <el-form-item :label="$t('components.AddHost.tags')" prop="tags">
                  <el-select v-model="data.serverData.tags" :loading="data.tagsLoading"
                             :placeholder="$t('components.AddHost.tagsPlaceholder')"
                             allow-create class="input-width" clearable multiple filterable
                             @change="tagsChange">
                    <el-option v-for="item in data.tagsList" :key="item.value" :value="item.value">{{
                        item.label
                      }}
                    </el-option>
                  </el-select>
                </el-form-item>
                <el-form-item :label="$t('components.AddHost.5mphy3snysg0')">
                  <el-input v-model.trim="data.serverData.remark" :placeholder="$t('components.AddHost.5mphy3snyxc0')"
                            class="textarea-width" type="textarea"  maxlength="255" />
                </el-form-item>
              </el-form>
            </div>
          </el-card>
          <el-card class="box-card">
            <div>
              <div class="card-header">
                <el-text tag="b">{{ t('physical.index.agentInstall') }}</el-text>
              </div>
              <el-form ref="formAgentRef" :model="data.agentData" :rules="formAgentRules" label-position="left"
                       label-width="150px">
                <el-form-item :label="t('physical.index.installAgent')">
                  <el-switch v-model="data.agentData.isAgent"/>
                </el-form-item>
                <div v-if="data.agentData.isAgent">
                  <el-form-item :label="$t('components.AddAgent.agentName')" prop="agentName">
                    <el-input v-model="data.agentData.agentName"  maxlength="101"
                              :placeholder="$t('components.AddAgent.namePlaceholder')" class="input-width"/>
                  </el-form-item>
                  <el-form-item :label="$t('components.AddAgent.installPath')" prop="installPath">
                    <el-input v-model.trim="data.agentData.installPath"
                              :placeholder="$t('components.AddAgent.installPathPlaceholder')" class="input-width"/>
                  </el-form-item>
                  <el-form-item :label="$t('components.AddHost.5mphy3snxtc0')" prop="agentPort">
                    <el-input-number v-model="data.agentData.agentPort" :max="65535" :min="0" :placeholder="$t('components.AddHost.5mphy3snxzk0')"
                                     class="input-width inner-class" controls-position="right"/>
                  </el-form-item>
                </div>
              </el-form>
            </div>
          </el-card>
        </el-space>
      </el-main>
    </el-container>
        <div class="openDesignFooterButterGap">
          <div class="footerButtonArea">
            <div v-if="data.status !== hostStatusEnum.unTest" class="label-color mr">
              {{ $t('components.AddHost.currentStatus') }}
            </div>
            <el-tag v-if="data.status === hostStatusEnum.success" type="success">
              {{ $t('components.AddHost.5mphy3snvg80') }}
            </el-tag>
            <el-tag v-if="data.status === hostStatusEnum.fail" type="danger">
              {{ $t('components.AddHost.5mphy3snwq40') }}
            </el-tag>
          </div>
          <div class="footerButtonArea">
            <el-button class="mr" @click="close">{{ $t('components.AddHost.5mphy3snwxs0') }}</el-button>
            <el-button v-if="isAdd" :loading="data.testLoading" class="mr" @click="handleTestHost">
              {{ $t('components.AddHost.5mphy3snx3o0') }}
            </el-button>
            <el-button :loading="data.loading" type="primary" @click="submit">
              {{ $t('components.AddHost.5mphy3snx7c0') }}
            </el-button>
          </div>
        </div>
  </div>
</template>

<script lang="ts" setup>
import { IpRegex, KeyValue } from '@/types/global'
import { FormInstance } from '@arco-design/web-vue/es/form'
import { computed, nextTick, onMounted, reactive, ref, toRaw } from 'vue'
import { addAgent, addHost, hostPage, hostPing, hostTagListAll, hostUserListAll, hostUserPage } from '@/api/ops'
import { Message } from '@arco-design/web-vue'
import { useI18n } from 'vue-i18n'
import { encryptPassword } from '@/utils/jsencrypt'
import showMessage from '@/hooks/showMessage'
import { useRoute, useRouter } from 'vue-router'
import WujieVue from 'wujie-vue3'
const { bus } = WujieVue
const { t } = useI18n()

enum hostStatusEnum {
  unTest = -1,
  success = 1,
  fail = 0
}

const data = reactive<KeyValue>({
  show: false,
  title: t('components.AddHost.5mphy3snz5k0'),
  loading: false,
  testLoading: false,
  status: hostStatusEnum.unTest,
  tagsLoading: false,
  tagsList: [],
  oldPwd: '',
  emptyPwd: 'emptyPassword',
  serverData: {
    name: '',
    hostId: '',
    privateIp: '',
    publicIp: '',
    port: 22,
    password: '',
    username: '',
    isRemember: true,
    tags: [],
    remark: ''
  },
  agentData: {
    isAgent: false,
    agentId: '',
    agentName: '',
    agentIp: '',
    agentPort: 10054,
    installPath: '',
    installUser: '',
    installUserId: ''
  }
})

const formServerRules = computed(() => {
  return {
    name: [
      { required: true, trigger: ['change', 'blur'], message: t('components.AddHost.namePlaceholder') },
      {
        validator: (rule: any, value: any, cb: any) => {
          return new Promise(resolve => {
            if (value.length < 100) {
              resolve(true)
            } else {
              cb(t('components.AddAgent.stringLengthOver'))
              resolve(false)
            }
          })
        },
      },
    ],
    privateIp: [
      { required: true, trigger: 'blur', message: t('components.AddHost.5mphy3snxdo0') },
      {
        validator: (rule: any, value: any, cb: any) => {
          console.log(value)
          return new Promise(resolve => {
            if (IpRegex.ipv4Reg.test(value) || IpRegex.ipv6Reg.test(value)) {
              resolve(true)
            } else {
              cb(t('database.JdbcInstance.5oxhtcboblw0'))
              resolve(false)
            }
          })
        }, trigger: 'blur'
      },
    ],
    publicIp: [
      { required: true, trigger: 'blur', message: t('components.AddHost.5mphy3snxmw0') },
      {
        validator: (rule: any, value: any, cb: any) => {
          return new Promise(resolve => {
            if (IpRegex.ipv4Reg.test(value) || IpRegex.ipv6Reg.test(value)) {
              resolve(true)
            } else {
              cb(t('database.JdbcInstance.5oxhtcboblw0'))
              resolve(false)
            }
          })
        }, trigger: 'blur'
      },
    ],
    port: [
      { required: true, trigger: 'blur', message: t('components.AddHost.5mphy3snxzk0') },
      {
        validator: (rule: any, value: any, cb: any) => {
          return new Promise(resolve => {
            if (value <= 65535 && value >0 ) {
              resolve(true)
            } else {
              cb(t('components.AddAgent.numberRangeOver'))
              resolve(false)
            }
          })
        },
      },
    ],
    username: [
      { required: true, trigger: 'blur', message: t('components.AddHost.usernamePlaceholder') },
      {
        validator: (rule: any, value: any, cb: any) => {
          return new Promise(resolve => {
            if (!value.trim()) {
              cb(t('database.JdbcInstance.5oxhtcbobtc0'))
              resolve(false)
            } else {
              if (value.length > 100) {
                cb(t('components.AddAgent.stringLengthOver'))
                resolve(false)
              } else {
                resolve(true)
              }
            }
          })
        }
      }
    ],
    password: [
      { required: true, 'validate-trigger': 'blur', message: t('components.AddHost.5mphy3snyao0') },
      {
        validator: (rule: any, value: any, cb: any) => {
          return new Promise(resolve => {
            if (value.length < 100) {
              resolve(true)
            } else {
              cb(t('components.AddAgent.stringLengthOver'))
              resolve(false)
            }
          })
        },
      },
    ]
  }
})

const formAgentRules = computed(() => {
  return {
    agentName: [
      { required: data.agentData.isAgent, trigger: 'blur', message: t('components.AddHost.namePlaceholder') },
      {
        validator: (rule: any, value: any, cb: any) => {
          return new Promise(resolve => {
            if (value.trim().length === 0 && value.length > 0) {
              cb(t('components.AddAgent.namePlaceholder'))
              return resolve(false)
            }
            if (value.length < 100) {
              resolve(true)
            } else {
              cb(t('components.AddAgent.stringLengthOver'))
              resolve(false)
            }
          })
        },
      },
    ],
    installPath: [
      { required: data.agentData.isAgent, trigger: 'blur', message: t('components.AddHost.5mphy3snxdo0') },
      {
        validator: (rule: any, value: any, callback: any) => {
          if (value.length >= 255) {
            callback(new Error(t('components.AddAgent.stringLengthOver')))
            return
          }
          if (/[\u4e00-\u9fa5]/.test(value)) {
            callback(new Error(t('components.AddAgent.noChinesePath')))
            return
          }
          const isValidPath = (path: any) => {
            if (path === '/' || path === '~') return true
            if (path.startsWith('~/')) {
              return !path.endsWith('/') && !path.includes('//')
            }
            const pathRegex = /^(?!.*\/\/)(?!.*\/$)(\/|\.\/)?([\w-]+(\/[\w-]+)*)?$/
            return pathRegex.test(path)
          }
          const isDepthValid = (path: string) => {
            if (path === '/' || path === '~') return true
            let pathToCheck = path
            if (path.startsWith('~/')) {
              pathToCheck = path.substring(1)
            }
            if (pathToCheck.startsWith('./')) pathToCheck = pathToCheck.substring(2)
            if (pathToCheck.startsWith('../')) pathToCheck = pathToCheck.substring(3)
            const components = pathToCheck.split('/').filter(comp => comp !== '')
            return components.length <= 5
          }
          if (!isValidPath(value)) {
            callback(new Error(t('components.AddAgent.formaterror')))
            return
          }
          if (!isDepthValid(value)) {
            callback(new Error(t('components.AddAgent.pathDepthExceeded')))
            return
          }
          callback()
        },
        trigger: ['blur', 'change']
      }
    ],
    agentPort: [
      { required: data.agentData.isAgent, trigger: 'blur', message: t('components.AddHost.5mphy3snxzk0') },
      {
        validator: (rule: any, value: any, cb: any) => {
          return new Promise(resolve => {
            if (value <= 65535 && value >0 ) {
              resolve(true)
            } else {
              cb(t('components.AddAgent.numberRangeOver'))
              resolve(false)
            }
          })
        },
      },
    ]
  }
})

const emits = defineEmits([`finish`])
const formServerRef = ref<null | FormInstance>(null)
const formAgentRef = ref<null | FormInstance>(null)

let agentInstallError = false
const submit = async () => {
  try {
    await formServerRef.value?.validate()
    await formAgentRef.value?.validate()
    data.loading = true
    encryptPassword(data.serverData.password).then(async (res) => {
      const param = Object.assign({}, data.serverData)
      param.password = res
      const finishServer = (showMessageInfo: any) => {
        if (showMessageInfo === '1') {
          showMessage('success', t('components.AddHost.addAgentSuc'))
        } else {
          showMessage('success', t('components.AddHost.addServerSuc'))
        }
        emits('finish')
        close()
      }
      const addAgentHandler = async () => {
        try {
          const agentData = {
            agentId: data.agentData.agentId,
            agentIp: data.agentData.agentIp,
            agentName: data.agentData.agentName,
            agentPort: data.agentData.agentPort,
            installPath: data.agentData.installPath,
            installUser: data.agentData.installUser,
            installUserId: data.agentData.installUserId
          }
          const res = await addAgent(agentData)
          if (Number(res.code) === 200) {
            agentInstallError = false
            finishServer('1')
          }
        } catch (error) {
          console.log(error)
          agentInstallError = true
        }
      }
      if (data.serverData.hostId === '' && !agentInstallError) {
        try {
          const res = await addHost(param)
          data.loading = false
          if (Number(res.code) !== 200) return
          if (!data.agentData.isAgent) {
            finishServer('2')
            return
          }
          data.agentData.installUser = data.serverData.username
          const hostRes = await hostPage({
            name: data.serverData.privateIp,
            tagIds: '',
            os: '',
            pageNum: 1,
            pageSize: 10
          })
          if (Number(hostRes.code) === 200) {
            data.agentData.agentId = hostRes.rows[0].hostId
            data.serverData.hostId = hostRes.rows[0].hostId
          }
          const userRes = await hostUserPage(data.agentData.agentId)
          data.agentData.installUserId = userRes.rows[0].hostUserId
          data.agentData.agentIp = data.serverData.privateIp
          await addAgentHandler()
        } catch (error) {
          console.log(error)
          showMessage('error', error)
          agentInstallError = true
        } finally {
          data.loading = false
        }
      } else {
        if (!data.agentData.isAgent) {
          finishServer('2')
        } else {
          await addAgentHandler()
        }
      }
    })
  } catch (error) {
    showMessage('error', t('components.AddHost.unFill'))
  }
}
const close = () => {
  agentInstallError = false
  data.show = false
  data.oldPwd = ''
  data.serverData.password = ''
  data.serverData.username = ''
  backToIndex()
  nextTick(() => {
    formServerRef.value?.clearValidate()
    formServerRef.value?.resetFields()
    formAgentRef.value?.clearValidate()
    formAgentRef.value?.resetFields()
  })
}

const tagsChange = (val: any) => {
  data.serverData.tags = val.filter((item: string) => {
    return item.trim() !== ''
  })
}

const passwordFocus = () => {
  if (data.serverData.password === data.emptyPwd) {
    data.serverData.password = ''
  }
}
const formPwdRef = ref()
const passwordBlur = () => {
  if (!data.serverData.password && data.oldPwd) {
    formPwdRef.value.invisible = true
    data.serverData.password = data.emptyPwd
  }
}

const handleTestHost = () => {
  formServerRef.value?.validate().then(async result => {
    if (result) {
      const {privateIp, publicIp, port, remark, username, hostId, password} = data.serverData
      data.testLoading = true
      let encryptPwd
      if (hostId && password === data.emptyPwd) {
        encryptPwd = data.oldPwd
      } else {
        encryptPwd = await encryptPassword(password)
      }
      const param = {}
      Object.assign(param, {
        privateIp,
        publicIp,
        port,
        password: encryptPwd,
        isRemember: true,
        remark,
        username
      })

      hostPing(toRaw(param)).then((res: KeyValue) => {
        if (Number(res.code) === 200) {
          data.status = hostStatusEnum.success
        } else {
          data.status = hostStatusEnum.fail
        }
      }).catch(() => {
        data.status = hostStatusEnum.fail
      }).finally(() => {
        data.testLoading = false
      })
    }
  }) .catch((error) => {
    console.log(error)
  })
}

const getAllTag = () => {
  data.tagsLoading = true
  hostTagListAll().then((res: KeyValue) => {
    if (Number(res.code) === 200) {
      data.tagsList = []
      res.data.forEach((item: KeyValue) => {
        const temp = {
          label: item.name,
          value: item.name
        }
        data.tagsList.push(temp)
      })
    }
  }).finally(() => {
    data.tagsLoading = false
  })
}

const isAdd = ref(true)
const open = () => {
  data.show = true
  getAllTag()
  data.status = hostStatusEnum.unTest
  data.loading = false
  isAdd.value = true
  data.title = t('components.AddHost.5mphy3snz5k0')
  Object.assign(data.serverData, {
    hostId: '',
    privateIp: '',
    publicIp: '',
    password: '',
    isRemember: true,
    port: 22,
    remark: ''
  })
  Object.assign(data.agentData, {
    agentId: '',
    agentName: '',
    agentIp: '',
    agentPort: 10054,
    installPath: '',
    installUser: '',
    installUserId: '',
    privateIp: '',
    publicIp: ''
  })
}

const handleBlur = () => {
  if (!data.serverData.name) {
    data.serverData.name = data.serverData.publicIp
  }
}

const route = useRoute()
const router = useRouter()
const backToIndex = () => {
  bus.$emit('opengauss-close-tab', route)
  router.push({
    name: 'ResourcePhysical'
  })
}

defineExpose({
  open
})
onMounted(() => {
  open()
})

</script>

<style lang="scss" scoped>

.input-width {
  width: 440px;
}

.textarea-width {
  width: 708px;
  height: 73px;
}

.home-container {
  position: relative;
  height: calc(100vh - 123px);
  padding-bottom: 24px;
  background: var(--o-bg-color-light);
  .el-container {
    height: 100%;
  }
  .el-main {
    padding: 16px 24px 20px;
    .card-header {
      .el-text {
        color: var(--o-text-color-primary);
      }
    }
  }

  .box-card {
    background-color: var(--o-bg-color-base);
    border: 1px solid var(--o-border-color-base);
  }

  .main-con {
    height: calc(100vh - 123px);
    padding-bottom: 40px;
    overflow-y: auto;
  }

  .submit-con {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 10;
    height: 45px;
    padding-left: 20px;
    padding-right: 20px;
    padding-top: 10px;

    background: var(--color-bg-2);
    border-top: 1px solid #e4e7ed;

    .btn-group {
      height: 100%;
      display: flex;
      justify-content: flex-end;
      align-items: center;
      gap: 20px;
    }

    .btn-item {
      margin-left: 10px;
      min-width: 80px;
    }
  }
}

.inner-class :deep(.el-input__inner) {
  text-align: left !important;
  padding-right: 30px;
}

</style>