<script setup lang="ts">
import { Form, Modal, message } from 'ant-design-vue/lib';
import { onMounted, reactive, toRaw } from 'vue';
import { addNeInfo, getNeInfoByTypeAndID, updateNeInfo } from '@/api/ne/neInfo';
import { neHostAuthorizedRSA, testNeHost } from '@/api/ne/neHost';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { NE_TYPE_LIST } from '@/constants/ne-constants';
import { fnRestStepState, fnToStepName, stepState } from '../hooks/useStep';
import useI18n from '@/hooks/useI18n';
import useDictStore from '@/store/modules/dict';
import useNeInfoStore from '@/store/modules/neinfo';
const { getDict } = useDictStore();
const { t } = useI18n();

/**字典数据 */
let dict: {
  /**主机类型 */
  neHostType: DictType[];
  /**分组 */
  neHostGroupId: DictType[];
  /**认证模式 */
  neHostAuthMode: DictType[];
} = reactive({
  neHostType: [],
  neHostGroupId: [],
  neHostAuthMode: [],
});

/**对话框对象信息状态类型 */
type ModalStateType = {
  /**是否可以下一步 */
  stepNext: boolean;
  /**标题 */
  title: string;
  /**表单数据 */
  from: Record<string, any>;
  /**确定按钮 loading */
  confirmLoading: boolean;
};

/**对话框对象信息状态 */
let modalState: ModalStateType = reactive({
  stepNext: false,
  title: '网元',
  from: {
    id: undefined,
    neId: '001',
    neType: 'AMF',
    neName: '',
    ip: '',
    port: 33030,
    pvFlag: 'PNF',
    rmUid: '4400HX1AMF001',
    neAddress: '',
    dn: '',
    vendorName: '',
    province: '',
    // 主机
    hosts: [
      {
        hostId: undefined,
        hostType: 'ssh',
        groupId: '1',
        title: 'SSH_NE_22',
        addr: '',
        port: 22,
        user: 'user',
        authMode: '0',
        password: 'user',
        privateKey: '',
        passPhrase: '',
        remark: '',
      },
      {
        hostId: undefined,
        hostType: 'telnet',
        groupId: '1',
        title: 'Telnet_NE_4100',
        addr: '',
        port: 4100,
        user: 'user',
        authMode: '0',
        password: 'user',
        remark: '',
      },
    ],
  },
  confirmLoading: false,
});

/**对话框内表单属性和校验规则 */
const modalStateFrom = Form.useForm(
  modalState.from,
  reactive({
    neType: [
      {
        required: true,
        message: '请输入网元类型',
      },
    ],
    neId: [
      {
        required: true,
        message: '请输入网元标识',
      },
    ],
    rmUid: [
      {
        required: true,
        message: '请输入资源唯一标识',
      },
    ],
    ip: [
      {
        required: true,
        message: '请输入网元IP地址',
      },
    ],
    neName: [
      {
        required: true,
        message: '请输入网元名称',
      },
    ],
  })
);

/**
 * 测试主机连接
 */
function fnHostTest(row: Record<string, any>) {
  if (modalState.confirmLoading || !row.addr) return;
  modalState.confirmLoading = true;
  const hide = message.loading(t('common.loading'), 0);
  testNeHost(row)
    .then(res => {
      if (res.code === RESULT_CODE_SUCCESS) {
        message.success({
          content: `${row.addr}:${row.port} ${t('views.ne.neHost.testOk')}`,
          duration: 2,
        });
      } else {
        message.error({
          content: `${row.addr}:${row.port} ${res.msg}`,
          duration: 2,
        });
      }
    })
    .finally(() => {
      hide();
      modalState.confirmLoading = false;
    });
}

/**测试主机连接-免密直连 */
function fnHostAuthorized(row: Record<string, any>) {
  if (modalState.confirmLoading) return;

  Modal.confirm({
    title: '提示',
    content: '是否要配置免密直连？',
    onOk: () => {
      modalState.confirmLoading = true;
      neHostAuthorizedRSA(row).then(res => {
        modalState.confirmLoading = false;
        if (res.code === RESULT_CODE_SUCCESS) {
          message.success({
            content: `操作成功`,
            duration: 2,
          });
        } else {
          message.error({
            content: `操作失败`,
            duration: 2,
          });
        }
      });
    },
  });
}

/**
 * 对话框弹出确认执行函数
 * 进行表达规则校验
 */
