<script setup lang="ts">
import { reactive, onMounted, toRaw } from 'vue';
import { message, Form, Modal } from 'ant-design-vue/es';
import useI18n from '@/hooks/useI18n';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { regExpIPv4, regExpIPv6 } from '@/utils/regular-utils';
import { neHostAuthorizedRSA, neHostCheckInfo } from '@/api/ne/neHost';
import useDictStore from '@/store/modules/dict';
import { fnToStepName, stepState } from '../hooks/useStep';
const { getDict } = useDictStore();
const { t } = useI18n();

/**字典数据 */
let dict: {
  /**认证模式 */
  neHostAuthMode: DictType[];
} = reactive({
  neHostAuthMode: [],
});

/**对象信息状态类型 */
type StateType = {
  /**服务器信息 */
  info: Record<string, any>;
  /**表单数据 */
  from: Record<string, any>;
  /**是否可以下一步 */
  stepNext: boolean;
  /**确定按钮 loading */
  confirmLoading: boolean;
};

/**对象信息状态 */
let state: StateType = reactive({
  info: {
    addr: '0.0.0.0',
    kernelName: '-',
    kernelRelease: '-',
    machine: '-',
    nodename: '-',
    prettyName: '-',
    sshLink: false,
    sudo: false,
  },
  from: {
    id: undefined,
    hostType: 'ssh',
    groupId: '1',
    title: 'SSH_NE_22',
    addr: '',
    port: 22,
    user: '',
    authMode: '2',
    password: '',
    privateKey: '',
    passPhrase: '',
    remark: '',
  },
  stepNext: false,
  confirmLoading: false,
});

/**表单属性和校验规则 */
const checkStateFrom = Form.useForm(
  state.from,
  reactive({
    addr: [
      {
        required: true,
        min: 1,
        max: 128,
        validator: modalStateFromEqualIPV4AndIPV6,
      },
    ],
    port: [
      {
        required: true,
        message: t('views.ne.neHost.portPlease'),
      },
    ],
    user: [
      {
        required: true,
        min: 1,
        max: 50,
        message: t('views.ne.neHost.userPlease'),
      },
    ],
    password: [
      {
        required: true,
        min: 1,
        max: 128,
        message: t('views.ne.neHost.passwordPlease'),
      },
    ],
    privateKey: [
      {
        required: true,
        min: 1,
        max: 3000,
        message: t('views.ne.neHost.privateKeyPlease'),
      },
    ],
  })
);

/**表单验证IP地址是否有效 */
function modalStateFromEqualIPV4AndIPV6(
  rule: Record<string, any>,
  value: string,
  callback: (error?: string) => void
) {
  if (!value) {
    return Promise.reject(t('views.ne.common.ipAddrPlease'));
  }

  if (value.indexOf('.') === -1 && value.indexOf(':') === -1) {
    return Promise.reject(t('valid.ipPlease'));
  }
  if (value.indexOf('.') !== -1 && !regExpIPv4.test(value)) {
    return Promise.reject(t('valid.ipv4Reg'));
  }
  if (value.indexOf(':') !== -1 && !regExpIPv6.test(value)) {
    return Promise.reject(t('valid.ipv6Reg'));
  }
  return Promise.resolve();
}

/**测试连接检查信息 */
function fnCheckInfo() {
  if (state.confirmLoading) return;
  const form = toRaw(state.from);
  const validateArr = ['addr', 'port', 'user'];
  if (form.authMode === '0') {
    validateArr.push('password');
  }
  if (form.authMode === '1') {
    validateArr.push('privateKey');
  }

  state.confirmLoading = true;
  const hide = message.loading(t('common.loading'), 0);
  checkStateFrom
    .validate(validateArr)
    .then(() => {
      Object.assign(state.info, {
        addr: '0.0.0.0',
        kernelName: '-',
        kernelRelease: '-',
        machine: '-',
        nodename: '-',
        prettyName: '-',
        sshLink: false,
        sudo: false,
      });
      return neHostCheckInfo(form);
    })
    .then(res => {
      if (res.code === RESULT_CODE_SUCCESS) {
        state.info = res.data;
        if (!res.data.sudo) {
          message.warning(t('views.ne.neQuickSetup.sudoErr'), 3);
          return;
        }
        // if (!res.data.sshLink) {
        //   message.warning({
        //     content: `请配置服务器间免密信任关系，确保服务器间文件传输功能`,
        //     duration: 2,
        //   });
        //   return;
        // }

        stepState.neHost = form; // 保存主机连接信息
        state.stepNext = true; // 开启下一步
        message.success({
          content: `${form.addr}:${form.port} ${t('views.ne.neHost.testOk')}`,
          duration: 2,
        });
      } else {
        message.error({
          content: `${form.addr}:${form.port} ${res.msg}`,
          duration: 2,
        });
      }
    })
    .catch(e => {
      message.error(t('common.errorFields', { num: e.errorFields.length }), 3);
    })
    .finally(() => {
      hide();
      state.confirmLoading = false;
    });
}

