<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 { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { NE_TYPE_LIST } from '@/constants/ne-constants';
import { regExpIPv4, regExpIPv6 } from '@/utils/regular-utils';
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: '',
    neType: '',
    neName: '',
    ip: '',
    port: 33030,
    pvFlag: 'PNF',
    rmUid: '4400HXAMF001',
    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: 'admin',
        authMode: '0',
        password: 'admin',
        remark: '',
      },
    ],
  },
  confirmLoading: false,
});

/**对话框内表单属性和校验规则 */
const modalStateFrom = Form.useForm(
  modalState.from,
  reactive({
    neType: [
      {
        required: true,
        message: t('views.ne.common.neTypePlease'),
      },
    ],
    neId: [
      {
        required: true,
        message: t('views.ne.common.neIdPlease'),
      },
    ],
    ip: [
      {
        required: true,
        validator: modalStateFromEqualIPV4AndIPV6,
      },
    ],
  })
);

/**表单验证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 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 = t('views.ne.neQuickSetup.configAddTitle');
      let confirmContent = t('views.ne.neQuickSetup.configAddTip');
      if (isUpdate) {
        confirmTitle = t('views.ne.neQuickSetup.configUpdateTitle');
        confirmContent = t('views.ne.neQuickSetup.configUpdateTip');
      }
      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: () => {
          from.rmUid = `4400HX${from.neType}${from.neId}`; // 4400HX1AMF001
          from.neName = `${from.neType}_${from.neId}`; // AMF_001
          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: res.msg,
                  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: modalState.from.ip,
      port: 5002,
      user: 'admin',
      authMode: '0',
      password: 'admin',
      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: t('views.ne.neQuickSetup.stepPrevTip'),
    onOk() {
      fnRestStepState();
      fnToStepName('Start');
    },
  });
}

/**下一步操作 */
function fnStepNext() {
  if (!modalState.stepNext) return;
  Modal.confirm({
    title: t('common.tipTitle'),
    content: t('views.ne.neQuickSetup.configStepNext'),
    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="6" :md="6" :xs="24" :offset="6">
          <a-form-item
            :label="t('views.ne.common.neType')"
            name="neType"
            v-bind="modalStateFrom.validateInfos.neType"
          >
            <a-auto-complete
              v-model:value="modalState.from.neType"
              :options="
                NE_TYPE_LIST.filter(s => s !== 'OMC').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.ne.common.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="6" :md="6" :xs="24">
          <a-form-item
            :label="t('views.ne.common.neId')"
            name="neId"
            v-bind="modalStateFrom.validateInfos.neId"
          >
            <a-input
              v-model:value="modalState.from.neId"
              allow-clear
              :placeholder="t('common.inputPlease')"
              :maxlength="24"
            >
              <template #prefix>
                <a-tooltip placement="topLeft">
                  <template #title>
                    {{ t('views.ne.common.neIdTip') }}
                  </template>
                  <InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
                </a-tooltip>
              </template>
            </a-input>
          </a-form-item>
        </a-col>
      </a-row>

      <a-row :gutter="16">
        <a-col :lg="6" :md="6" :xs="24" :offset="6">
          <a-form-item
            :label="t('views.ne.common.ipAddr')"
            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"
              :disabled="true"
            >
              <template #prefix>
                <a-tooltip placement="topLeft">
                  <template #title>
                    <div>
                      {{ t('views.ne.common.ipAddrTip') }}
                    </div>
                  </template>
                  <InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
                </a-tooltip>
              </template>
            </a-input>
          </a-form-item>
        </a-col>
        <a-col :lg="6" :md="6" :xs="24">
          <a-form-item
            :label="t('views.ne.common.port')"
            name="port"
            v-bind="modalStateFrom.validateInfos.port"
          >
            <a-input-number
              v-model:value="modalState.from.port"
              style="width: 100%"
              :min="1"
              :max="65535"
              :maxlength="5"
              placeholder="<=65535"
            >
              <template #prefix>
                <a-tooltip placement="topLeft">
                  <template #title>
                    <div>{{ t('views.ne.common.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>

    <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"
          ghost
          @click="fnModalOk()"
          :loading="modalState.confirmLoading"
        >
          {{ t('views.ne.neQuickSetup.stepSave') }}
        </a-button>

        <a-button
          type="primary"
          @click="fnStepNext()"
          :disabled="!modalState.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>