function fnModalOk() {
  const from = toRaw(modalState.from);
  modalStateFrom
    .validate()
    .then(e => {
      modalState.confirmLoading = true;
      return getNeInfoByTypeAndID(from.neType, from.neId);
    })
    .then(res => {
      if (res.code === RESULT_CODE_SUCCESS) {
        // 补充更新必要信息
        from.id = res.data.id;
        from.hostIds = res.data.hostIds;
        const hostIds = res.data.hostIds.split(',');
        if (hostIds.length == 2) {
          from.hosts[0].hostId = hostIds[0];
          from.hosts[1].hostId = hostIds[1];
        }
        return true;
      } else {
        // 清除更新必要信息
        from.id = undefined;
        from.hostIds = '';
        for (let index = 0; index < from.hosts.length; index++) {
          from.hosts[index].hostId = undefined;
        }
        return false;
      }
    })
    .then(isUpdate => {
      let confirmTitle = '新增提示';
      let confirmContent = `是否新增为新的网元信息并继续？`;
      if (isUpdate) {
        confirmTitle = '更新提示';
        confirmContent = `是否更新到已存在网元信息并继续？`;
      }
      Modal.confirm({
        title: confirmTitle,
        content: confirmContent,
        onCancel: () => {
          // 清除更新必要信息
          from.id = undefined;
          from.hostIds = '';
          for (let index = 0; index < from.hosts.length; index++) {
            from.hosts[index].hostId = undefined;
          }
        },
        onOk: () => {
          const hide = message.loading(t('common.loading'), 0);
          const result =
            isUpdate && from.id ? updateNeInfo(from) : addNeInfo(from);
          result
            .then(res => {
              if (res.code === RESULT_CODE_SUCCESS) {
                message.success({
                  content: `${t('common.operateOk')}`,
                  duration: 3,
                });
                // 刷新缓存的网元信息
                useNeInfoStore().fnRefreshNelist();
                stepState.neInfo = from; // 保存网元信息
                modalState.stepNext = true; // 开启下一步
              } else {
                message.error({
                  content: `${t('common.operateErr')}`,
                  duration: 3,
                });
              }
            })
            .finally(() => {
              hide();
              modalState.confirmLoading = false;
            });
        },
      });
    })
    .catch(e => {
      message.error(t('common.errorFields', { num: e.errorFields.length }), 3);
    })
    .finally(() => {
      modalState.confirmLoading = false;
    });
}

/**
 * 表单修改网元类型
 */
function fnNeTypeChange(v: any) {
  const hostsLen = modalState.from.hosts.length;
  // 网元默认只含22和4100
  if (hostsLen === 3 && v !== 'UPF') {
    modalState.from.hosts.pop();
  }
  // UPF标准版本可支持5002
  if (hostsLen === 2 && v === 'UPF') {
    modalState.from.hosts.push({
      hostId: undefined,
      hostType: 'telnet',
      groupId: '1',
      title: 'Telnet_NE_5002',
      addr: '',
      port: 5002,
      user: 'user',
      authMode: '0',
      password: 'user',
      remark: '',
    });
  }
}

/**
 * 表单修改网元IP
 */
function fnNeIPChange(e: any) {
  const v = e.target.value;
  if (v.length < 7) return;
  for (const host of modalState.from.hosts) {
    host.addr = v;
  }
}

/**返回上一步 */
function fnStepPrev() {
  Modal.confirm({
    title: t('common.tipTitle'),
    content: '确认要放弃当前变更返回上一步吗？',
    onOk() {
      fnRestStepState();
      fnToStepName('Start');
    },
  });
}

/**下一步操作 */
function fnStepNext() {
  if (!modalState.stepNext) return;
  Modal.confirm({
    title: t('common.tipTitle'),
    content: '确认要下一步进行网元软件安装？',
    onOk() {
      fnToStepName('NeInfoSoftwareInstall');
    },
  });
}