/**测试连接检查信息表单重置 */
function fnCheckInfoReset() {
  Object.assign(state.info, {
    addr: '0.0.0.0',
    kernelName: '-',
    kernelRelease: '-',
    machine: '-',
    nodename: '-',
    prettyName: '-',
    sshLink: false,
    sudo: false,
  });
  state.stepNext = false;
  checkStateFrom.resetFields();
}

/**测试主机连接-免密直连 */
function fnHostAuthorized() {
  if (state.confirmLoading) return;

  Modal.confirm({
    title: t('common.tipTitle'),
    content: t('views.ne.neHost.authRSATip'),
    onOk: () => {
      const form = toRaw(state.from);
      state.confirmLoading = true;
      neHostAuthorizedRSA(form).then(res => {
        state.confirmLoading = false;
        if (res.code === RESULT_CODE_SUCCESS) {
          message.success(t('common.operateOk'), 3);
        } else {
          message.error(t('common.operateErr'), 3);
        }
      });
    },
  });
}

/**返回上一步 */
function fnStepPrev() {
  Modal.confirm({
    title: t('common.tipTitle'),
    content: t('views.ne.neQuickSetup.stepPrevTip'),
    onOk() {
      fnToStepName('Para5G');
    },
  });
}

/**下一步操作 */
function fnStepNext() {
  if (!state.stepNext) return;
  Modal.confirm({
    title: t('common.tipTitle'),
    content: t('views.ne.neQuickSetup.startStepNext'),
    onOk() {
      fnToStepName('NeInfoConfig');
    },
  });
}

onMounted(() => {
  // 初始字典数据
  Promise.allSettled([getDict('ne_host_authMode')]).then(resArr => {
    if (resArr[0].status === 'fulfilled') {
      dict.neHostAuthMode = resArr[0].value;
    }
  });
});
</script>

<template>
  <div class="ne">
    <a-descriptions :column="{ lg: 3, md: 2, sm: 2, xs: 1 }" bordered>
      <a-descriptions-item :label="t('views.ne.neQuickSetup.addr')" :span="3">
        {{ state.info.addr }}
      </a-descriptions-item>
      <a-descriptions-item :label="t('views.ne.neQuickSetup.kernelName')">
        {{ state.info.kernelName }}
      </a-descriptions-item>
      <a-descriptions-item :label="t('views.ne.neQuickSetup.machine')">
        {{ state.info.machine }}
      </a-descriptions-item>
      <a-descriptions-item :label="t('views.ne.neQuickSetup.kernelRelease')">
        {{ state.info.kernelRelease }}
      </a-descriptions-item>
      <a-descriptions-item>
        <template #label>
          {{ t('views.ne.neQuickSetup.prettyName') }}
          <a-tooltip placement="topLeft">
            <template #title>
              {{ t('views.ne.neQuickSetup.prettyNameTip') }}
            </template>
            <InfoCircleOutlined style="opacity: 0.45; color: inherit" />
          </a-tooltip>
        </template>
        {{ state.info.prettyName }}
      </a-descriptions-item>
      <a-descriptions-item :label="t('views.ne.neQuickSetup.nodename')">
        {{ state.info.nodename }}
      </a-descriptions-item>
      <a-descriptions-item :label="t('views.ne.neQuickSetup.auth')">
        <a-tag :color="state.info.sudo ? 'success' : 'error'">
          <template #icon>
            <CheckCircleOutlined v-if="state.info.sudo" />
            <CloseCircleOutlined v-else />
          </template>
          {{ t('views.ne.neQuickSetup.sudo') }}
        </a-tag>

        <a-tag :color="state.info.sshLink ? 'success' : 'error'">
          <template #icon>
            <CheckCircleOutlined v-if="state.info.sshLink" />
            <CloseCircleOutlined v-else />
          </template>
          {{ t('views.ne.neQuickSetup.sshLink') }}
        </a-tag>
      </a-descriptions-item>
    </a-descriptions>

    <a-form
      name="checkStateFrom"
      layout="horizontal"
      :label-col="{ span: 6 }"
      :label-wrap="true"
      style="margin-top: 20px; width: 68%"
    >
      <a-row>
        <a-col :lg="12" :md="12" :xs="24">
          <a-form-item
            :label="t('views.ne.neHost.addr')"
            name="addr"
            v-bind="checkStateFrom.validateInfos.addr"
          >
            <a-input
              v-model:value="state.from.addr"
              allow-clear
              :maxlength="128"
              :placeholder="t('common.inputPlease')"
            >
            </a-input>
          </a-form-item>
        </a-col>
        <a-col :lg="12" :md="12" :xs="24">
          <a-form-item
            :label="t('views.ne.neHost.port')"
            name="port"
            v-bind="checkStateFrom.validateInfos.port"
          >
            <a-input-number
              v-model:value="state.from.port"
              :min="10"
              :max="65535"
              :step="1"
              :maxlength="5"
              style="width: 100%"
            ></a-input-number>
          </a-form-item>
        </a-col>
      </a-row>

      <a-row>
        <a-col :lg="12" :md="12" :xs="24">
          <a-form-item
            :label="t('views.ne.neHost.user')"
            name="user"
            v-bind="checkStateFrom.validateInfos.user"
          >
            <a-input
              v-model:value="state.from.user"
              allow-clear
              :maxlength="32"
              :placeholder="t('common.inputPlease')"
            >
            </a-input>
          </a-form-item>
        </a-col>
        <a-col :lg="12" :md="12" :xs="24">
          <a-form-item :label="t('views.ne.neHost.authMode')">
            <a-select
              v-model:value="state.from.authMode"
              default-value="0"
              :options="dict.neHostAuthMode"
            >
            </a-select>
          </a-form-item>
        </a-col>
      </a-row>

      <a-form-item
        v-if="state.from.authMode === '0'"
        :label="t('views.ne.neHost.password')"
        :label-col="{ span: 3 }"
        :label-wrap="true"
        name="password"
        v-bind="checkStateFrom.validateInfos.password"
      >
        <a-input-password
          v-model:value="state.from.password"
          :maxlength="128"
          :placeholder="t('common.inputPlease')"
        >
        </a-input-password>
      </a-form-item>

      <template v-if="state.from.authMode === '1'">
        <a-form-item
          :label="t('views.ne.neHost.privateKey')"
          :label-col="{ span: 3 }"
          :label-wrap="true"
          name="privateKey"
          v-bind="checkStateFrom.validateInfos.privateKey"
        >
          <a-textarea
            v-model:value="state.from.privateKey"
            :auto-size="{ minRows: 4, maxRows: 6 }"
            :maxlength="3000"
            :show-count="true"
            :placeholder="t('views.ne.neHost.privateKeyPlease')"
          />
        </a-form-item>

        <a-form-item
          :label="t('views.ne.neHost.passPhrase')"
          :label-col="{ span: 3 }"
          :label-wrap="true"
        >
          <a-input-password
            v-model:value="state.from.passPhrase"
            :maxlength="128"
            :placeholder="t('common.inputPlease')"
          >
          </a-input-password>
        </a-form-item>
      </template>

      <a-form-item :wrapper-col="{ span: 8, offset: 3 }">
        <a-space direction="horizontal" :size="18">
          <a-button
            type="primary"
            ghost
            html-type="submit"
            @click="fnCheckInfo()"
            :loading="state.confirmLoading"
          >
            {{ t('views.ne.neHost.test') }}
          </a-button>

          <a-button
            type="dashed"
            @click="fnHostAuthorized()"
            :disabled="state.confirmLoading"
            v-if="state.from.authMode !== '2'"
          >
            {{ t('views.ne.neHost.authRSA') }}
          </a-button>

          <a-button
            type="link"
            @click="fnCheckInfoReset()"
            :disabled="state.confirmLoading"
          >
            {{ t('common.reset') }}
          </a-button>
        </a-space>
      </a-form-item>
    </a-form>

    <div class="ne-oper">
      <a-space direction="horizontal" :size="18">
        <a-button @click="fnStepPrev()">
          {{ t('views.ne.neQuickSetup.stepPrev') }}
        </a-button>

        <a-button
          type="primary"
          @click="fnStepNext()"
          :disabled="!state.stepNext"
        >
          {{ t('views.ne.neQuickSetup.stepNext') }}
        </a-button>
      </a-space>
    </div>
  </div>
</template>

<style lang="less" scoped>
.ne {
  min-height: 400px;
  display: flex;
  flex-direction: column;

  & .ant-form {
    flex: 1;
  }

  &-oper {
    text-align: end;
  }
}
</style>