onMounted(() => {
  // 初始字典数据
  Promise.allSettled([
    getDict('ne_host_type'),
    getDict('ne_host_groupId'),
    getDict('ne_host_authMode'),
  ])
    .then(resArr => {
      if (resArr[0].status === 'fulfilled') {
        dict.neHostType = resArr[0].value;
      }
      if (resArr[1].status === 'fulfilled') {
        dict.neHostGroupId = resArr[1].value;
      }
      if (resArr[2].status === 'fulfilled') {
        dict.neHostAuthMode = resArr[2].value;
      }
    })
    .finally(() => {
      if (stepState.neInfo.id) {
        Object.assign(modalState.from, stepState.neInfo);
      } else {
        modalState.from.ip = stepState.neHost.addr;
        Object.assign(modalState.from.hosts[0], stepState.neHost);
        Object.assign(modalState.from.hosts[1], {
          addr: modalState.from.ip,
          user: 'admin',
          password: 'admin',
        });
      }
    });
});
</script>

<template>
  <div class="ne">
    <a-form
      name="modalStateFrom"
      layout="horizontal"
      :label-col="{ span: 6 }"
      :labelWrap="true"
    >
      <a-row :gutter="16">
        <a-col :lg="12" :md="12" :xs="24">
          <a-form-item
            :label="t('views.configManage.neManage.neType')"
            name="neType"
            v-bind="modalStateFrom.validateInfos.neType"
          >
            <a-auto-complete
              v-model:value="modalState.from.neType"
              :options="NE_TYPE_LIST.map(v => ({ value: v }))"
              @change="fnNeTypeChange"
            >
              <a-input
                allow-clear
                :placeholder="t('common.inputPlease')"
                :maxlength="32"
              >
                <template #prefix>
                  <a-tooltip placement="topLeft">
                    <template #title>
                      {{ t('views.configManage.neManage.neTypeTip') }}
                    </template>
                    <InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
                  </a-tooltip>
                </template>
              </a-input>
            </a-auto-complete>
          </a-form-item>
        </a-col>
        <a-col :lg="12" :md="12" :xs="24">
          <a-form-item
            :label="t('views.configManage.neManage.pvflag')"
            name="pvFlag"
            v-bind="modalStateFrom.validateInfos.pvFlag"
          >
            <a-select
              v-model:value="modalState.from.pvFlag"
              default-value="PNF"
            >
              <a-select-opt-group :label="t('views.configManage.neManage.pnf')">
                <a-select-option value="PNF">PNF</a-select-option>
              </a-select-opt-group>
              <a-select-opt-group :label="t('views.configManage.neManage.vnf')">
                <a-select-option value="VNF">VNF</a-select-option>
              </a-select-opt-group>
            </a-select>
          </a-form-item>
        </a-col>
      </a-row>

      <a-row :gutter="16">
        <a-col :lg="12" :md="12" :xs="24">
          <a-form-item
            :label="t('views.configManage.neManage.neId')"
            name="neId"
            v-bind="modalStateFrom.validateInfos.neId"
          >
            <a-input
              v-model:value="modalState.from.neId"
              allow-clear
              :placeholder="t('common.inputPlease')"
              :maxlength="32"
            ></a-input>
          </a-form-item>
        </a-col>
        <a-col :lg="12" :md="12" :xs="24">
          <a-form-item
            :label="t('views.configManage.neManage.neName')"
            name="neName"
            v-bind="modalStateFrom.validateInfos.neName"
          >
            <a-input
              v-model:value="modalState.from.neName"
              allow-clear
              :placeholder="t('common.inputPlease')"
              :maxlength="64"
            >
            </a-input>
          </a-form-item>
        </a-col>
      </a-row>

      <a-row :gutter="16">
        <a-col :lg="12" :md="12" :xs="24">
          <a-form-item
            :label="t('views.configManage.neManage.ip')"
            name="ip"
            v-bind="modalStateFrom.validateInfos.ip"
          >
            <a-input
              v-model:value="modalState.from.ip"
              allow-clear
              :placeholder="t('common.inputPlease')"
              :maxlength="128"
              @change="fnNeIPChange"
            >
              <template #prefix>
                <a-tooltip placement="topLeft">
                  <template #title>
                    <div>
                      {{ t('views.ne.neInfo.ipAddr') }}
                    </div>
                  </template>
                  <InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
                </a-tooltip>
              </template>
            </a-input>
          </a-form-item>
        </a-col>
        <a-col :lg="12" :md="12" :xs="24">
          <a-form-item
            :label="t('views.configManage.neManage.port')"
            name="port"
            v-bind="modalStateFrom.validateInfos.port"
          >
            <a-input-number
              v-model:value="modalState.from.port"
              style="width: 100%"
              :min="1"
              :max="65535"
              placeholder="<=65535"
            >
              <template #prefix>
                <a-tooltip placement="topLeft">
                  <template #title>
                    <div>{{ t('views.configManage.neManage.portTip') }}</div>
                  </template>
                  <InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
                </a-tooltip>
              </template>
            </a-input-number>
          </a-form-item>
        </a-col>
      </a-row>

      <a-form-item
        :label="t('views.configManage.neManage.uid')"
        name="rmUid"
        v-bind="modalStateFrom.validateInfos.rmUid"
        :label-col="{ span: 3 }"
        :labelWrap="true"
      >
        <a-input
          v-model:value="modalState.from.rmUid"
          allow-clear
          :placeholder="t('common.inputPlease')"
          :maxlength="40"
        >
          <template #prefix>
            <a-tooltip placement="topLeft">
              <template #title>
                <div>
                  {{ t('views.ne.neInfo.rmUID') }}
                </div>
              </template>
              <InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
            </a-tooltip>
          </template>
        </a-input>
      </a-form-item>

      <a-divider orientation="left">
        {{ t('views.ne.neInfo.hostConfig') }}
      </a-divider>

      <!-- 主机连接配置 -->
      <a-collapse class="collapse" ghost>
        <a-collapse-panel
          v-for="host in modalState.from.hosts"
          :key="host.title"
          :header="`${host.hostType.toUpperCase()} ${host.port}`"
        >
          <a-row :gutter="16">
            <a-col :lg="12" :md="12" :xs="24">
              <a-form-item :label="t('views.ne.neHost.addr')">
                <a-input
                  v-model:value="host.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">
                <a-input-number
                  v-model:value="host.port"
                  :min="10"
                  :max="65535"
                  :step="1"
                  style="width: 100%"
                ></a-input-number>
              </a-form-item>
            </a-col>
          </a-row>

          <a-row :gutter="16">
            <a-col :lg="12" :md="12" :xs="24">
              <a-form-item :label="t('views.ne.neHost.user')">
                <a-input
                  v-model:value="host.user"
                  allow-clear
                  :maxlength="50"
                  :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="host.authMode"
                  default-value="0"
                  :options="dict.neHostAuthMode"
                  :disabled="host.hostType === 'telnet'"
                >
                </a-select>
              </a-form-item>
            </a-col>
          </a-row>

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

          <template v-if="host.authMode === '1'">
            <a-form-item
              :label="t('views.ne.neHost.privateKey')"
              :label-col="{ span: 3 }"
              :label-wrap="true"
            >
              <a-textarea
                v-model:value="host.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="host.passPhrase"
                :maxlength="128"
                :placeholder="t('common.inputPlease')"
              >
              </a-input-password>
            </a-form-item>
          </template>

          <a-form-item
            :label="t('views.ne.neHost.remark')"
            :label-col="{ span: 3 }"
            :label-wrap="true"
          >
            <a-textarea
              v-model:value="host.remark"
              :auto-size="{ minRows: 1, maxRows: 6 }"
              :maxlength="450"
              :show-count="true"
              :placeholder="t('common.inputPlease')"
            />
          </a-form-item>

          <a-form-item
            :label="t('views.ne.neHost.test')"
            name="test"
            :label-col="{ span: 3 }"
            :label-wrap="true"
          >
            <a-button
              type="primary"
              shape="round"
              @click="fnHostTest(host)"
              :loading="modalState.confirmLoading"
            >
              <template #icon><LinkOutlined /></template>
            </a-button>

            <a-button
              type="link"
              @click="fnHostAuthorized(host)"
              :loading="modalState.confirmLoading"
              v-if="host.hostType === 'ssh' && host.authMode !== '2'"
            >
              免密授权
            </a-button>
          </a-form-item>
        </a-collapse-panel>
      </a-collapse>
    </a-form>

    <div class="ne-oper">
      <a-space direction="horizontal" :size="18">
        <a-button @click="fnStepPrev()"> 上一步 </a-button>

        <a-button
          type="primary"
          @click="fnModalOk()"
          :loading="modalState.confirmLoading"
        >
          保存信息
        </a-button>

        <a-button
          type="default"
          @click="fnStepNext()"
          :disabled="!modalState.stepNext"
        >
          下一步
        </a-button>
      </a-space>
    </div>
  </div>
</template>

<style lang="less" scoped>
.ne {
  padding-top: 12px;

  &-oper {
    padding-top: 24px;
    text-align: end;
  }
}
</style>
